1.1 --- a/src/scene.c Thu Mar 21 20:48:18 2024 +0100 1.2 +++ b/src/scene.c Thu Mar 21 22:23:00 2024 +0100 1.3 @@ -65,8 +65,8 @@ 1.4 scene->root = asc_scene_node_empty(); 1.5 1.6 // initialize the render groups 1.7 - cx_array_initialize(scene->rg_none, 8); 1.8 - cx_array_initialize(scene->rg_fonts, 8); 1.9 + cx_array_initialize(scene->rg_sprites_opaque, 8); 1.10 + cx_array_initialize(scene->rg_sprites_blended, 8); 1.11 } 1.12 1.13 void asc_scene_destroy(AscScene *scene) { 1.14 @@ -83,10 +83,16 @@ 1.15 rg[i].draw(rg[i].node); \ 1.16 } (void)0 1.17 1.18 +#define asc_scene_draw_render_group_reversed(rg) \ 1.19 + for(size_t i = rg##_size ; i > 0 ; i--) { \ 1.20 + rg[i-1].draw(rg[i-1].node); \ 1.21 + } (void)0 1.22 + 1.23 void asc_scene_draw(AscScene *scene) { 1.24 // reset render groups 1.25 - scene->rg_none_size = 0; 1.26 - scene->rg_fonts_size = 0; 1.27 + // TODO: avoid recalculating the groups, if possible 1.28 + scene->rg_sprites_opaque_size = 0; 1.29 + scene->rg_sprites_blended_size = 0; 1.30 1.31 // skip the root node deliberately, we know it's just the container 1.32 CxTreeIterator iter = asc_scene_node_iterator(scene->root, false); 1.33 @@ -94,6 +100,8 @@ 1.34 1.35 // update the children and add them to the render groups 1.36 cx_foreach(AscSceneNode*, node, iter) { 1.37 + node->depth = iter.depth; 1.38 + 1.39 // execute behaviors, first 1.40 AscBehaviorNode *behavior = node->behaviors; 1.41 while (behavior) { 1.42 @@ -122,11 +130,11 @@ 1.43 node->draw_func, node 1.44 }; 1.45 switch (node->render_group) { 1.46 - case ASC_RENDER_GROUP_NONE: 1.47 - cx_array_simple_add(scene->rg_none, entry); 1.48 + case ASC_RENDER_GROUP_SPRITE_OPAQUE: 1.49 + cx_array_simple_add(scene->rg_sprites_opaque, entry); 1.50 break; 1.51 - case ASC_RENDER_GROUP_FONTS: 1.52 - cx_array_simple_add(scene->rg_fonts, entry); 1.53 + case ASC_RENDER_GROUP_SPRITE_BLEND: 1.54 + cx_array_simple_add(scene->rg_sprites_blended, entry); 1.55 break; 1.56 } 1.57 } 1.58 @@ -139,6 +147,7 @@ 1.59 scene->viewport.size.width, 1.60 scene->viewport.size.height 1.61 ); 1.62 + glClear(GL_COLOR_BUFFER_BIT); 1.63 1.64 // ----------------------------------------- 1.65 // process the render groups for each camera 1.66 @@ -149,21 +158,25 @@ 1.67 if (camera->update == NULL) continue; 1.68 camera->update(camera); 1.69 1.70 - // for the NONE group, the draw func is expected to do everything 1.71 + // 2D Elements 1.72 + // =========== 1.73 glEnable(GL_DEPTH_TEST); 1.74 - glDisable(GL_BLEND); 1.75 - asc_scene_draw_render_group(scene->rg_none); 1.76 + glClear(GL_DEPTH_BUFFER_BIT); 1.77 1.78 - // draw the FONTS group 1.79 - glDisable(GL_DEPTH_TEST); 1.80 - glEnable(GL_BLEND); 1.81 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1.82 + // Sprites 1.83 + // ------- 1.84 // TODO: see if we can really always ignore the view matrix 1.85 - // TODO: compute render order for alpha blending to work correctly 1.86 glUseProgram(ASC_SHADER_SPRITE.base.id); 1.87 glUniformMatrix4fv(ASC_SHADER_SPRITE.base.projection, 1, 1.88 GL_FALSE, camera->projection); 1.89 - asc_scene_draw_render_group(scene->rg_fonts); 1.90 + 1.91 + // render opaque sprites from front to back 1.92 + glDisable(GL_BLEND); 1.93 + asc_scene_draw_render_group_reversed(scene->rg_sprites_opaque); 1.94 + // render sprites with alpha value from back to front 1.95 + glEnable(GL_BLEND); 1.96 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1.97 + asc_scene_draw_render_group(scene->rg_sprites_blended); 1.98 } 1.99 } 1.100