57 offsetof(AscSceneNode, children), |
57 offsetof(AscSceneNode, children), |
58 offsetof(AscSceneNode, next) |
58 offsetof(AscSceneNode, next) |
59 ); |
59 ); |
60 } |
60 } |
61 |
61 |
62 void asc_scene_draw(AscSceneNode *root, asc_recti viewport, AscCamera *camera) { |
62 void asc_scene_draw(AscSceneNode *root, asc_recti viewport, const AscCamera *camera) { |
63 // create render groups |
63 // create render groups |
64 CxList *render_group[ASC_RENDER_GROUP_COUNT]; |
64 CxList *render_group[ASC_RENDER_GROUP_COUNT]; |
65 cx_for_n(i, ASC_RENDER_GROUP_COUNT) { |
65 cx_for_n(i, ASC_RENDER_GROUP_COUNT) { |
66 render_group[i] = cxArrayListCreateSimple(CX_STORE_POINTERS, 32); |
66 render_group[i] = cxArrayListCreateSimple(CX_STORE_POINTERS, 32); |
67 } |
67 } |
128 ); |
128 ); |
129 |
129 |
130 // ------------------------- |
130 // ------------------------- |
131 // process the render groups |
131 // process the render groups |
132 // ------------------------- |
132 // ------------------------- |
133 AscShaderProgram *shader; |
|
134 CxIterator render_iter; |
133 CxIterator render_iter; |
135 |
134 |
136 // 2D Elements |
135 // 2D Elements |
137 // =========== |
136 // =========== |
138 glEnable(GL_DEPTH_TEST); |
137 glEnable(GL_DEPTH_TEST); |
139 glClear(GL_DEPTH_BUFFER_BIT); |
138 glClear(GL_DEPTH_BUFFER_BIT); |
140 |
139 |
141 // Sprites |
140 // Sprites |
142 // ------- |
141 // ------- |
143 shader = &asc_active_window->glctx.shader.sprite.program; |
142 size_t sprite_count = cxListSize(render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE]) |
144 glUseProgram(shader->id); |
143 + cxListSize(render_group[ASC_RENDER_GROUP_SPRITE_BLEND]); |
145 glUniformMatrix4fv(shader->projection, 1, |
144 if (sprite_count > 0) { |
146 GL_FALSE, camera->projection); |
145 AscShaderProgram *shader = &asc_active_window->glctx.shader.sprite.program; |
147 glUniformMatrix4fv(shader->view, 1, |
146 glUseProgram(shader->id); |
148 GL_FALSE, camera->view); |
147 glUniformMatrix4fv(shader->projection, 1, |
149 |
148 GL_FALSE, camera->projection); |
150 // render opaque sprites from front to back |
149 glUniformMatrix4fv(shader->view, 1, |
151 glDisable(GL_BLEND); |
150 GL_FALSE, camera->view); |
152 render_iter = cxListBackwardsIterator(render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE]); |
151 |
153 cx_foreach(AscSprite const *, node, render_iter) { |
152 // render opaque sprites from front to back |
154 asc_sprite_draw(node); |
153 glDisable(GL_BLEND); |
155 } |
154 render_iter = cxListBackwardsIterator(render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE]); |
156 |
155 cx_foreach(AscSprite const *, node, render_iter) { |
157 // render sprites with alpha value from back to front |
156 asc_sprite_draw(node); |
158 glEnable(GL_BLEND); |
157 } |
159 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
158 |
160 render_iter = cxListIterator(render_group[ASC_RENDER_GROUP_SPRITE_BLEND]); |
159 // render sprites with alpha value from back to front |
161 cx_foreach(AscSprite const *, node, render_iter) { |
160 glEnable(GL_BLEND); |
162 asc_sprite_draw(node); |
161 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
162 render_iter = cxListIterator(render_group[ASC_RENDER_GROUP_SPRITE_BLEND]); |
|
163 cx_foreach(AscSprite const *, node, render_iter) { |
|
164 asc_sprite_draw(node); |
|
165 } |
163 } |
166 } |
164 |
167 |
165 // deallocate render groups |
168 // deallocate render groups |
166 cx_for_n(i, ASC_RENDER_GROUP_COUNT) { |
169 cx_for_n(i, ASC_RENDER_GROUP_COUNT) { |
167 cxListFree(render_group[i]); |
170 cxListFree(render_group[i]); |