# HG changeset patch # User Emmanuel Gil Peyrot # Date 1378499754 -7200 # Node ID 6e733ed817bd8ff9aeb423d84f027634248fbb82 # Parent 1b56d62250abf854b452677a005ebc73b888f1b7 Move every rendering function from gamerunner to gamerenderer. diff --git a/pytouhou/ui/background.pxd b/pytouhou/ui/background.pxd --- a/pytouhou/ui/background.pxd +++ b/pytouhou/ui/background.pxd @@ -11,6 +11,7 @@ cdef class BackgroundRenderer: cdef unsigned short blendfunc, nb_vertices cdef Vertex *vertex_buffer cdef unsigned int use_fixed_pipeline, vbo + cdef object background - cpdef render_background(self) - cpdef prerender(self, background) + cdef void render_background(self) + cdef void load(self, background) diff --git a/pytouhou/ui/background.pyx b/pytouhou/ui/background.pyx --- a/pytouhou/ui/background.pyx +++ b/pytouhou/ui/background.pyx @@ -42,7 +42,7 @@ cdef class BackgroundRenderer: glGenBuffers(1, &self.vbo) - cpdef render_background(self): + cdef void render_background(self): if self.use_fixed_pipeline: glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].x) glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].u) @@ -68,11 +68,13 @@ cdef class BackgroundRenderer: glBindBuffer(GL_ARRAY_BUFFER, 0) - cpdef prerender(self, background): + cdef void load(self, background): cdef float ox, oy, oz, ox2, oy2, oz2 cdef unsigned short nb_vertices = 0 cdef Vertex* vertex_buffer + self.background = background + vertex_buffer = self.vertex_buffer for ox, oy, oz, model_id, model in background.object_instances: diff --git a/pytouhou/ui/gamerenderer.pxd b/pytouhou/ui/gamerenderer.pxd --- a/pytouhou/ui/gamerenderer.pxd +++ b/pytouhou/ui/gamerenderer.pxd @@ -1,9 +1,16 @@ from pytouhou.utils.matrix cimport Matrix +from .background cimport BackgroundRenderer from .renderer cimport Renderer from .shader cimport Shader cdef class GameRenderer(Renderer): cdef Matrix game_mvp, interface_mvp, proj cdef Shader game_shader, background_shader, interface_shader + cdef BackgroundRenderer background_renderer - cdef object game, background, background_renderer #XXX + cdef void load_background(self, background) + cdef void start(self, game) + cdef void render(self, game) + cdef void render_game(self, game) + cdef void render_text(self, texts) + cdef void render_interface(self, interface, game_boss) diff --git a/pytouhou/ui/gamerenderer.pyx b/pytouhou/ui/gamerenderer.pyx --- a/pytouhou/ui/gamerenderer.pyx +++ b/pytouhou/ui/gamerenderer.pyx @@ -16,25 +16,64 @@ from itertools import chain from pytouhou.lib.opengl cimport \ (glClear, glMatrixMode, glLoadIdentity, glLoadMatrixf, glDisable, - glEnable, glFogi, glFogf, glFogfv, - GL_PROJECTION, GL_MODELVIEW, GL_FOG, GL_FOG_MODE, GL_LINEAR, - GL_FOG_START, GL_FOG_END, GL_FOG_COLOR, GL_COLOR_BUFFER_BIT, GLfloat) + glEnable, glFogi, glFogf, glFogfv, GL_PROJECTION, GL_MODELVIEW, + GL_FOG, GL_FOG_MODE, GL_LINEAR, GL_FOG_START, GL_FOG_END, + GL_FOG_COLOR, GL_COLOR_BUFFER_BIT, GLfloat, glViewport, glScissor, + GL_SCISSOR_TEST, GL_DEPTH_BUFFER_BIT) -from pytouhou.utils.maths cimport setup_camera +from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d +from .shaders.eosd import GameShader, BackgroundShader + +from collections import namedtuple +Rect = namedtuple('Rect', 'x y w h') +Color = namedtuple('Color', 'r g b a') cdef class GameRenderer(Renderer): - def __init__(self, resource_loader): + def __init__(self, resource_loader, use_fixed_pipeline): + self.use_fixed_pipeline = use_fixed_pipeline #XXX + Renderer.__init__(self, resource_loader) + if not self.use_fixed_pipeline: + self.game_shader = GameShader() + self.background_shader = BackgroundShader() + self.interface_shader = self.game_shader - def render(self): + + cdef void load_background(self, background): + if background is not None: + self.background_renderer = BackgroundRenderer(self.use_fixed_pipeline) + self.background_renderer.load(background) + else: + self.background_renderer = None + + + cdef void start(self, game): + self.proj = perspective(30, float(game.width) / float(game.height), + 101010101./2010101., 101010101./10101.) + game_view = setup_camera(0, 0, 1) + self.game_mvp = game_view * self.proj + self.interface_mvp = ortho_2d(0., float(game.interface.width), float(game.interface.height), 0.) + + + cdef void render(self, game): + self.render_game(game) + self.render_text(game.texts + game.native_texts) + self.render_interface(game.interface, game.boss) + + + cdef void render_game(self, game): + cdef long game_x, game_y cdef float x, y, z, dx, dy, dz, fog_data[4], fog_start, fog_end cdef unsigned char fog_r, fog_g, fog_b cdef Matrix mvp - back = self.background - game = self.game + game_x, game_y = game.interface.game_pos + glViewport(game_x, game_y, game.width, game.height) + glClear(GL_DEPTH_BUFFER_BIT) + glScissor(game_x, game_y, game.width, game.height) + glEnable(GL_SCISSOR_TEST) if self.use_fixed_pipeline: glMatrixMode(GL_PROJECTION) @@ -50,7 +89,8 @@ cdef class GameRenderer(Renderer): self.game_shader.uniform_matrix('mvp', self.game_mvp) self.render_elements([game.spellcard_effect]) - elif back is not None: + elif self.background_renderer is not None: + back = self.background_renderer.background x, y, z = back.position_interpolator.values dx, dy, dz = back.position2_interpolator.values fog_b, fog_g, fog_r, fog_start, fog_end = back.fog_interpolator.values @@ -106,7 +146,7 @@ cdef class GameRenderer(Renderer): self.game_shader.bind() self.game_shader.uniform_matrix('mvp', self.game_mvp) - self.render_elements(enemy for enemy in game.enemies if enemy.visible) + self.render_elements([enemy for enemy in game.enemies if enemy.visible]) self.render_elements(game.effects) self.render_elements(chain(game.players_bullets, game.lasers_sprites(), @@ -115,3 +155,68 @@ cdef class GameRenderer(Renderer): self.render_elements(chain(game.bullets, game.lasers, game.cancelled_bullets, game.items, game.labels)) + + if game.msg_runner: + rect = Rect(48, 368, 288, 48) + color1 = Color(0, 0, 0, 192) + color2 = Color(0, 0, 0, 128) + self.render_quads([rect], [(color1, color1, color2, color2)], 0) + + glDisable(GL_SCISSOR_TEST) + + + cdef void render_text(self, texts): + if self.font_manager is None: + return + + labels = [label for label in texts if label is not None] + self.font_manager.load(labels) + + black = Color(0, 0, 0, 255) + + for label in labels: + if label is None: + continue + + rect = Rect(label.x, label.y, label.width, label.height) + gradient = [Color(*color, a=label.alpha) for color in label.gradient] + + if label.shadow: + shadow_rect = Rect(label.x + 1, label.y + 1, label.width, label.height) + shadow = [black._replace(a=label.alpha)] * 4 + self.render_quads([shadow_rect, rect], [shadow, gradient], label.texture) + else: + self.render_quads([rect], [gradient], label.texture) + + + cdef void render_interface(self, interface, game_boss): + elements = [] + + if self.use_fixed_pipeline: + glMatrixMode(GL_MODELVIEW) + glLoadMatrixf(self.interface_mvp.data) + glDisable(GL_FOG) + else: + self.interface_shader.bind() + self.interface_shader.uniform_matrix('mvp', self.interface_mvp) + glViewport(0, 0, interface.width, interface.height) + + items = [item for item in interface.items if item.anmrunner and item.anmrunner.running] + labels = interface.labels.values() + + if items: + # Redraw all the interface + elements.extend(items) + else: + # Redraw only changed labels + labels = [label for label in labels if label.changed] + + elements.extend(interface.level_start) + + if game_boss is not None: + elements.extend(interface.boss_items) + + elements.extend(labels) + self.render_elements(elements) + for label in labels: + label.changed = False diff --git a/pytouhou/ui/gamerunner.pyx b/pytouhou/ui/gamerunner.pyx --- a/pytouhou/ui/gamerunner.pyx +++ b/pytouhou/ui/gamerunner.pyx @@ -14,37 +14,23 @@ from pytouhou.lib cimport sdl -from pytouhou.lib.opengl cimport \ - (glMatrixMode, glEnable, glDisable, glViewport, glScissor, - glLoadMatrixf, glGenBuffers, glDeleteBuffers, GL_MODELVIEW, - GL_FOG, GL_SCISSOR_TEST, glClear, GL_DEPTH_BUFFER_BIT) - -from pytouhou.utils.helpers import get_logger -from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d - from .window cimport Window from .gamerenderer cimport GameRenderer -from .background import BackgroundRenderer from .music import MusicPlayer, SFXPlayer, NullPlayer -from .shaders.eosd import GameShader, BackgroundShader - -from collections import namedtuple -Rect = namedtuple('Rect', 'x y w h') -Color = namedtuple('Color', 'r g b a') - -logger = get_logger(__name__) -cdef class GameRunner(GameRenderer): +cdef class GameRunner: + cdef object game, background + cdef GameRenderer renderer cdef Window window cdef object replay_level, save_keystates cdef long width, height, keystate - cdef bint skip + cdef bint skip, use_fixed_pipeline def __init__(self, window, resource_loader, bint skip=False): self.use_fixed_pipeline = window.use_fixed_pipeline #XXX - GameRenderer.__init__(self, resource_loader) + self.renderer = GameRenderer(resource_loader, self.use_fixed_pipeline) self.window = window self.replay_level = None @@ -54,21 +40,13 @@ cdef class GameRunner(GameRenderer): self.width = window.width #XXX self.height = window.height #XXX - if not self.use_fixed_pipeline: - self.game_shader = GameShader() - self.background_shader = BackgroundShader() - self.interface_shader = self.game_shader - def load_game(self, game=None, background=None, bgms=None, replay=None, save_keystates=None): self.game = game self.background = background - self.texture_manager.load(game.resource_loader.instanced_anms.values()) - - if background: - self.background_renderer = BackgroundRenderer(self.use_fixed_pipeline) - self.background_renderer.prerender(background) + self.renderer.texture_manager.load(game.resource_loader.instanced_anms.values()) + self.renderer.load_background(background) self.set_input(replay) if replay and replay.levels[game.stage - 1]: @@ -98,16 +76,13 @@ cdef class GameRunner(GameRenderer): def start(self): - width = self.game.interface.width if self.game else 640 - height = self.game.interface.height if self.game else 480 - if (width, height) != (self.width, self.height): + cdef long width, height + width = self.game.interface.width if self.game is not None else 640 + height = self.game.interface.height if self.game is not None else 480 + if width != self.width or height != self.height: self.window.set_size(width, height) - self.proj = perspective(30, float(self.game.width) / float(self.game.height), - 101010101./2010101., 101010101./10101.) - game_view = setup_camera(0, 0, 1) - self.game_mvp = game_view * self.proj - self.interface_mvp = ortho_2d(0., float(self.width), float(self.height), 0.) + self.renderer.start(self.game) def finish(self): @@ -166,88 +141,7 @@ cdef class GameRunner(GameRenderer): self.save_keystates.append(keystate) self.game.run_iter(keystate) + self.game.interface.labels['framerate'].set_text('%.2ffps' % self.window.get_fps()) if not self.skip: - self.render_game() - self.render_text() - self.render_interface() + self.renderer.render(self.game) return True - - - def render_game(self): - # Switch to game projection - #TODO: move that to GameRenderer? - x, y = self.game.interface.game_pos - glViewport(x, y, self.game.width, self.game.height) - glClear(GL_DEPTH_BUFFER_BIT) - glScissor(x, y, self.game.width, self.game.height) - glEnable(GL_SCISSOR_TEST) - - GameRenderer.render(self) - - glDisable(GL_SCISSOR_TEST) - - if self.game.msg_runner: - rect = Rect(48, 368, 288, 48) - color1 = Color(0, 0, 0, 192) - color2 = Color(0, 0, 0, 128) - self.render_quads([rect], [(color1, color1, color2, color2)], 0) - - - def render_text(self): - if self.font_manager is None: - return - - labels = [label for label in self.game.texts + self.game.native_texts if label is not None] - self.font_manager.load(labels) - - black = Color(0, 0, 0, 255) - - for label in labels: - if label is None: - continue - - rect = Rect(label.x, label.y, label.width, label.height) - gradient = [Color(*color, a=label.alpha) for color in label.gradient] - - if label.shadow: - shadow_rect = Rect(label.x + 1, label.y + 1, label.width, label.height) - shadow = [black._replace(a=label.alpha)] * 4 - self.render_quads([shadow_rect, rect], [shadow, gradient], label.texture) - else: - self.render_quads([rect], [gradient], label.texture) - - - def render_interface(self): - elements = [] - interface = self.game.interface - interface.labels['framerate'].set_text('%.2ffps' % self.window.get_fps()) - - if self.use_fixed_pipeline: - glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(self.interface_mvp.data) - glDisable(GL_FOG) - else: - self.interface_shader.bind() - self.interface_shader.uniform_matrix('mvp', self.interface_mvp) - glViewport(0, 0, self.width, self.height) - - items = [item for item in interface.items if item.anmrunner and item.anmrunner.running] - labels = interface.labels.values() - - if items: - # Redraw all the interface - elements.extend(items) - else: - # Redraw only changed labels - labels = [label for label in labels if label.changed] - - elements.extend(interface.level_start) - - if self.game.boss: - elements.extend(interface.boss_items) - - elements.extend(labels) - self.render_elements(elements) - for label in labels: - label.changed = False -