63 |
63 |
64 // create the root node |
64 // create the root node |
65 scene->root = asc_scene_node_empty(); |
65 scene->root = asc_scene_node_empty(); |
66 |
66 |
67 // initialize the render groups |
67 // initialize the render groups |
68 cx_array_initialize(scene->rg_none, 8); |
68 cx_array_initialize(scene->rg_sprites_opaque, 8); |
69 cx_array_initialize(scene->rg_fonts, 8); |
69 cx_array_initialize(scene->rg_sprites_blended, 8); |
70 } |
70 } |
71 |
71 |
72 void asc_scene_destroy(AscScene *scene) { |
72 void asc_scene_destroy(AscScene *scene) { |
73 asc_scene_node_free(scene->root); |
73 asc_scene_node_free(scene->root); |
74 } |
74 } |
81 #define asc_scene_draw_render_group(rg) \ |
81 #define asc_scene_draw_render_group(rg) \ |
82 cx_for_n(i, rg##_size) { \ |
82 cx_for_n(i, rg##_size) { \ |
83 rg[i].draw(rg[i].node); \ |
83 rg[i].draw(rg[i].node); \ |
84 } (void)0 |
84 } (void)0 |
85 |
85 |
|
86 #define asc_scene_draw_render_group_reversed(rg) \ |
|
87 for(size_t i = rg##_size ; i > 0 ; i--) { \ |
|
88 rg[i-1].draw(rg[i-1].node); \ |
|
89 } (void)0 |
|
90 |
86 void asc_scene_draw(AscScene *scene) { |
91 void asc_scene_draw(AscScene *scene) { |
87 // reset render groups |
92 // reset render groups |
88 scene->rg_none_size = 0; |
93 // TODO: avoid recalculating the groups, if possible |
89 scene->rg_fonts_size = 0; |
94 scene->rg_sprites_opaque_size = 0; |
|
95 scene->rg_sprites_blended_size = 0; |
90 |
96 |
91 // skip the root node deliberately, we know it's just the container |
97 // skip the root node deliberately, we know it's just the container |
92 CxTreeIterator iter = asc_scene_node_iterator(scene->root, false); |
98 CxTreeIterator iter = asc_scene_node_iterator(scene->root, false); |
93 cxIteratorNext(iter); |
99 cxIteratorNext(iter); |
94 |
100 |
95 // update the children and add them to the render groups |
101 // update the children and add them to the render groups |
96 cx_foreach(AscSceneNode*, node, iter) { |
102 cx_foreach(AscSceneNode*, node, iter) { |
|
103 node->depth = iter.depth; |
|
104 |
97 // execute behaviors, first |
105 // execute behaviors, first |
98 AscBehaviorNode *behavior = node->behaviors; |
106 AscBehaviorNode *behavior = node->behaviors; |
99 while (behavior) { |
107 while (behavior) { |
100 behavior->func(node); |
108 behavior->func(node); |
101 behavior = behavior->next; |
109 behavior = behavior->next; |
120 if (node->draw_func != NULL) { |
128 if (node->draw_func != NULL) { |
121 struct asc_render_group_entry entry = { |
129 struct asc_render_group_entry entry = { |
122 node->draw_func, node |
130 node->draw_func, node |
123 }; |
131 }; |
124 switch (node->render_group) { |
132 switch (node->render_group) { |
125 case ASC_RENDER_GROUP_NONE: |
133 case ASC_RENDER_GROUP_SPRITE_OPAQUE: |
126 cx_array_simple_add(scene->rg_none, entry); |
134 cx_array_simple_add(scene->rg_sprites_opaque, entry); |
127 break; |
135 break; |
128 case ASC_RENDER_GROUP_FONTS: |
136 case ASC_RENDER_GROUP_SPRITE_BLEND: |
129 cx_array_simple_add(scene->rg_fonts, entry); |
137 cx_array_simple_add(scene->rg_sprites_blended, entry); |
130 break; |
138 break; |
131 } |
139 } |
132 } |
140 } |
133 } |
141 } |
134 |
142 |
137 scene->viewport.pos.x, |
145 scene->viewport.pos.x, |
138 -scene->viewport.pos.y, |
146 -scene->viewport.pos.y, |
139 scene->viewport.size.width, |
147 scene->viewport.size.width, |
140 scene->viewport.size.height |
148 scene->viewport.size.height |
141 ); |
149 ); |
|
150 glClear(GL_COLOR_BUFFER_BIT); |
142 |
151 |
143 // ----------------------------------------- |
152 // ----------------------------------------- |
144 // process the render groups for each camera |
153 // process the render groups for each camera |
145 // ----------------------------------------- |
154 // ----------------------------------------- |
146 cx_for_n(cam_id, ASC_SCENE_CAMERAS_MAX) { |
155 cx_for_n(cam_id, ASC_SCENE_CAMERAS_MAX) { |
147 // update camera parameters, first |
156 // update camera parameters, first |
148 AscCamera *camera = &scene->cameras[cam_id]; |
157 AscCamera *camera = &scene->cameras[cam_id]; |
149 if (camera->update == NULL) continue; |
158 if (camera->update == NULL) continue; |
150 camera->update(camera); |
159 camera->update(camera); |
151 |
160 |
152 // for the NONE group, the draw func is expected to do everything |
161 // 2D Elements |
|
162 // =========== |
153 glEnable(GL_DEPTH_TEST); |
163 glEnable(GL_DEPTH_TEST); |
154 glDisable(GL_BLEND); |
164 glClear(GL_DEPTH_BUFFER_BIT); |
155 asc_scene_draw_render_group(scene->rg_none); |
165 |
156 |
166 // Sprites |
157 // draw the FONTS group |
167 // ------- |
158 glDisable(GL_DEPTH_TEST); |
|
159 glEnable(GL_BLEND); |
|
160 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
161 // TODO: see if we can really always ignore the view matrix |
168 // TODO: see if we can really always ignore the view matrix |
162 // TODO: compute render order for alpha blending to work correctly |
|
163 glUseProgram(ASC_SHADER_SPRITE.base.id); |
169 glUseProgram(ASC_SHADER_SPRITE.base.id); |
164 glUniformMatrix4fv(ASC_SHADER_SPRITE.base.projection, 1, |
170 glUniformMatrix4fv(ASC_SHADER_SPRITE.base.projection, 1, |
165 GL_FALSE, camera->projection); |
171 GL_FALSE, camera->projection); |
166 asc_scene_draw_render_group(scene->rg_fonts); |
172 |
|
173 // render opaque sprites from front to back |
|
174 glDisable(GL_BLEND); |
|
175 asc_scene_draw_render_group_reversed(scene->rg_sprites_opaque); |
|
176 // render sprites with alpha value from back to front |
|
177 glEnable(GL_BLEND); |
|
178 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
179 asc_scene_draw_render_group(scene->rg_sprites_blended); |
167 } |
180 } |
168 } |
181 } |
169 |
182 |
170 AscSceneNode *asc_scene_node_empty(void) { |
183 AscSceneNode *asc_scene_node_empty(void) { |
171 AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); |
184 AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); |