Mercurial > touhou
changeset 423:d8630c086926
Replace Pyglet with our own Cython OpenGL wrapper.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 16 Jul 2013 21:07:15 +0200 |
parents | 52829ebe2561 |
children | f4d76d3d6f2a |
files | pytouhou/lib/opengl.pxd pytouhou/lib/opengl.pyxbld pytouhou/ui/background.pxd pytouhou/ui/background.pyx pytouhou/ui/background.pyxbld pytouhou/ui/gamerenderer.py pytouhou/ui/gamerenderer.pyx pytouhou/ui/gamerenderer.pyxbld pytouhou/ui/gamerunner.py pytouhou/ui/gamerunner.pyx pytouhou/ui/gamerunner.pyxbld pytouhou/ui/renderer.pxd pytouhou/ui/renderer.pyx pytouhou/ui/renderer.pyxbld pytouhou/ui/texture.pyx pytouhou/ui/texture.pyxbld pytouhou/ui/window.py pytouhou/ui/window.pyx pytouhou/ui/window.pyxbld pytouhou/utils/matrix.pxd pytouhou/utils/matrix.pyx setup.py |
diffstat | 19 files changed, 365 insertions(+), 135 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/pytouhou/lib/opengl.pxd @@ -0,0 +1,108 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2013 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +## +## 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. +## + +cdef extern from 'GL/gl.h': + ctypedef unsigned int GLuint + ctypedef int GLint + ctypedef float GLfloat + ctypedef float GLclampf + ctypedef char GLboolean + ctypedef char GLchar + ctypedef unsigned int GLsizei + ctypedef unsigned int GLsizeiptr + ctypedef unsigned int GLbitfield + ctypedef void GLvoid + + ctypedef enum GLenum: + GL_ARRAY_BUFFER + GL_STATIC_DRAW + GL_DYNAMIC_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 + GL_DEPTH_TEST + GL_QUADS + + GL_TEXTURE_MIN_FILTER + GL_TEXTURE_MAG_FILTER + GL_LINEAR + GL_BGRA + GL_RGBA + GL_RGB + GL_LUMINANCE + GL_UNSIGNED_SHORT_5_6_5 + GL_UNSIGNED_SHORT_4_4_4_4_REV + + GL_COLOR_BUFFER_BIT + GL_SCISSOR_TEST + GL_MODELVIEW + GL_FOG + + GL_DEPTH_BUFFER_BIT + GL_PROJECTION + GL_FOG_MODE + GL_FOG_START + GL_FOG_END + GL_FOG_COLOR + + GL_BLEND + GL_PERSPECTIVE_CORRECTION_HINT + GL_FOG_HINT + GL_NICEST + GL_COLOR_ARRAY + GL_VERTEX_ARRAY + GL_TEXTURE_COORD_ARRAY + + void glVertexPointer(GLint size, GLenum type_, GLsizei stride, GLvoid *pointer) + void glTexCoordPointer(GLint size, GLenum type_, GLsizei stride, GLvoid *pointer) + void glColorPointer(GLint size, GLenum type_, GLsizei stride, GLvoid *pointer) + void glVertexAttribPointer(GLuint index, GLint size, GLenum type_, GLboolean normalized, GLsizei stride, const GLvoid *pointer) + void glEnableVertexAttribArray(GLuint index) + + void glBlendFunc(GLenum sfactor, GLenum dfactor) + void glDrawArrays(GLenum mode, GLint first, GLsizei count) + void glDrawElements(GLenum mode, GLsizei count, GLenum type_, const GLvoid *indices) + void glEnable(GLenum cap) + void glDisable(GLenum cap) + + void glGenBuffers(GLsizei n, GLuint * buffers) + void glDeleteBuffers(GLsizei n, const GLuint * buffers) + void glBindBuffer(GLenum target, GLuint buffer_) + void glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) + + void glGenTextures(GLsizei n, GLuint *textures) + void glBindTexture(GLenum target, GLuint texture) + void glTexParameteri(GLenum target, GLenum pname, GLint param) + void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format_, GLenum type_, const GLvoid *data) + + void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) #XXX + void glClear(GLbitfield mask) + void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) + void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) + void glMatrixMode(GLenum mode) + void glLoadIdentity() + void glLoadMatrixf(const GLfloat * m) + + void glFogi(GLenum pname, GLint param) + void glFogf(GLenum pname, GLfloat param) + void glFogfv(GLenum pname, const GLfloat * params) + + void glHint(GLenum target, GLenum mode) + void glEnableClientState(GLenum cap)
new file mode 100644 --- /dev/null +++ b/pytouhou/lib/opengl.pyxbld @@ -0,0 +1,30 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2013 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +## +## 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. +## + +""" Build instructions for the OpenGL module. """ + +from distutils.extension import Extension +from subprocess import check_output + +COMMAND = 'pkg-config' +LIBRARIES = ['gl'] + +def make_ext(modname, pyxfilename): + """ Compile and link with the corrects options. """ + compile_args = check_output([COMMAND, '--cflags'] + LIBRARIES).split() + link_args = check_output([COMMAND, '--libs'] + LIBRARIES).split() + return Extension(name=modname, + sources=[pyxfilename], + extra_compile_args=compile_args, + extra_link_args=link_args)
new file mode 100644 --- /dev/null +++ b/pytouhou/ui/background.pxd @@ -0,0 +1,15 @@ +cdef struct Vertex: + float x, y, z + float u, v + unsigned char r, g, b, a + + +cdef class BackgroundRenderer: + cdef public texture_manager + cdef object texture_key + cdef unsigned short blendfunc, nb_vertices + cdef Vertex *vertex_buffer + cdef unsigned int use_fixed_pipeline, vbo + + cpdef render_background(self) + cpdef prerender(self, background)
new file mode 100644 --- /dev/null +++ b/pytouhou/ui/background.pyx @@ -0,0 +1,101 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2013 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +## +## 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. +## + +from libc.stdlib cimport malloc, free, realloc + +from pytouhou.lib.opengl cimport \ + (glVertexPointer, glTexCoordPointer, glColorPointer, + glVertexAttribPointer, glEnableVertexAttribArray, glBlendFunc, + glBindTexture, glBindBuffer, glBufferData, GL_ARRAY_BUFFER, + GL_STATIC_DRAW, GL_UNSIGNED_BYTE, GL_FLOAT, GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_TEXTURE_2D, glGenBuffers, + glEnable, glDisable, GL_DEPTH_TEST, glDrawArrays, GL_QUADS) + +from .sprite cimport get_sprite_rendering_data + + +cdef class BackgroundRenderer: + def __cinit__(self): + # Allocate buffers + self.vertex_buffer = <Vertex*> malloc(65536 * sizeof(Vertex)) + + + def __dealloc__(self): + free(self.vertex_buffer) + + + def __init__(self, texture_manager, use_fixed_pipeline): + self.texture_manager = texture_manager + self.use_fixed_pipeline = use_fixed_pipeline + + if not use_fixed_pipeline: + glGenBuffers(1, &self.vbo) + + + cpdef 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) + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &self.vertex_buffer[0].r) + else: + glBindBuffer(GL_ARRAY_BUFFER, self.vbo) + + #TODO: find a way to use offsetof() instead of those ugly hardcoded values. + glVertexAttribPointer(0, 3, GL_FLOAT, False, sizeof(Vertex), <void*>0) + glEnableVertexAttribArray(0) + glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>12) + glEnableVertexAttribArray(1) + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>20) + glEnableVertexAttribArray(2) + + glEnable(GL_DEPTH_TEST) + 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(self, background): + cdef float ox, oy, oz, ox2, oy2, oz2 + cdef unsigned short nb_vertices = 0 + cdef Vertex* vertex_buffer + + vertex_buffer = self.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] = Vertex(x1 + ox + ox2, y1 + oy + oy2, z1 + oz + oz2, left, bottom, r, g, b, a) + vertex_buffer[nb_vertices+1] = Vertex(x2 + ox + ox2, y2 + oy + oy2, z2 + oz + oz2, right, bottom, r, g, b, a) + vertex_buffer[nb_vertices+2] = Vertex(x3 + ox + ox2, y3 + oy + oy2, z3 + oz + oz2, right, top, r, g, b, a) + vertex_buffer[nb_vertices+3] = Vertex(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.vertex_buffer = <Vertex*> realloc(vertex_buffer, nb_vertices * sizeof(Vertex)) + + if not self.use_fixed_pipeline: + glBindBuffer(GL_ARRAY_BUFFER, self.vbo) + glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(Vertex), &self.vertex_buffer[0], GL_STATIC_DRAW) + glBindBuffer(GL_ARRAY_BUFFER, 0)
new file mode 120000 --- /dev/null +++ b/pytouhou/ui/background.pyxbld @@ -0,0 +1,1 @@ +../lib/opengl.pyxbld \ No newline at end of file
rename from pytouhou/ui/gamerenderer.py rename to pytouhou/ui/gamerenderer.pyx --- a/pytouhou/ui/gamerenderer.py +++ b/pytouhou/ui/gamerenderer.pyx @@ -13,16 +13,18 @@ ## +from libc.stdlib cimport malloc, free + from itertools import chain -from pyglet.gl import (glClear, glMatrixMode, glLoadIdentity, glLoadMatrixf, - glDisable, glEnable, glFogi, glFogf, glFogfv, - GL_DEPTH_BUFFER_BIT, 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) +from pytouhou.lib.opengl cimport \ + (glClear, glMatrixMode, glLoadIdentity, glLoadMatrixf, glDisable, + glEnable, glFogi, glFogf, glFogfv, GL_DEPTH_BUFFER_BIT, + 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) -from pytouhou.utils.matrix import Matrix -from pytouhou.utils.maths import setup_camera +from pytouhou.utils.matrix cimport Matrix, matrix_to_floats +from pytouhou.utils.maths cimport setup_camera from .renderer import Renderer @@ -34,6 +36,8 @@ class GameRenderer(Renderer): def render(self): + cdef float* fog_data + glClear(GL_DEPTH_BUFFER_BIT) back = self.background @@ -46,7 +50,7 @@ class GameRenderer(Renderer): if game is not None and game.spellcard_effect is not None: if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(self.game_mvp.get_c_data()) + glLoadMatrixf(matrix_to_floats(self.game_mvp)) glDisable(GL_FOG) else: self.game_shader.bind() @@ -72,16 +76,23 @@ class GameRenderer(Renderer): view = setup_camera(dx, dy, dz) model_view_projection = model * view * self.proj mvp = model_view_projection.get_c_data() + mvp_cython = matrix_to_floats(model_view_projection) if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(mvp) + glLoadMatrixf(mvp_cython) glEnable(GL_FOG) 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.)) + fog_data = <float*>malloc(4 * sizeof(float)) + fog_data[0] = fog_r / 255. + fog_data[1] = fog_g / 255. + fog_data[2] = fog_b / 255. + fog_data[3] = 1. + glFogfv(GL_FOG_COLOR, fog_data) + free(fog_data) else: self.background_shader.bind() self.background_shader.uniform_matrixf('mvp', mvp) @@ -90,14 +101,14 @@ class GameRenderer(Renderer): self.background_shader.uniformf('fog_end', fog_end) self.background_shader.uniformf('fog_color', fog_r / 255., fog_g / 255., fog_b / 255., 1.) - self.render_background() + self.background_renderer.render_background() else: glClear(GL_COLOR_BUFFER_BIT) if game is not None: if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(self.game_mvp.get_c_data()) + glLoadMatrixf(matrix_to_floats(self.game_mvp)) glDisable(GL_FOG) else: self.game_shader.bind()
new file mode 120000 --- /dev/null +++ b/pytouhou/ui/gamerenderer.pyxbld @@ -0,0 +1,1 @@ +../lib/opengl.pyxbld \ No newline at end of file
rename from pytouhou/ui/gamerunner.py rename to pytouhou/ui/gamerunner.pyx --- a/pytouhou/ui/gamerunner.py +++ b/pytouhou/ui/gamerunner.pyx @@ -14,25 +14,28 @@ from pytouhou.lib import sdl -from pyglet.gl import (glMatrixMode, glEnable, glDisable, glViewport, - glScissor, glLoadMatrixf, glGenBuffers, glDeleteBuffers, - GL_MODELVIEW, GL_PROJECTION, GL_FOG, GL_SCISSOR_TEST) +from pytouhou.lib.opengl cimport \ + (glMatrixMode, glEnable, glDisable, glViewport, glScissor, + glLoadMatrixf, glGenBuffers, glDeleteBuffers, GL_MODELVIEW, + GL_FOG, GL_SCISSOR_TEST) from pytouhou.utils.helpers import get_logger -from pytouhou.utils.maths import perspective, setup_camera, ortho_2d +from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d +from pytouhou.utils.matrix cimport matrix_to_floats from .gamerenderer import GameRenderer +from .background import BackgroundRenderer from .music import MusicPlayer, SFXPlayer, NullPlayer from .shaders.eosd import GameShader, BackgroundShader -from ctypes import c_uint, byref - logger = get_logger(__name__) class GameRunner(GameRenderer): def __init__(self, window, resource_loader, replay=None, skip=False): + self.use_fixed_pipeline = window.use_fixed_pipeline #XXX + GameRenderer.__init__(self, resource_loader) self.window = window @@ -40,7 +43,6 @@ class GameRunner(GameRenderer): self.skip = skip self.keystate = 0 - self.use_fixed_pipeline = window.use_fixed_pipeline #XXX self.width = window.width #XXX self.height = window.height #XXX @@ -49,10 +51,6 @@ class GameRunner(GameRenderer): self.background_shader = BackgroundShader() self.interface_shader = self.game_shader - vbo_array = (c_uint * 2)() - glGenBuffers(2, vbo_array) - self.vbo, self.back_vbo = vbo_array - def load_game(self, game=None, background=None, bgms=None, replay=None, save_keystates=None): self.game = game @@ -61,7 +59,8 @@ class GameRunner(GameRenderer): self.texture_manager.preload(game.resource_loader.instanced_anms.values()) if background: - self.prerender_background(background) + self.background_renderer = BackgroundRenderer(self.texture_manager, self.use_fixed_pipeline) + self.background_renderer.prerender(background) self.set_input(replay) if replay and replay.levels[game.stage - 1]: @@ -177,10 +176,11 @@ class GameRunner(GameRenderer): if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW) - glLoadMatrixf(self.interface_mvp.get_c_data()) + glLoadMatrixf(matrix_to_floats(self.interface_mvp)) glDisable(GL_FOG) else: self.interface_shader.bind() + #self.interface_shader.uniform_matrixf('mvp', matrix_to_floats(self.interface_mvp)) self.interface_shader.uniform_matrixf('mvp', self.interface_mvp.get_c_data()) glViewport(0, 0, self.width, self.height)
new file mode 120000 --- /dev/null +++ b/pytouhou/ui/gamerunner.pyxbld @@ -0,0 +1,1 @@ +../lib/opengl.pyxbld \ No newline at end of file
--- a/pytouhou/ui/renderer.pxd +++ b/pytouhou/ui/renderer.pxd @@ -4,19 +4,9 @@ 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 unsigned int vbo 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) - cpdef prerender_background(self, background)
--- a/pytouhou/ui/renderer.pyx +++ b/pytouhou/ui/renderer.pyx @@ -12,21 +12,19 @@ ## GNU General Public License for more details. ## -from libc.stdlib cimport malloc, free, realloc +from libc.stdlib cimport malloc, free from itertools import chain -import ctypes - from struct import pack -from pyglet.gl import (glVertexPointer, glTexCoordPointer, glColorPointer, - glVertexAttribPointer, glEnableVertexAttribArray, - glBlendFunc, glBindTexture, glDrawElements, - glBindBuffer, glBufferData, GL_ARRAY_BUFFER, - 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 pytouhou.lib.opengl cimport \ + (glVertexPointer, glTexCoordPointer, glColorPointer, + glVertexAttribPointer, glEnableVertexAttribArray, glBlendFunc, + glBindTexture, glDrawElements, glBindBuffer, glBufferData, + GL_ARRAY_BUFFER, GL_DYNAMIC_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, + glGenBuffers) from .sprite cimport get_sprite_rendering_data from .texture cimport TextureManager @@ -39,20 +37,21 @@ cdef class Renderer: def __cinit__(self): # Allocate buffers self.vertex_buffer = <Vertex*> malloc(MAX_ELEMENTS * sizeof(Vertex)) - self.background_vertex_buffer = <VertexFloat*> malloc(65536 * sizeof(Vertex)) def __dealloc__(self): free(self.vertex_buffer) - free(self.background_vertex_buffer) def __init__(self, resource_loader): self.texture_manager = TextureManager(resource_loader) + if not self.use_fixed_pipeline: + glGenBuffers(1, &self.vbo) + cpdef render_elements(self, elements): - cdef unsigned short nb_vertices = 0 + cdef unsigned short nb_vertices = 0, nb_indices, *new_indices indices_by_texture = {} @@ -86,85 +85,33 @@ cdef class Renderer: return if self.use_fixed_pipeline: - glVertexPointer(3, GL_INT, sizeof(Vertex), <long> &self.vertex_buffer[0].x) - glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), <long> &self.vertex_buffer[0].u) - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), <long> &self.vertex_buffer[0].r) + glVertexPointer(3, GL_INT, sizeof(Vertex), &self.vertex_buffer[0].x) + glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &self.vertex_buffer[0].u) + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &self.vertex_buffer[0].r) else: glBindBuffer(GL_ARRAY_BUFFER, self.vbo) - glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(Vertex), <long> &self.vertex_buffer[0], GL_DYNAMIC_DRAW) + glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(Vertex), &self.vertex_buffer[0], GL_DYNAMIC_DRAW) #TODO: find a way to use offsetof() instead of those ugly hardcoded values. - glVertexAttribPointer(0, 3, GL_INT, False, sizeof(Vertex), 0) + glVertexAttribPointer(0, 3, GL_INT, False, sizeof(Vertex), <void*>0) glEnableVertexAttribArray(0) - glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), 12) + glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>12) glEnableVertexAttribArray(1) - glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), 20) + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>20) glEnableVertexAttribArray(2) for (texture_key, blendfunc), indices in indices_by_texture.items(): + + #TODO: find a more elegent way. nb_indices = len(indices) - indices = pack(str(nb_indices) + 'H', *indices) + new_indices = <unsigned short*> malloc(nb_indices * sizeof(unsigned short)) + for i in xrange(nb_indices): + new_indices[i] = indices[i] + glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) glBindTexture(GL_TEXTURE_2D, self.texture_manager[texture_key]) - glDrawElements(GL_TRIANGLES, nb_indices, GL_UNSIGNED_SHORT, indices) + glDrawElements(GL_TRIANGLES, nb_indices, GL_UNSIGNED_SHORT, new_indices) + free(new_indices) if not self.use_fixed_pipeline: glBindBuffer(GL_ARRAY_BUFFER, 0) - - - cpdef render_background(self): - if self.use_fixed_pipeline: - glVertexPointer(3, GL_FLOAT, sizeof(VertexFloat), <long> &self.background_vertex_buffer[0].x) - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexFloat), <long> &self.background_vertex_buffer[0].u) - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexFloat), <long> &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) - 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 = <VertexFloat*> 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), <long> &self.background_vertex_buffer[0], GL_STATIC_DRAW) - glBindBuffer(GL_ARRAY_BUFFER, 0)
new file mode 120000 --- /dev/null +++ b/pytouhou/ui/renderer.pyxbld @@ -0,0 +1,1 @@ +../lib/opengl.pyxbld \ No newline at end of file
--- a/pytouhou/ui/texture.pyx +++ b/pytouhou/ui/texture.pyx @@ -12,17 +12,16 @@ ## GNU General Public License for more details. ## -from pyglet.gl import (glTexParameteri, GL_TEXTURE_MIN_FILTER, - GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_BGRA, GL_RGBA, - GL_RGB, GL_LUMINANCE, GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4_REV, - glGenTextures, glBindTexture, glTexImage2D, - GL_TEXTURE_2D) -from ctypes import c_uint, byref +from pytouhou.lib.opengl cimport \ + (glTexParameteri, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, + GL_LINEAR, GL_BGRA, GL_RGBA, GL_RGB, GL_LUMINANCE, GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4_REV, + glGenTextures, glBindTexture, glTexImage2D, GL_TEXTURE_2D, GLuint) + from pytouhou.lib.sdl import load_png, create_rgb_surface -import os +from pytouhou.formats.thtx import Texture #TODO: perhaps define that elsewhere? -from pytouhou.formats.thtx import Texture #TODO: perhaps define that elsewhere? +import os cdef class TextureManager: @@ -65,6 +64,8 @@ cdef class TextureManager: def load_texture(self, key): + cdef GLuint id_ + if not isinstance(key, Texture): first_name, secondary_name = key key = self.load_png_texture(first_name, secondary_name) @@ -92,9 +93,8 @@ cdef class TextureManager: else: raise Exception('Unknown texture type') - id_ = c_uint() - glGenTextures(1, byref(id_)) - glBindTexture(GL_TEXTURE_2D, id_.value) + glGenTextures(1, &id_) + glBindTexture(GL_TEXTURE_2D, id_) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) @@ -103,6 +103,6 @@ cdef class TextureManager: key.width, key.height, 0, format_, type_, - key.data) + <char*>key.data) - return id_.value + return id_
new file mode 120000 --- /dev/null +++ b/pytouhou/ui/texture.pyxbld @@ -0,0 +1,1 @@ +../lib/opengl.pyxbld \ No newline at end of file
rename from pytouhou/ui/window.py rename to pytouhou/ui/window.pyx --- a/pytouhou/ui/window.py +++ b/pytouhou/ui/window.pyx @@ -15,10 +15,10 @@ from pytouhou.lib import sdl -from pyglet.gl import (glEnable, glHint, glEnableClientState, GL_TEXTURE_2D, - GL_BLEND, GL_PERSPECTIVE_CORRECTION_HINT, GL_FOG_HINT, - GL_NICEST, GL_COLOR_ARRAY, GL_VERTEX_ARRAY, - GL_TEXTURE_COORD_ARRAY) +from pytouhou.lib.opengl cimport \ + (glEnable, glHint, glEnableClientState, GL_TEXTURE_2D, GL_BLEND, + GL_PERSPECTIVE_CORRECTION_HINT, GL_FOG_HINT, GL_NICEST, + GL_COLOR_ARRAY, GL_VERTEX_ARRAY, GL_TEXTURE_COORD_ARRAY) class Clock(object):
new file mode 120000 --- /dev/null +++ b/pytouhou/ui/window.pyxbld @@ -0,0 +1,1 @@ +../lib/opengl.pyxbld \ No newline at end of file
--- a/pytouhou/utils/matrix.pxd +++ b/pytouhou/utils/matrix.pxd @@ -1,5 +1,8 @@ +cdef float* matrix_to_floats(Matrix self) + cdef class Matrix: cdef public list data + cdef float *c_data cpdef flip(self) cpdef scale(self, x, y, z)
--- a/pytouhou/utils/matrix.pyx +++ b/pytouhou/utils/matrix.pyx @@ -14,9 +14,21 @@ from libc.math cimport sin, cos from ctypes import c_float +from libc.stdlib cimport malloc, free + + +cdef float* matrix_to_floats(Matrix self): + for i in xrange(4): + for j in xrange(4): + self.c_data[i*4+j] = self.data[i][j] + return self.c_data cdef class Matrix: + def __cinit__(self): + self.c_data = <float*>malloc(16 * sizeof(float)) + + def __init__(self, data=None): self.data = data or [[1, 0, 0, 0], [0, 1, 0, 0], @@ -24,6 +36,10 @@ cdef class Matrix: [0, 0, 0, 1]] + def __dealloc__(self): + free(self.c_data) + + def __mul__(self, Matrix other): out = Matrix() d1 = self.data
--- a/setup.py +++ b/setup.py @@ -54,6 +54,9 @@ for directory, _, files in os.walk('pyto if extension_name == 'pytouhou.lib.sdl': compile_args = check_output([COMMAND, '--cflags'] + LIBRARIES).split() link_args = check_output([COMMAND, '--libs'] + LIBRARIES).split() + elif extension_name.startswith('pytouhou.ui.'): #XXX + compile_args = check_output([COMMAND, '--cflags', 'gl']).split() + link_args = check_output([COMMAND, '--libs', 'gl']).split() else: compile_args = None link_args = None