28 #include "ascension/error.h" |
28 #include "ascension/error.h" |
29 #include "ascension/context.h" |
29 #include "ascension/context.h" |
30 #include "ascension/scene.h" |
30 #include "ascension/scene.h" |
31 #include "ascension/behavior.h" |
31 #include "ascension/behavior.h" |
32 #include "ascension/shader.h" |
32 #include "ascension/shader.h" |
33 #include "ascension/sprite.h" |
|
34 |
33 |
35 #include <cx/tree.h> |
34 #include <cx/tree.h> |
36 #include <cx/array_list.h> |
35 #include <cx/array_list.h> |
37 |
36 |
38 #include <GL/glew.h> |
37 #include <GL/glew.h> |
74 asc_behavior_trigger(behavior); |
73 asc_behavior_trigger(behavior); |
75 } |
74 } |
76 } |
75 } |
77 } |
76 } |
78 |
77 |
79 static void asc_scene_draw_sprites( |
78 static void asc_scene_draw2d( |
80 const AscScene *scene, |
79 const AscScene *scene, |
81 const CxList *opaque, |
80 const CxList *opaque, |
82 const CxList *blend |
81 const CxList *blend |
83 ) { |
82 ) { |
84 glEnable(GL_DEPTH_TEST); |
83 glEnable(GL_DEPTH_TEST); |
85 glClear(GL_DEPTH_BUFFER_BIT); |
84 glClear(GL_DEPTH_BUFFER_BIT); |
86 const AscCamera *camera = asc_scene_camera(scene); |
85 const AscCamera *camera = asc_scene_camera(scene); |
87 |
86 |
88 // render opaque sprites from front to back |
87 // render opaque nodes from front to back |
89 CxIterator iter_opaque = cxListBackwardsIterator(opaque); |
88 CxIterator iter_opaque = cxListBackwardsIterator(opaque); |
90 |
89 |
91 // render sprites with alpha value from back to front |
90 // render nodes with alpha blending from back to front |
92 CxIterator iter_blend = cxListIterator(blend); |
91 CxIterator iter_blend = cxListIterator(blend); |
93 |
92 |
94 // TODO: implement interleaving by depth |
93 // TODO: implement interleaving by depth |
95 // TODO: implement sorting by shader ID to reduce shader switches |
94 // TODO: implement sorting by shader ID to reduce shader switches |
96 if (cxIteratorValid(iter_opaque)) { |
95 if (cxIteratorValid(iter_opaque)) { |
97 glDisable(GL_BLEND); |
96 glDisable(GL_BLEND); |
98 cx_foreach(const AscSprite*, node, iter_opaque) { |
97 cx_foreach(const AscSceneNode*, node, iter_opaque) { |
99 asc_sprite_draw(camera, node); |
98 node->draw_func(camera, node); |
100 } |
99 } |
101 } |
100 } |
102 if (cxIteratorValid(iter_blend)) { |
101 if (cxIteratorValid(iter_blend)) { |
103 glEnable(GL_BLEND); |
102 glEnable(GL_BLEND); |
104 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
103 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
105 cx_foreach(const AscSprite*, node, iter_blend) { |
104 cx_foreach(const AscSceneNode*, node, iter_blend) { |
106 asc_sprite_draw(camera, node); |
105 node->draw_func(camera, node); |
107 } |
106 } |
108 } |
107 } |
109 } |
108 } |
110 |
109 |
111 void asc_scene_draw(AscScene *scene) { |
110 void asc_scene_draw(AscScene *scene) { |
208 |
207 |
209 // clear any previously active shader / camera combination |
208 // clear any previously active shader / camera combination |
210 asc_shader_use(NULL, NULL); |
209 asc_shader_use(NULL, NULL); |
211 |
210 |
212 // 2D Elements |
211 // 2D Elements |
213 // =========== |
212 asc_scene_draw2d(scene, |
214 |
213 render_group[ASC_RENDER_GROUP_2D_OPAQUE], |
215 // Sprites |
214 render_group[ASC_RENDER_GROUP_2D_BLEND] |
216 // ------- |
|
217 asc_scene_draw_sprites(scene, |
|
218 render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE], |
|
219 render_group[ASC_RENDER_GROUP_SPRITE_BLEND] |
|
220 ); |
215 ); |
221 } |
216 } |
222 |
217 |
223 void asc_scene_add_node(AscScene *scene, AscSceneNode *node) { |
218 void asc_scene_add_node(AscScene *scene, AscSceneNode *node) { |
224 asc_scene_node_link(scene->root, node); |
219 asc_scene_node_link(scene->root, node); |