# HG changeset patch # User Emmanuel Gil Peyrot # Date 1360693171 -3600 # Node ID 1c773544eaeb3e357f2bbdb6f44290bc8250a9cf # Parent 8d252cdb495fb7322160dcdc057528935d635ed1 Make the background use a single vbo and offsets, just like the 2D code. diff --git a/pytouhou/ui/background.pxd b/pytouhou/ui/background.pxd deleted file mode 100644 --- a/pytouhou/ui/background.pxd +++ /dev/null @@ -1,1 +0,0 @@ -cpdef object get_background_rendering_data(object background) diff --git a/pytouhou/ui/background.pyx b/pytouhou/ui/background.pyx deleted file mode 100644 --- a/pytouhou/ui/background.pyx +++ /dev/null @@ -1,53 +0,0 @@ -# -*- encoding: utf-8 -*- -## -## Copyright (C) 2011 Thibaut Girka -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published -## by the Free Software Foundation; version 3 only. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - -#TODO: lots of things - -from struct import pack -from itertools import chain - -from .sprite cimport get_sprite_rendering_data - -cpdef object get_background_rendering_data(object background): - cdef float x, y, z, ox, oy, oz, ox2, oy2, oz2 - cdef list vertices, uvs, colors - - #TODO: do not cache the results, and use view frustum culling - try: - return background._rendering_data - except AttributeError: - pass - - vertices = [] - uvs = [] - colors = [] - - for ox, oy, oz, model_id, model in background.object_instances: - for ox2, oy2, oz2, width_override, height_override, sprite in model: - #TODO: view frustum culling - key, (vertices2, (left, right, bottom, top), colors2) = get_sprite_rendering_data(sprite) - vertices.extend([(x + ox + ox2, y + oy + oy2, z + oz + oz2) - for x, y, z in vertices2]) - uvs.extend((left, bottom, right, bottom, right, top, left, top)) - colors.extend(colors2 * 4) - - nb_vertices = len(vertices) - vertices_s = pack(str(3 * nb_vertices) + 'f', *chain(*vertices)) - uvs_s = pack(str(2 * nb_vertices) + 'f', *uvs) - colors_s = pack(str(4 * nb_vertices) + 'B', *colors) - - background._rendering_data = [(key, (nb_vertices, vertices_s, uvs_s, colors_s))] - - return background._rendering_data - diff --git a/pytouhou/ui/gamerenderer.py b/pytouhou/ui/gamerenderer.py --- a/pytouhou/ui/gamerenderer.py +++ b/pytouhou/ui/gamerenderer.py @@ -43,6 +43,7 @@ class GameRenderer(Renderer): if game: # Preload textures self.texture_manager.preload(game.resource_loader.instanced_anms.values()) + self.prerender_background(background) def render(self): @@ -66,33 +67,33 @@ class GameRenderer(Renderer): self.render_elements([game.spellcard_effect]) elif back is not None: - if self.use_fixed_pipeline: - glEnable(GL_FOG) - else: - self.background_shader.bind() - fog_b, fog_g, fog_r, fog_start, fog_end = back.fog_interpolator.values 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 + + model = Matrix() + model.data[3] = [-x, -y, -z, 1] + view = self.setup_camera(dx, dy, dz) glFogi(GL_FOG_MODE, GL_LINEAR) glFogf(GL_FOG_START, fog_start) glFogf(GL_FOG_END, fog_end) glFogfv(GL_FOG_COLOR, (GLfloat * 4)(fog_r / 255., fog_g / 255., fog_b / 255., 1.)) - model = Matrix() - model.data[3] = [-x, -y, -z, 1] - view = self.setup_camera(dx, dy, dz) + if self.use_fixed_pipeline: + glEnable(GL_FOG) - if self.use_fixed_pipeline: model_view_projection = model * view * self.proj glMatrixMode(GL_MODELVIEW) glLoadMatrixf(model_view_projection.get_c_data()) else: + self.background_shader.bind() + model_view = model * view self.background_shader.uniform_matrixf('model_view', model_view.get_c_data()) self.background_shader.uniform_matrixf('projection', self.proj.get_c_data()) - self.render_background(back) + self.render_background() else: glClear(GL_COLOR_BUFFER_BIT) diff --git a/pytouhou/ui/gamerunner.py b/pytouhou/ui/gamerunner.py --- a/pytouhou/ui/gamerunner.py +++ b/pytouhou/ui/gamerunner.py @@ -57,7 +57,9 @@ class GameRunner(pyglet.window.Window, G self.background_shader = BackgroundShader() self.interface_shader = self.game_shader - self.vbo = c_uint(0) + vbo_array = (c_uint * 2)() + glGenBuffers(2, vbo_array) + self.vbo, self.back_vbo = vbo_array if game: self.load_game(game, background, replay) @@ -106,8 +108,6 @@ class GameRunner(pyglet.window.Window, G glEnableClientState(GL_COLOR_ARRAY) glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) - else: - glGenBuffers(1, byref(self.vbo)) self.proj = self.perspective(30, float(self.game.width) / float(self.game.height), 101010101./2010101., 101010101./10101.) @@ -129,7 +129,8 @@ class GameRunner(pyglet.window.Window, G self.update() if not self.use_fixed_pipeline: - glDeleteBuffers(1, byref(self.vbo)) + vbo_array = (c_uint * 2)(self.vbo, self.back_vbo) + glDeleteBuffers(2, vbo_array) def _event_text_symbol(self, ev): diff --git a/pytouhou/ui/renderer.pxd b/pytouhou/ui/renderer.pxd --- a/pytouhou/ui/renderer.pxd +++ b/pytouhou/ui/renderer.pxd @@ -4,12 +4,22 @@ cdef struct Vertex: unsigned char r, g, b, a +cdef struct VertexFloat: + float x, y, z + float u, v + unsigned char r, g, b, a + + cdef class Renderer: cdef public texture_manager cdef Vertex *vertex_buffer + cdef object texture_key + cdef unsigned short blendfunc, nb_vertices + cdef VertexFloat *background_vertex_buffer cpdef render_elements(self, elements) - cpdef render_background(self, back) + cpdef render_background(self) + cpdef prerender_background(self, background) cpdef ortho_2d(self, left, right, bottom, top) cpdef look_at(self, eye, center, up) cpdef perspective(self, fovy, aspect, zNear, zFar) diff --git a/pytouhou/ui/renderer.pyx b/pytouhou/ui/renderer.pyx --- a/pytouhou/ui/renderer.pyx +++ b/pytouhou/ui/renderer.pyx @@ -12,7 +12,7 @@ ## GNU General Public License for more details. ## -from libc.stdlib cimport malloc, free +from libc.stdlib cimport malloc, free, realloc from libc.math cimport tan from math import radians from itertools import chain @@ -25,13 +25,12 @@ from pyglet.gl import (glVertexPointer, glVertexAttribPointer, glEnableVertexAttribArray, glBlendFunc, glBindTexture, glDrawElements, glBindBuffer, glBufferData, GL_ARRAY_BUFFER, - GL_DYNAMIC_DRAW, GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, + GL_DYNAMIC_DRAW, GL_STATIC_DRAW, GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_INT, GL_FLOAT, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_TEXTURE_2D, GL_TRIANGLES, glEnable, glDisable, GL_DEPTH_TEST, glDrawArrays, GL_QUADS) from .sprite cimport get_sprite_rendering_data -from .background import get_background_rendering_data from .texture cimport TextureManager from pytouhou.utils.matrix cimport Matrix from pytouhou.utils.vector import Vector, normalize, cross, dot @@ -44,10 +43,12 @@ cdef class Renderer: def __cinit__(self): # Allocate buffers self.vertex_buffer = malloc(MAX_ELEMENTS * sizeof(Vertex)) + self.background_vertex_buffer = malloc(65536 * sizeof(Vertex)) def __dealloc__(self): free(self.vertex_buffer) + free(self.background_vertex_buffer) def __init__(self, resource_loader): @@ -112,25 +113,63 @@ cdef class Renderer: glBindBuffer(GL_ARRAY_BUFFER, 0) - cpdef render_background(self, back): + cpdef render_background(self): + if self.use_fixed_pipeline: + glVertexPointer(3, GL_FLOAT, sizeof(VertexFloat), &self.background_vertex_buffer[0].x) + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexFloat), &self.background_vertex_buffer[0].u) + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexFloat), &self.background_vertex_buffer[0].r) + else: + glBindBuffer(GL_ARRAY_BUFFER, self.back_vbo) + + #TODO: find a way to use offsetof() instead of those ugly hardcoded values. + glVertexAttribPointer(0, 3, GL_FLOAT, False, sizeof(VertexFloat), 0) + glEnableVertexAttribArray(0) + glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(VertexFloat), 12) + glEnableVertexAttribArray(1) + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(VertexFloat), 20) + glEnableVertexAttribArray(2) + glEnable(GL_DEPTH_TEST) - for (texture_key, blendfunc), (nb_vertices, vertices, uvs, colors) in get_background_rendering_data(back): - if self.use_fixed_pipeline: - glVertexPointer(3, GL_FLOAT, 0, vertices) - glTexCoordPointer(2, GL_FLOAT, 0, uvs) - glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors) - else: - glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, vertices) - glEnableVertexAttribArray(0) - glVertexAttribPointer(1, 2, GL_FLOAT, False, 0, uvs) - glEnableVertexAttribArray(1) - glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, 0, colors) - glEnableVertexAttribArray(2) - glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) - glBindTexture(GL_TEXTURE_2D, self.texture_manager[texture_key]) - glDrawArrays(GL_QUADS, 0, nb_vertices) + glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[self.blendfunc]) + glBindTexture(GL_TEXTURE_2D, self.texture_manager[self.texture_key]) + glDrawArrays(GL_QUADS, 0, self.nb_vertices) glDisable(GL_DEPTH_TEST) + if not self.use_fixed_pipeline: + glBindBuffer(GL_ARRAY_BUFFER, 0) + + + cpdef prerender_background(self, background): + cdef float ox, oy, oz, ox2, oy2, oz2 + cdef unsigned short nb_vertices = 0 + cdef VertexFloat* vertex_buffer + + vertex_buffer = self.background_vertex_buffer + + for ox, oy, oz, model_id, model in background.object_instances: + for ox2, oy2, oz2, width_override, height_override, sprite in model: + #TODO: view frustum culling + key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite) + (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4) = vertices + left, right, bottom, top = uvs + r, g, b, a = colors + + vertex_buffer[nb_vertices] = VertexFloat(x1 + ox + ox2, y1 + oy + oy2, z1 + oz + oz2, left, bottom, r, g, b, a) + vertex_buffer[nb_vertices+1] = VertexFloat(x2 + ox + ox2, y2 + oy + oy2, z2 + oz + oz2, right, bottom, r, g, b, a) + vertex_buffer[nb_vertices+2] = VertexFloat(x3 + ox + ox2, y3 + oy + oy2, z3 + oz + oz2, right, top, r, g, b, a) + vertex_buffer[nb_vertices+3] = VertexFloat(x4 + ox + ox2, y4 + oy + oy2, z4 + oz + oz2, left, top, r, g, b, a) + + nb_vertices += 4 + + self.texture_key, self.blendfunc = key + self.nb_vertices = nb_vertices + self.background_vertex_buffer = realloc(vertex_buffer, nb_vertices * sizeof(VertexFloat)) + + if not self.use_fixed_pipeline: + glBindBuffer(GL_ARRAY_BUFFER, self.back_vbo) + glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(VertexFloat), &self.background_vertex_buffer[0], GL_STATIC_DRAW) + glBindBuffer(GL_ARRAY_BUFFER, 0) + cpdef ortho_2d(self, left, right, bottom, top): mat = Matrix()