diff -r 6c438be1a1fd -r df81d493716e src/scene.c --- a/src/scene.c Thu Mar 21 20:48:18 2024 +0100 +++ b/src/scene.c Thu Mar 21 22:23:00 2024 +0100 @@ -65,8 +65,8 @@ scene->root = asc_scene_node_empty(); // initialize the render groups - cx_array_initialize(scene->rg_none, 8); - cx_array_initialize(scene->rg_fonts, 8); + cx_array_initialize(scene->rg_sprites_opaque, 8); + cx_array_initialize(scene->rg_sprites_blended, 8); } void asc_scene_destroy(AscScene *scene) { @@ -83,10 +83,16 @@ rg[i].draw(rg[i].node); \ } (void)0 +#define asc_scene_draw_render_group_reversed(rg) \ + for(size_t i = rg##_size ; i > 0 ; i--) { \ + rg[i-1].draw(rg[i-1].node); \ + } (void)0 + void asc_scene_draw(AscScene *scene) { // reset render groups - scene->rg_none_size = 0; - scene->rg_fonts_size = 0; + // TODO: avoid recalculating the groups, if possible + scene->rg_sprites_opaque_size = 0; + scene->rg_sprites_blended_size = 0; // skip the root node deliberately, we know it's just the container CxTreeIterator iter = asc_scene_node_iterator(scene->root, false); @@ -94,6 +100,8 @@ // update the children and add them to the render groups cx_foreach(AscSceneNode*, node, iter) { + node->depth = iter.depth; + // execute behaviors, first AscBehaviorNode *behavior = node->behaviors; while (behavior) { @@ -122,11 +130,11 @@ node->draw_func, node }; switch (node->render_group) { - case ASC_RENDER_GROUP_NONE: - cx_array_simple_add(scene->rg_none, entry); + case ASC_RENDER_GROUP_SPRITE_OPAQUE: + cx_array_simple_add(scene->rg_sprites_opaque, entry); break; - case ASC_RENDER_GROUP_FONTS: - cx_array_simple_add(scene->rg_fonts, entry); + case ASC_RENDER_GROUP_SPRITE_BLEND: + cx_array_simple_add(scene->rg_sprites_blended, entry); break; } } @@ -139,6 +147,7 @@ scene->viewport.size.width, scene->viewport.size.height ); + glClear(GL_COLOR_BUFFER_BIT); // ----------------------------------------- // process the render groups for each camera @@ -149,21 +158,25 @@ if (camera->update == NULL) continue; camera->update(camera); - // for the NONE group, the draw func is expected to do everything + // 2D Elements + // =========== glEnable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - asc_scene_draw_render_group(scene->rg_none); + glClear(GL_DEPTH_BUFFER_BIT); - // draw the FONTS group - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // Sprites + // ------- // TODO: see if we can really always ignore the view matrix - // TODO: compute render order for alpha blending to work correctly glUseProgram(ASC_SHADER_SPRITE.base.id); glUniformMatrix4fv(ASC_SHADER_SPRITE.base.projection, 1, GL_FALSE, camera->projection); - asc_scene_draw_render_group(scene->rg_fonts); + + // render opaque sprites from front to back + glDisable(GL_BLEND); + asc_scene_draw_render_group_reversed(scene->rg_sprites_opaque); + // render sprites with alpha value from back to front + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + asc_scene_draw_render_group(scene->rg_sprites_blended); } }