From fd6b9ef6397fee2092a7ab7ee06c2e54292658e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Fri, 12 Apr 2024 00:22:52 +0200 Subject: [PATCH] gfx: model render pass switch + lmap fix --- bind/v4k.lua | 11 +++++- engine/joint/v4k.h | 82 +++++++++++++++++++++++++++++++++------ engine/split/v4k_render.c | 68 +++++++++++++++++++++++++++----- engine/split/v4k_render.h | 14 ++++++- engine/v4k.c | 68 +++++++++++++++++++++++++++----- engine/v4k.h | 14 ++++++- 6 files changed, 223 insertions(+), 34 deletions(-) diff --git a/bind/v4k.lua b/bind/v4k.lua index c69d4dd..0d7b37b 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -1036,6 +1036,7 @@ typedef struct renderstate_t { float clear_color[4]; double clear_depth; bool depth_test_enabled; + bool depth_write_enabled; unsigned depth_func; bool blend_enabled; unsigned blend_func; @@ -1361,6 +1362,12 @@ enum SHADING_MODE { SHADING_PHONG, SHADING_PBR, }; +enum RENDER_PASS { + RENDER_PASS_NORMAL, + RENDER_PASS_SHADOW, + RENDER_PASS_LIGHTMAP, + NUM_RENDER_PASSES +}; typedef struct model_t { struct iqm_t *iqm; int shading; @@ -1390,7 +1397,7 @@ typedef struct model_t { float *instanced_matrices; unsigned num_instances; int stored_flags; - renderstate_t rs; + renderstate_t rs[NUM_RENDER_PASSES]; } model_t; enum BILLBOARD_MODE { BILLBOARD_X = 0x1, @@ -1413,6 +1420,8 @@ enum BILLBOARD_MODE { void model_set_texture(model_t, texture_t t); bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out); void model_destroy(model_t); + unsigned model_getpass(); + unsigned model_setpass(unsigned pass); vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); typedef struct anims_t { int inuse; diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 667ba12..46afcb1 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -17041,6 +17041,7 @@ typedef struct renderstate_t { // Depth test bool depth_test_enabled; + bool depth_write_enabled; unsigned depth_func; // Blending @@ -17615,6 +17616,14 @@ enum SHADING_MODE { SHADING_PBR, }; +enum RENDER_PASS { + RENDER_PASS_NORMAL, + RENDER_PASS_SHADOW, + RENDER_PASS_LIGHTMAP, + + NUM_RENDER_PASSES +}; + typedef struct model_t { struct iqm_t *iqm; // private @@ -17652,7 +17661,7 @@ typedef struct model_t { unsigned num_instances; int stored_flags; - renderstate_t rs; + renderstate_t rs[NUM_RENDER_PASSES]; } model_t; enum BILLBOARD_MODE { @@ -17679,6 +17688,9 @@ API void model_set_texture(model_t, texture_t t); API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out); API void model_destroy(model_t); +API unsigned model_getpass(); +API unsigned model_setpass(unsigned pass); + API vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); // ----------------------------------------------------------------------------- @@ -370139,6 +370151,7 @@ renderstate_t renderstate() { // Enable depth test by default with less or equal function state.depth_test_enabled = GL_TRUE; + state.depth_write_enabled = GL_TRUE; state.depth_func = GL_LEQUAL; // Disable blending by default @@ -370208,6 +370221,9 @@ void renderstate_apply(const renderstate_t *state) { glDisable(GL_DEPTH_TEST); } + // Apply depth write + glDepthMask(state->depth_write_enabled); + // Apply blending if (state->blend_enabled) { glEnable(GL_BLEND); @@ -373785,20 +373801,47 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model, return true; } +static +void model_set_renderstates(model_t *m) { + for (int i = 0; irs[i] = renderstate(); + } + + // Normal pass + renderstate_t *normal_rs = &m->rs[RENDER_PASS_NORMAL]; + { + normal_rs->blend_enabled = 1; + normal_rs->blend_src = GL_SRC_ALPHA; + normal_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + normal_rs->cull_face_mode = GL_BACK; + normal_rs->front_face = GL_CW; + } + + // Shadow pass @todo + renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW]; + { + shadow_rs->blend_enabled = 1; + shadow_rs->blend_src = GL_SRC_ALPHA; + shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + shadow_rs->cull_face_mode = GL_BACK; + shadow_rs->front_face = GL_CW; + } + + // Lightmap pass + renderstate_t *lightmap_rs = &m->rs[RENDER_PASS_LIGHTMAP]; + { + lightmap_rs->blend_enabled = 0; + lightmap_rs->cull_face_enabled = 0; + lightmap_rs->front_face = GL_CW; + } +} + model_t model_from_mem(const void *mem, int len, int flags) { model_t m = {0}; - { - m.rs = renderstate(); - m.rs.blend_enabled = 1; - m.rs.blend_src = GL_SRC_ALPHA; - m.rs.blend_dst = GL_ONE_MINUS_SRC_ALPHA; - m.rs.cull_face_mode = GL_BACK; - m.rs.front_face = GL_CW; - } - m.stored_flags = flags; m.shading = SHADING_PHONG; + model_set_renderstates(&m); const char *ptr = (const char *)mem; // can't cache shader programs since we enable features via flags here @@ -374080,7 +374123,7 @@ void model_draw_call(model_t m, int shader) { handle old_shader = last_shader; shader_bind(shader); - renderstate_apply(&m.rs); + renderstate_apply(&m.rs[model_getpass()]); glBindVertexArray( q->vao ); @@ -374227,6 +374270,19 @@ void model_destroy(model_t m) { FREE(q); } +static unsigned model_renderpass = RENDER_PASS_NORMAL; + +unsigned model_getpass() { + return model_renderpass; +} + +unsigned model_setpass(unsigned pass) { + ASSERT(pass < NUM_RENDER_PASSES); + unsigned old_pass = model_renderpass; + model_renderpass = pass; + return old_pass; +} + anims_t animations(const char *pathfile, int flags) { anims_t a = {0}; a.anims = animlist(pathfile); @@ -374284,6 +374340,8 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm glBindTexture(GL_TEXTURE_2D, 0); } + unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP); + for (int b = 0; b < bounces; b++) { for (int i = 0; i < array_count(lm->models); i++) { model_t *m = lm->models[i]; @@ -374310,6 +374368,8 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm } } + model_setpass(old_pass); + // postprocess texture for (int i = 0; i < array_count(lm->models); i++) { model_t *m = lm->models[i]; diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index 206a662..c9b2d78 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -67,6 +67,7 @@ renderstate_t renderstate() { // Enable depth test by default with less or equal function state.depth_test_enabled = GL_TRUE; + state.depth_write_enabled = GL_TRUE; state.depth_func = GL_LEQUAL; // Disable blending by default @@ -136,6 +137,9 @@ void renderstate_apply(const renderstate_t *state) { glDisable(GL_DEPTH_TEST); } + // Apply depth write + glDepthMask(state->depth_write_enabled); + // Apply blending if (state->blend_enabled) { glEnable(GL_BLEND); @@ -3713,20 +3717,47 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model, return true; } +static +void model_set_renderstates(model_t *m) { + for (int i = 0; irs[i] = renderstate(); + } + + // Normal pass + renderstate_t *normal_rs = &m->rs[RENDER_PASS_NORMAL]; + { + normal_rs->blend_enabled = 1; + normal_rs->blend_src = GL_SRC_ALPHA; + normal_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + normal_rs->cull_face_mode = GL_BACK; + normal_rs->front_face = GL_CW; + } + + // Shadow pass @todo + renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW]; + { + shadow_rs->blend_enabled = 1; + shadow_rs->blend_src = GL_SRC_ALPHA; + shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + shadow_rs->cull_face_mode = GL_BACK; + shadow_rs->front_face = GL_CW; + } + + // Lightmap pass + renderstate_t *lightmap_rs = &m->rs[RENDER_PASS_LIGHTMAP]; + { + lightmap_rs->blend_enabled = 0; + lightmap_rs->cull_face_enabled = 0; + lightmap_rs->front_face = GL_CW; + } +} + model_t model_from_mem(const void *mem, int len, int flags) { model_t m = {0}; - { - m.rs = renderstate(); - m.rs.blend_enabled = 1; - m.rs.blend_src = GL_SRC_ALPHA; - m.rs.blend_dst = GL_ONE_MINUS_SRC_ALPHA; - m.rs.cull_face_mode = GL_BACK; - m.rs.front_face = GL_CW; - } - m.stored_flags = flags; m.shading = SHADING_PHONG; + model_set_renderstates(&m); const char *ptr = (const char *)mem; // can't cache shader programs since we enable features via flags here @@ -4008,7 +4039,7 @@ void model_draw_call(model_t m, int shader) { handle old_shader = last_shader; shader_bind(shader); - renderstate_apply(&m.rs); + renderstate_apply(&m.rs[model_getpass()]); glBindVertexArray( q->vao ); @@ -4155,6 +4186,19 @@ void model_destroy(model_t m) { FREE(q); } +static unsigned model_renderpass = RENDER_PASS_NORMAL; + +unsigned model_getpass() { + return model_renderpass; +} + +unsigned model_setpass(unsigned pass) { + ASSERT(pass < NUM_RENDER_PASSES); + unsigned old_pass = model_renderpass; + model_renderpass = pass; + return old_pass; +} + anims_t animations(const char *pathfile, int flags) { anims_t a = {0}; a.anims = animlist(pathfile); @@ -4212,6 +4256,8 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm glBindTexture(GL_TEXTURE_2D, 0); } + unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP); + for (int b = 0; b < bounces; b++) { for (int i = 0; i < array_count(lm->models); i++) { model_t *m = lm->models[i]; @@ -4238,6 +4284,8 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm } } + model_setpass(old_pass); + // postprocess texture for (int i = 0; i < array_count(lm->models); i++) { model_t *m = lm->models[i]; diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index c0f6ced..4f24986 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -19,6 +19,7 @@ typedef struct renderstate_t { // Depth test bool depth_test_enabled; + bool depth_write_enabled; unsigned depth_func; // Blending @@ -593,6 +594,14 @@ enum SHADING_MODE { SHADING_PBR, }; +enum RENDER_PASS { + RENDER_PASS_NORMAL, + RENDER_PASS_SHADOW, + RENDER_PASS_LIGHTMAP, + + NUM_RENDER_PASSES +}; + typedef struct model_t { struct iqm_t *iqm; // private @@ -630,7 +639,7 @@ typedef struct model_t { unsigned num_instances; int stored_flags; - renderstate_t rs; + renderstate_t rs[NUM_RENDER_PASSES]; } model_t; enum BILLBOARD_MODE { @@ -657,6 +666,9 @@ API void model_set_texture(model_t, texture_t t); API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out); API void model_destroy(model_t); +API unsigned model_getpass(); +API unsigned model_setpass(unsigned pass); + API vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); // ----------------------------------------------------------------------------- diff --git a/engine/v4k.c b/engine/v4k.c index b57fa9d..7b49d53 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -17238,6 +17238,7 @@ renderstate_t renderstate() { // Enable depth test by default with less or equal function state.depth_test_enabled = GL_TRUE; + state.depth_write_enabled = GL_TRUE; state.depth_func = GL_LEQUAL; // Disable blending by default @@ -17307,6 +17308,9 @@ void renderstate_apply(const renderstate_t *state) { glDisable(GL_DEPTH_TEST); } + // Apply depth write + glDepthMask(state->depth_write_enabled); + // Apply blending if (state->blend_enabled) { glEnable(GL_BLEND); @@ -20884,20 +20888,47 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model, return true; } +static +void model_set_renderstates(model_t *m) { + for (int i = 0; irs[i] = renderstate(); + } + + // Normal pass + renderstate_t *normal_rs = &m->rs[RENDER_PASS_NORMAL]; + { + normal_rs->blend_enabled = 1; + normal_rs->blend_src = GL_SRC_ALPHA; + normal_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + normal_rs->cull_face_mode = GL_BACK; + normal_rs->front_face = GL_CW; + } + + // Shadow pass @todo + renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW]; + { + shadow_rs->blend_enabled = 1; + shadow_rs->blend_src = GL_SRC_ALPHA; + shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + shadow_rs->cull_face_mode = GL_BACK; + shadow_rs->front_face = GL_CW; + } + + // Lightmap pass + renderstate_t *lightmap_rs = &m->rs[RENDER_PASS_LIGHTMAP]; + { + lightmap_rs->blend_enabled = 0; + lightmap_rs->cull_face_enabled = 0; + lightmap_rs->front_face = GL_CW; + } +} + model_t model_from_mem(const void *mem, int len, int flags) { model_t m = {0}; - { - m.rs = renderstate(); - m.rs.blend_enabled = 1; - m.rs.blend_src = GL_SRC_ALPHA; - m.rs.blend_dst = GL_ONE_MINUS_SRC_ALPHA; - m.rs.cull_face_mode = GL_BACK; - m.rs.front_face = GL_CW; - } - m.stored_flags = flags; m.shading = SHADING_PHONG; + model_set_renderstates(&m); const char *ptr = (const char *)mem; // can't cache shader programs since we enable features via flags here @@ -21179,7 +21210,7 @@ void model_draw_call(model_t m, int shader) { handle old_shader = last_shader; shader_bind(shader); - renderstate_apply(&m.rs); + renderstate_apply(&m.rs[model_getpass()]); glBindVertexArray( q->vao ); @@ -21326,6 +21357,19 @@ void model_destroy(model_t m) { FREE(q); } +static unsigned model_renderpass = RENDER_PASS_NORMAL; + +unsigned model_getpass() { + return model_renderpass; +} + +unsigned model_setpass(unsigned pass) { + ASSERT(pass < NUM_RENDER_PASSES); + unsigned old_pass = model_renderpass; + model_renderpass = pass; + return old_pass; +} + anims_t animations(const char *pathfile, int flags) { anims_t a = {0}; a.anims = animlist(pathfile); @@ -21383,6 +21427,8 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm glBindTexture(GL_TEXTURE_2D, 0); } + unsigned old_pass = model_setpass(RENDER_PASS_LIGHTMAP); + for (int b = 0; b < bounces; b++) { for (int i = 0; i < array_count(lm->models); i++) { model_t *m = lm->models[i]; @@ -21409,6 +21455,8 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm } } + model_setpass(old_pass); + // postprocess texture for (int i = 0; i < array_count(lm->models); i++) { model_t *m = lm->models[i]; diff --git a/engine/v4k.h b/engine/v4k.h index 02f64db..cfe035e 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -3108,6 +3108,7 @@ typedef struct renderstate_t { // Depth test bool depth_test_enabled; + bool depth_write_enabled; unsigned depth_func; // Blending @@ -3682,6 +3683,14 @@ enum SHADING_MODE { SHADING_PBR, }; +enum RENDER_PASS { + RENDER_PASS_NORMAL, + RENDER_PASS_SHADOW, + RENDER_PASS_LIGHTMAP, + + NUM_RENDER_PASSES +}; + typedef struct model_t { struct iqm_t *iqm; // private @@ -3719,7 +3728,7 @@ typedef struct model_t { unsigned num_instances; int stored_flags; - renderstate_t rs; + renderstate_t rs[NUM_RENDER_PASSES]; } model_t; enum BILLBOARD_MODE { @@ -3746,6 +3755,9 @@ API void model_set_texture(model_t, texture_t t); API bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out); API void model_destroy(model_t); +API unsigned model_getpass(); +API unsigned model_setpass(unsigned pass); + API vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); // -----------------------------------------------------------------------------