Thu, 21 Mar 2024 22:23:00 +0100
add correct interleaving of opaque and transparent sprites
shader/sprite_vtx.glsl | file | annotate | diff | comparison | revisions | |
src/ascension/datatypes.h | file | annotate | diff | comparison | revisions | |
src/ascension/scene.h | file | annotate | diff | comparison | revisions | |
src/ascension/shader.h | file | annotate | diff | comparison | revisions | |
src/camera.c | file | annotate | diff | comparison | revisions | |
src/scene.c | file | annotate | diff | comparison | revisions | |
src/shader.c | file | annotate | diff | comparison | revisions | |
src/text.c | file | annotate | diff | comparison | revisions | |
src/window.c | file | annotate | diff | comparison | revisions |
1.1 --- a/shader/sprite_vtx.glsl Thu Mar 21 20:48:18 2024 +0100 1.2 +++ b/shader/sprite_vtx.glsl Thu Mar 21 22:23:00 2024 +0100 1.3 @@ -5,8 +5,12 @@ 1.4 1.5 uniform mat4 projection; 1.6 uniform mat4 model; 1.7 +uniform float depth; 1.8 1.9 void main(void) { 1.10 - gl_Position = projection*model*vec4(position, 0.0, 1.0); 1.11 + vec4 pos = projection*model*vec4(position.x, position.y, 0, 1.0); 1.12 + // apply depth 1.13 + pos.z = depth / -256.0; 1.14 + gl_Position = pos; 1.15 texcoord = vec2(model[0].x, model[1].y)*position; 1.16 }
2.1 --- a/src/ascension/datatypes.h Thu Mar 21 20:48:18 2024 +0100 2.2 +++ b/src/ascension/datatypes.h Thu Mar 21 22:23:00 2024 +0100 2.3 @@ -138,14 +138,17 @@ 2.4 float left, 2.5 float right, 2.6 float bottom, 2.7 - float top 2.8 + float top, 2.9 + float near, 2.10 + float far 2.11 ) { 2.12 memset(mat, 0, sizeof(float) * 16); 2.13 mat[asc_mat4_index(0,0)] = 2.f / (right - left); 2.14 mat[asc_mat4_index(1,1)] = 2.f / (top - bottom); 2.15 - mat[asc_mat4_index(2,2)] = -1; 2.16 + mat[asc_mat4_index(2,2)] = -2.f / (far - near); 2.17 mat[asc_mat4_index(3,0)] = -(right + left) / (right - left); 2.18 mat[asc_mat4_index(3,1)] = -(top + bottom) / (top - bottom); 2.19 + mat[asc_mat4_index(3,2)] = -(far + near) / (far - near); 2.20 mat[asc_mat4_index(3,3)] = 1; 2.21 } 2.22
3.1 --- a/src/ascension/scene.h Thu Mar 21 20:48:18 2024 +0100 3.2 +++ b/src/ascension/scene.h Thu Mar 21 22:23:00 2024 +0100 3.3 @@ -49,8 +49,8 @@ 3.4 }; 3.5 3.6 enum AscRenderGroup { 3.7 - ASC_RENDER_GROUP_NONE, 3.8 - ASC_RENDER_GROUP_FONTS 3.9 + ASC_RENDER_GROUP_SPRITE_OPAQUE, 3.10 + ASC_RENDER_GROUP_SPRITE_BLEND 3.11 }; 3.12 3.13 struct AscSceneNode { 3.14 @@ -63,6 +63,7 @@ 3.15 asc_scene_update_func update_func; 3.16 asc_scene_update_func transform_update_func; 3.17 asc_scene_draw_func draw_func; 3.18 + unsigned depth; 3.19 asc_transform world_transform; 3.20 asc_transform local_transform; 3.21 asc_transform final_transform; 3.22 @@ -87,8 +88,8 @@ 3.23 AscSceneNode *root; 3.24 asc_recti viewport; 3.25 AscCamera cameras[ASC_SCENE_CAMERAS_MAX]; 3.26 - CX_ARRAY_DECLARE(struct asc_render_group_entry, rg_none); 3.27 - CX_ARRAY_DECLARE(struct asc_render_group_entry, rg_fonts); 3.28 + CX_ARRAY_DECLARE(struct asc_render_group_entry, rg_sprites_opaque); 3.29 + CX_ARRAY_DECLARE(struct asc_render_group_entry, rg_sprites_blended); 3.30 } AscScene; 3.31 3.32 /**
4.1 --- a/src/ascension/shader.h Thu Mar 21 20:48:18 2024 +0100 4.2 +++ b/src/ascension/shader.h Thu Mar 21 22:23:00 2024 +0100 4.3 @@ -42,6 +42,7 @@ 4.4 typedef struct AscShaderSprite { 4.5 AscShaderProgram base; 4.6 int surface; 4.7 + int depth; 4.8 } AscShaderSprite; 4.9 4.10
5.1 --- a/src/camera.c Thu Mar 21 20:48:18 2024 +0100 5.2 +++ b/src/camera.c Thu Mar 21 22:23:00 2024 +0100 5.3 @@ -32,7 +32,7 @@ 5.4 float right = left + (float) camera->rect.size.width; 5.5 float top = (float) camera->rect.pos.y; 5.6 float bottom = top + (float) camera->rect.size.height; 5.7 - asc_mat4f_ortho(camera->projection, left, right, bottom, top); 5.8 + asc_mat4f_ortho(camera->projection, left, right, bottom, top, -1, 1); 5.9 } 5.10 5.11 void asc_camera_ortho(AscCamera *camera, asc_recti rect) {
6.1 --- a/src/scene.c Thu Mar 21 20:48:18 2024 +0100 6.2 +++ b/src/scene.c Thu Mar 21 22:23:00 2024 +0100 6.3 @@ -65,8 +65,8 @@ 6.4 scene->root = asc_scene_node_empty(); 6.5 6.6 // initialize the render groups 6.7 - cx_array_initialize(scene->rg_none, 8); 6.8 - cx_array_initialize(scene->rg_fonts, 8); 6.9 + cx_array_initialize(scene->rg_sprites_opaque, 8); 6.10 + cx_array_initialize(scene->rg_sprites_blended, 8); 6.11 } 6.12 6.13 void asc_scene_destroy(AscScene *scene) { 6.14 @@ -83,10 +83,16 @@ 6.15 rg[i].draw(rg[i].node); \ 6.16 } (void)0 6.17 6.18 +#define asc_scene_draw_render_group_reversed(rg) \ 6.19 + for(size_t i = rg##_size ; i > 0 ; i--) { \ 6.20 + rg[i-1].draw(rg[i-1].node); \ 6.21 + } (void)0 6.22 + 6.23 void asc_scene_draw(AscScene *scene) { 6.24 // reset render groups 6.25 - scene->rg_none_size = 0; 6.26 - scene->rg_fonts_size = 0; 6.27 + // TODO: avoid recalculating the groups, if possible 6.28 + scene->rg_sprites_opaque_size = 0; 6.29 + scene->rg_sprites_blended_size = 0; 6.30 6.31 // skip the root node deliberately, we know it's just the container 6.32 CxTreeIterator iter = asc_scene_node_iterator(scene->root, false); 6.33 @@ -94,6 +100,8 @@ 6.34 6.35 // update the children and add them to the render groups 6.36 cx_foreach(AscSceneNode*, node, iter) { 6.37 + node->depth = iter.depth; 6.38 + 6.39 // execute behaviors, first 6.40 AscBehaviorNode *behavior = node->behaviors; 6.41 while (behavior) { 6.42 @@ -122,11 +130,11 @@ 6.43 node->draw_func, node 6.44 }; 6.45 switch (node->render_group) { 6.46 - case ASC_RENDER_GROUP_NONE: 6.47 - cx_array_simple_add(scene->rg_none, entry); 6.48 + case ASC_RENDER_GROUP_SPRITE_OPAQUE: 6.49 + cx_array_simple_add(scene->rg_sprites_opaque, entry); 6.50 break; 6.51 - case ASC_RENDER_GROUP_FONTS: 6.52 - cx_array_simple_add(scene->rg_fonts, entry); 6.53 + case ASC_RENDER_GROUP_SPRITE_BLEND: 6.54 + cx_array_simple_add(scene->rg_sprites_blended, entry); 6.55 break; 6.56 } 6.57 } 6.58 @@ -139,6 +147,7 @@ 6.59 scene->viewport.size.width, 6.60 scene->viewport.size.height 6.61 ); 6.62 + glClear(GL_COLOR_BUFFER_BIT); 6.63 6.64 // ----------------------------------------- 6.65 // process the render groups for each camera 6.66 @@ -149,21 +158,25 @@ 6.67 if (camera->update == NULL) continue; 6.68 camera->update(camera); 6.69 6.70 - // for the NONE group, the draw func is expected to do everything 6.71 + // 2D Elements 6.72 + // =========== 6.73 glEnable(GL_DEPTH_TEST); 6.74 - glDisable(GL_BLEND); 6.75 - asc_scene_draw_render_group(scene->rg_none); 6.76 + glClear(GL_DEPTH_BUFFER_BIT); 6.77 6.78 - // draw the FONTS group 6.79 - glDisable(GL_DEPTH_TEST); 6.80 - glEnable(GL_BLEND); 6.81 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 6.82 + // Sprites 6.83 + // ------- 6.84 // TODO: see if we can really always ignore the view matrix 6.85 - // TODO: compute render order for alpha blending to work correctly 6.86 glUseProgram(ASC_SHADER_SPRITE.base.id); 6.87 glUniformMatrix4fv(ASC_SHADER_SPRITE.base.projection, 1, 6.88 GL_FALSE, camera->projection); 6.89 - asc_scene_draw_render_group(scene->rg_fonts); 6.90 + 6.91 + // render opaque sprites from front to back 6.92 + glDisable(GL_BLEND); 6.93 + asc_scene_draw_render_group_reversed(scene->rg_sprites_opaque); 6.94 + // render sprites with alpha value from back to front 6.95 + glEnable(GL_BLEND); 6.96 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 6.97 + asc_scene_draw_render_group(scene->rg_sprites_blended); 6.98 } 6.99 } 6.100
7.1 --- a/src/shader.c Thu Mar 21 20:48:18 2024 +0100 7.2 +++ b/src/shader.c Thu Mar 21 22:23:00 2024 +0100 7.3 @@ -139,6 +139,7 @@ 7.4 void asc_shader_initialize_predefined(void) { 7.5 ASC_SHADER_SPRITE.base = asc_shader_compile_link_discard("shader/sprite_vtx.glsl", "shader/sprite_frag.glsl"); 7.6 ASC_SHADER_SPRITE.surface = glGetUniformLocation(ASC_SHADER_SPRITE.base.id, "surface"); 7.7 + ASC_SHADER_SPRITE.depth = glGetUniformLocation(ASC_SHADER_SPRITE.base.id, "depth"); 7.8 } 7.9 7.10 void asc_shader_destroy_predefined(void) {
8.1 --- a/src/text.c Thu Mar 21 20:48:18 2024 +0100 8.2 +++ b/src/text.c Thu Mar 21 22:23:00 2024 +0100 8.3 @@ -46,6 +46,9 @@ 8.4 glBindTexture(GL_TEXTURE_RECTANGLE, node->tex_id); 8.5 glUniform1i(ASC_SHADER_SPRITE.surface, 0); 8.6 8.7 + // Apply depth 8.8 + glUniform1f(ASC_SHADER_SPRITE.depth, (float)(node->base.depth)); 8.9 + 8.10 // Draw mesh 8.11 asc_primitives_draw_plane(); 8.12 } 8.13 @@ -83,7 +86,7 @@ 8.14 } 8.15 node->dimension.width = surface->w; 8.16 node->dimension.height = surface->h; 8.17 - asc_node_update_transform(node); 8.18 + asc_node_update_transform((AscSceneNode *) node); 8.19 8.20 // Transfer Image Data 8.21 // TODO: move the image data transfer to a separate function - we will need it more often 8.22 @@ -104,7 +107,7 @@ 8.23 return NULL; 8.24 } 8.25 8.26 - node->base.render_group = ASC_RENDER_GROUP_FONTS; 8.27 + node->base.render_group = ASC_RENDER_GROUP_SPRITE_BLEND; 8.28 node->base.free_func = (asc_scene_free_func) asc_text_free; 8.29 node->base.update_func = (asc_scene_update_func) asc_text_update; 8.30 node->base.transform_update_func = (asc_scene_update_func) asc_text_update_transform;
9.1 --- a/src/window.c Thu Mar 21 20:48:18 2024 +0100 9.2 +++ b/src/window.c Thu Mar 21 22:23:00 2024 +0100 9.3 @@ -116,6 +116,7 @@ 9.4 GLenum err = glewInit(); 9.5 if (err == GLEW_OK) { 9.6 SDL_GL_SetSwapInterval(settings->vsync); 9.7 + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 9.8 glEnable(GL_DEBUG_OUTPUT); 9.9 glDebugMessageCallback(asc_gl_debug_callback, NULL); 9.10 9.11 @@ -183,10 +184,6 @@ 9.12 asc_window_activate(window); 9.13 } 9.14 9.15 - // Clear for new frame 9.16 - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 9.17 - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 9.18 - 9.19 // Draw the UI 9.20 asc_scene_draw(&window->ui); 9.21