comparison pytouhou/ui/gamerenderer.pyx @ 222:5cac48b328ad

Refactor rendering code a bit. Move duplicated camera setup code to a new “setup_camera” method, and move common methods to a new “Renderer” module in order to make individual sprite rendering easier.
author Thibaut Girka <thib@sitedethib.com>
date Sun, 18 Dec 2011 20:47:48 +0100
parents 5c3600e0f0cd
children 98c64ffcbdff
comparison
equal deleted inserted replaced
221:5c3600e0f0cd 222:5cac48b328ad
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ## GNU General Public License for more details. 12 ## GNU General Public License for more details.
13 ## 13 ##
14 14
15 from libc.stdlib cimport malloc, free
16 15
17 import ctypes
18
19 from struct import pack
20 from itertools import chain 16 from itertools import chain
21 17
22 from pyglet.gl import * 18 from pyglet.gl import *
23 19
24 from .texture import TextureManager 20 from .renderer cimport Renderer
25 from .sprite cimport get_sprite_rendering_data
26 from .background import get_background_rendering_data 21 from .background import get_background_rendering_data
27 22
28 23
29 MAX_ELEMENTS = 10000
30 24
31 25 cdef class GameRenderer(Renderer):
32 cdef struct Vertex:
33 int x, y, z
34 float u, v
35 unsigned char r, g, b, a
36
37
38 cdef class GameRenderer:
39 cdef public texture_manager
40 cdef public game 26 cdef public game
41 cdef public background 27 cdef public background
42 28
43 cdef Vertex *vertex_buffer
44
45
46 def __cinit__(self):
47 # Allocate buffers
48 self.vertex_buffer = <Vertex*> malloc(MAX_ELEMENTS * sizeof(Vertex))
49
50
51 def __dealloc__(self):
52 free(self.vertex_buffer)
53
54 29
55 def __init__(self, resource_loader, game=None, background=None): 30 def __init__(self, resource_loader, game=None, background=None):
56 self.texture_manager = TextureManager(resource_loader) 31 Renderer.__init__(self, resource_loader)
57 32
58 self.game = game 33 self.game = game
59 self.background = background 34 self.background = background
60
61
62 cdef render_elements(self, elements):
63 cdef unsigned short nb_vertices = 0
64
65 indices_by_texture = {}
66
67 for element in elements:
68 sprite = element._sprite
69 if sprite:
70 ox, oy = element.x, element.y
71 key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite)
72 rec = indices_by_texture.setdefault(key, [])
73
74 # Pack data in buffer
75 (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4) = vertices
76 r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3, r4, g4, b4, a4 = colors
77 u1, v1, u2, v2, u3, v3, u4, v4 = uvs
78 self.vertex_buffer[nb_vertices] = Vertex(x1 + ox, y1 + oy, z1, u1, v1, r1, g1, b1, a1)
79 self.vertex_buffer[nb_vertices+1] = Vertex(x2 + ox, y2 + oy, z2, u2, v2, r2, g2, b2, a2)
80 self.vertex_buffer[nb_vertices+2] = Vertex(x3 + ox, y3 + oy, z3, u3, v3, r3, g3, b3, a3)
81 self.vertex_buffer[nb_vertices+3] = Vertex(x4 + ox, y4 + oy, z4, u4, v4, r4, g4, b4, a4)
82
83 # Add indices
84 index = nb_vertices
85 rec.extend((index, index + 1, index + 2, index + 3))
86
87 nb_vertices += 4
88
89 for (texture_key, blendfunc), indices in indices_by_texture.items():
90 glVertexPointer(3, GL_INT, 24, <long> &self.vertex_buffer[0].x)
91 glTexCoordPointer(2, GL_FLOAT, 24, <long> &self.vertex_buffer[0].u)
92 glColorPointer(4, GL_UNSIGNED_BYTE, 24, <long> &self.vertex_buffer[0].r)
93
94 nb_indices = len(indices)
95 indices = pack(str(nb_indices) + 'H', *indices)
96 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc])
97 glBindTexture(GL_TEXTURE_2D, self.texture_manager[texture_key].id)
98 glDrawElements(GL_QUADS, nb_indices, GL_UNSIGNED_SHORT, indices)
99 35
100 36
101 def render(self): 37 def render(self):
102 glClear(GL_DEPTH_BUFFER_BIT) 38 glClear(GL_DEPTH_BUFFER_BIT)
103 39
104 back = self.background 40 back = self.background
105 game = self.game 41 game = self.game
106 texture_manager = self.texture_manager 42 texture_manager = self.texture_manager
107 43
108 if game is not None and game.effect is not None: 44 if game is not None and game.effect is not None:
109 glMatrixMode(GL_MODELVIEW) 45 self.setup_camera(0, 0, 1)
110 glLoadIdentity()
111 # Some explanations on the magic constants:
112 # 192. = 384. / 2. = width / 2.
113 # 224. = 448. / 2. = height / 2.
114 # 835.979370 = 224./math.tan(math.radians(15)) = (height/2.)/math.tan(math.radians(fov/2))
115 # This is so that objects on the (O, x, y) plane use pixel coordinates
116 gluLookAt(192., 224., - 835.979370,
117 192., 224., 0., 0., -1., 0.)
118 46
119 glDisable(GL_FOG) 47 glDisable(GL_FOG)
120 self.render_elements([game.effect]) 48 self.render_elements([game.effect])
121 glEnable(GL_FOG) 49 glEnable(GL_FOG)
122 elif back is not None: 50 elif back is not None:
127 glFogi(GL_FOG_MODE, GL_LINEAR) 55 glFogi(GL_FOG_MODE, GL_LINEAR)
128 glFogf(GL_FOG_START, fog_start) 56 glFogf(GL_FOG_START, fog_start)
129 glFogf(GL_FOG_END, fog_end) 57 glFogf(GL_FOG_END, fog_end)
130 glFogfv(GL_FOG_COLOR, (GLfloat * 4)(fog_r / 255., fog_g / 255., fog_b / 255., 1.)) 58 glFogfv(GL_FOG_COLOR, (GLfloat * 4)(fog_r / 255., fog_g / 255., fog_b / 255., 1.))
131 59
132 glMatrixMode(GL_MODELVIEW) 60 self.setup_camera(dx, dy, dz)
133 glLoadIdentity()
134 # Some explanations on the magic constants:
135 # 192. = 384. / 2. = width / 2.
136 # 224. = 448. / 2. = height / 2.
137 # 835.979370 = 224./math.tan(math.radians(15)) = (height/2.)/math.tan(math.radians(fov/2))
138 # This is so that objects on the (O, x, y) plane use pixel coordinates
139 gluLookAt(192., 224., - 835.979370 * dz,
140 192. + dx, 224. - dy, 0., 0., -1., 0.)
141 glTranslatef(-x, -y, -z) 61 glTranslatef(-x, -y, -z)
142 62
143 glEnable(GL_DEPTH_TEST) 63 glEnable(GL_DEPTH_TEST)
144 for (texture_key, blendfunc), (nb_vertices, vertices, uvs, colors) in get_background_rendering_data(back): 64 for (texture_key, blendfunc), (nb_vertices, vertices, uvs, colors) in get_background_rendering_data(back):
145 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc]) 65 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc])
151 glDisable(GL_DEPTH_TEST) 71 glDisable(GL_DEPTH_TEST)
152 else: 72 else:
153 glClear(GL_COLOR_BUFFER_BIT) 73 glClear(GL_COLOR_BUFFER_BIT)
154 74
155 if game is not None: 75 if game is not None:
156 glMatrixMode(GL_MODELVIEW) 76 self.setup_camera(0, 0, 1)
157 glLoadIdentity()
158 # Some explanations on the magic constants:
159 # 192. = 384. / 2. = width / 2.
160 # 224. = 448. / 2. = height / 2.
161 # 835.979370 = 224./math.tan(math.radians(15)) = (height/2.)/math.tan(math.radians(fov/2))
162 # This is so that objects on the (O, x, y) plane use pixel coordinates
163 gluLookAt(192., 224., - 835.979370,
164 192., 224., 0., 0., -1., 0.)
165 77
166 glDisable(GL_FOG) 78 glDisable(GL_FOG)
167 self.render_elements(game.enemies) 79 self.render_elements(game.enemies)
168 self.render_elements(game.effects) 80 self.render_elements(game.effects)
169 self.render_elements(chain(game.players_bullets, 81 self.render_elements(chain(game.players_bullets,