45 asc_wprintf("Scene %"PRIxPTR" is already initialized - initialization skipped.", (uintptr_t) scene); |
44 asc_wprintf("Scene %"PRIxPTR" is already initialized - initialization skipped.", (uintptr_t) scene); |
46 return; |
45 return; |
47 } |
46 } |
48 asc_camera_init_(&scene->camera, args); |
47 asc_camera_init_(&scene->camera, args); |
49 scene->root = asc_scene_node_empty(); |
48 scene->root = asc_scene_node_empty(); |
|
49 for (unsigned i = 0 ; i < ASC_RENDER_GROUP_COUNT ; i++) { |
|
50 scene->internal.render_groups[i] = cxArrayListCreateSimple(CX_STORE_POINTERS, 32); |
|
51 } |
50 |
52 |
51 asc_dprintf("Initialized scene %"PRIxPTR, (uintptr_t) scene); |
53 asc_dprintf("Initialized scene %"PRIxPTR, (uintptr_t) scene); |
52 } |
54 } |
53 |
55 |
54 void asc_scene_destroy(AscScene *scene) { |
56 void asc_scene_destroy(AscScene *scene) { |
55 if (scene->root == NULL) return; |
57 if (scene->root == NULL) return; |
56 |
58 for (unsigned i = 0 ; i < ASC_RENDER_GROUP_COUNT ; i++) { |
|
59 cxListFree(scene->internal.render_groups[i]); |
|
60 scene->internal.render_groups[i] = NULL; |
|
61 } |
57 asc_dprintf("Destroyed scene %"PRIxPTR, (uintptr_t) scene); |
62 asc_dprintf("Destroyed scene %"PRIxPTR, (uintptr_t) scene); |
58 asc_scene_node_free(scene->root); |
63 asc_scene_node_free(scene->root); |
59 } |
64 } |
60 |
65 |
61 void asc_scene_execute_behaviors(AscScene *scene) { |
66 void asc_scene_execute_behaviors(AscScene *scene) { |
67 CxIterator behavior_iter = cxListIterator(node->behaviors); |
72 CxIterator behavior_iter = cxListIterator(node->behaviors); |
68 cx_foreach(AscBehavior*, behavior, behavior_iter) { |
73 cx_foreach(AscBehavior*, behavior, behavior_iter) { |
69 if (behavior->enabled) { |
74 if (behavior->enabled) { |
70 behavior->func(behavior); |
75 behavior->func(behavior); |
71 } |
76 } |
|
77 } |
|
78 } |
|
79 } |
|
80 |
|
81 void asc_scene_draw_sprites( |
|
82 const AscScene *scene, |
|
83 const CxList *opaque_rect, |
|
84 const CxList *opaque_uv, |
|
85 const CxList *blend_rect, |
|
86 const CxList *blend_uv |
|
87 ) { |
|
88 // render opaque sprites from front to back |
|
89 CxIterator iter_opaque_rect = cxListBackwardsIterator(opaque_rect); |
|
90 CxIterator iter_opaque_uv = cxListBackwardsIterator(opaque_uv); |
|
91 |
|
92 // render sprites with alpha value from back to front |
|
93 CxIterator iter_blend_rect = cxListIterator(blend_rect); |
|
94 CxIterator iter_blend_uv = cxListIterator(blend_uv); |
|
95 |
|
96 // TODO: implement interleaving by depth |
|
97 if (cxIteratorValid(iter_opaque_rect)) { |
|
98 glDisable(GL_BLEND); |
|
99 AscShaderSprite *shader = ASC_SHADER_SPRITE_RECT; |
|
100 asc_shader_program_use(&shader->program, &scene->camera); |
|
101 cx_foreach(const AscSprite*, node, iter_opaque_rect) { |
|
102 asc_sprite_draw(shader, node); |
|
103 } |
|
104 } |
|
105 if (cxIteratorValid(iter_opaque_uv)) { |
|
106 glDisable(GL_BLEND); |
|
107 AscShaderSprite *shader = ASC_SHADER_SPRITE_UV; |
|
108 asc_shader_program_use(&shader->program, &scene->camera); |
|
109 cx_foreach(const AscSprite*, node, iter_opaque_uv) { |
|
110 asc_sprite_draw(shader, node); |
|
111 } |
|
112 } |
|
113 if (cxIteratorValid(iter_blend_rect)) { |
|
114 glEnable(GL_BLEND); |
|
115 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
116 AscShaderSprite *shader = ASC_SHADER_SPRITE_RECT; |
|
117 asc_shader_program_use(&shader->program, &scene->camera); |
|
118 cx_foreach(const AscSprite*, node, iter_blend_rect) { |
|
119 asc_sprite_draw(shader, node); |
|
120 } |
|
121 } |
|
122 if (cxIteratorValid(iter_blend_uv)) { |
|
123 glEnable(GL_BLEND); |
|
124 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
125 AscShaderSprite *shader = ASC_SHADER_SPRITE_UV; |
|
126 asc_shader_program_use(&shader->program, &scene->camera); |
|
127 cx_foreach(const AscSprite*, node, iter_blend_uv) { |
|
128 asc_sprite_draw(shader, node); |
72 } |
129 } |
73 } |
130 } |
74 } |
131 } |
75 |
132 |
76 void asc_scene_draw(AscScene *scene) { |
133 void asc_scene_draw(AscScene *scene) { |
88 if (scene->camera.projection_update_func != NULL) { |
145 if (scene->camera.projection_update_func != NULL) { |
89 scene->camera.projection_update_func(&scene->camera, window_size); |
146 scene->camera.projection_update_func(&scene->camera, window_size); |
90 } |
147 } |
91 } |
148 } |
92 |
149 |
93 // create render groups |
150 // reset render groups |
94 CxList *render_group[ASC_RENDER_GROUP_COUNT]; |
151 CxList **render_group = scene->internal.render_groups; |
95 for (unsigned i = 0 ; i < ASC_RENDER_GROUP_COUNT ; i++) { |
152 for (unsigned i = 0 ; i < ASC_RENDER_GROUP_COUNT ; i++) { |
96 render_group[i] = cxArrayListCreateSimple(CX_STORE_POINTERS, 32); |
153 cxListClear(render_group[i]); |
97 } |
154 } |
98 |
155 |
99 // update the scene graph and add nodes to their render groups |
156 // update the scene graph and add nodes to their render groups |
100 CxTreeVisitor iter = cx_tree_visitor(scene->root, |
157 CxTreeVisitor iter = cx_tree_visitor(scene->root, |
101 offsetof(AscSceneNode, children), |
158 offsetof(AscSceneNode, children), |
168 } |
225 } |
169 |
226 |
170 // ------------------------- |
227 // ------------------------- |
171 // process the render groups |
228 // process the render groups |
172 // ------------------------- |
229 // ------------------------- |
173 CxIterator render_iter; |
|
174 |
230 |
175 // 2D Elements |
231 // 2D Elements |
176 // =========== |
232 // =========== |
177 glEnable(GL_DEPTH_TEST); |
233 glEnable(GL_DEPTH_TEST); |
178 glClear(GL_DEPTH_BUFFER_BIT); |
234 glClear(GL_DEPTH_BUFFER_BIT); |
179 |
235 |
180 // Sprites |
236 // Sprites |
181 // ------- |
237 // ------- |
182 size_t sprite_count = cxListSize(render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE]) |
238 asc_scene_draw_sprites(scene, |
183 + cxListSize(render_group[ASC_RENDER_GROUP_SPRITE_BLEND]); |
239 render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE_RECT], |
184 if (sprite_count > 0) { |
240 render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE_UV], |
185 AscShaderProgram *shader = &ASC_SHADER_SPRITE->program; |
241 render_group[ASC_RENDER_GROUP_SPRITE_BLEND_RECT], |
186 glUseProgram(shader->id); |
242 render_group[ASC_RENDER_GROUP_SPRITE_BLEND_UV] |
187 glUniformMatrix4fv(shader->projection, 1, |
243 ); |
188 GL_FALSE, scene->camera.projection); |
|
189 glUniformMatrix4fv(shader->view, 1, |
|
190 GL_FALSE, scene->camera.view); |
|
191 |
|
192 // render opaque sprites from front to back |
|
193 glDisable(GL_BLEND); |
|
194 render_iter = cxListBackwardsIterator(render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE]); |
|
195 cx_foreach(AscSprite const *, node, render_iter) { |
|
196 asc_sprite_draw(node); |
|
197 } |
|
198 |
|
199 // render sprites with alpha value from back to front |
|
200 glEnable(GL_BLEND); |
|
201 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
202 render_iter = cxListIterator(render_group[ASC_RENDER_GROUP_SPRITE_BLEND]); |
|
203 cx_foreach(AscSprite const *, node, render_iter) { |
|
204 asc_sprite_draw(node); |
|
205 } |
|
206 } |
|
207 |
|
208 // deallocate render groups |
|
209 for (unsigned i = 0 ; i < ASC_RENDER_GROUP_COUNT ; i++) { |
|
210 cxListFree(render_group[i]); |
|
211 } |
|
212 } |
244 } |
213 |
245 |
214 void asc_scene_add_node(AscScene *scene, AscSceneNode *node) { |
246 void asc_scene_add_node(AscScene *scene, AscSceneNode *node) { |
215 asc_scene_node_link(scene->root, node); |
247 asc_scene_node_link(scene->root, node); |
216 } |
248 } |