diff --git a/bind/v4k.lua b/bind/v4k.lua index e9252d2..b6971a7 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -1205,7 +1205,7 @@ typedef struct shadowmap_t { void shadowmap_destroy(shadowmap_t *s); void shadowmap_begin(shadowmap_t *s); bool shadowmap_step(shadowmap_t *s); - void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view); + void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, float cam_far, mat44 cam_view); void shadowmap_end(shadowmap_t *s); unsigned shader(const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines); unsigned shader_geom(const char *gs, const char *vs, const char *fs, const char *attribs, const char *fragcolor, const char *defines); @@ -1408,7 +1408,10 @@ enum RENDER_PASS { RENDER_PASS_OPAQUE, RENDER_PASS_TRANSPARENT, RENDER_PASS_OVERRIDES_BEGIN, - RENDER_PASS_SHADOW, + RENDER_PASS_SHADOW_BEGIN, + RENDER_PASS_SHADOW_PCF, + RENDER_PASS_SHADOW_VSM, + RENDER_PASS_SHADOW_END, RENDER_PASS_LIGHTMAP, RENDER_PASS_CUSTOM, RENDER_PASS_OVERRIDES_END, diff --git a/demos/09-shadows.c b/demos/09-shadows.c index 8d690d5..9e089ba 100644 --- a/demos/09-shadows.c +++ b/demos/09-shadows.c @@ -51,7 +51,7 @@ int main(int argc, char** argv) { light_t lit4 = light(); { lit4.type = LIGHT_DIRECTIONAL; lit4.cast_shadows = true; - lit4.shadow_distance = 2000.0f; + // lit4.shadow_distance = 2000.0f; lit4.diffuse = vec3(1, 0.7, 0.8); } @@ -87,6 +87,7 @@ int main(int argc, char** argv) { initialized = 1; sky = skybox(flag("--mie") ? 0 : SKY_DIRS[SKY_DIR], 0); sm = shadowmap(512, 2048); + // sm.blur_pcf = 0; mdl = model(OBJ_MDLS[OBJ_MDL], 0); shader_bind(mdl.program); cubemap_sh_shader(&sky.cubemap); @@ -166,7 +167,7 @@ int main(int argc, char** argv) { { for (int i = 0; i < array_count(lights); i++) { while (shadowmap_step(&sm)) { - shadowmap_light(&sm, &lights[i], cam.fov, cam.view); + shadowmap_light(&sm, &lights[i], cam.fov, 2000.0f, cam.view); model_render(mdl, cam.proj, cam.view, mdl.pivot, 0); } } diff --git a/engine/art/shaderlib/shadowmap.glsl b/engine/art/shaderlib/shadowmap.glsl index 4e705c5..ea20217 100644 --- a/engine/art/shaderlib/shadowmap.glsl +++ b/engine/art/shaderlib/shadowmap.glsl @@ -59,7 +59,7 @@ float shadow_pcf(float distance, vec3 lightDir, int light_index) { // Calculate bias vec3 normal = normalize(vneye.xyz); float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); - const float bias_modifier = 0.5; + const float bias_modifier = 0.45; if (cascade_index == NUM_SHADOW_CASCADES-1) { bias *= 1 / (u_cascade_distances[NUM_SHADOW_CASCADES-1] * bias_modifier); } else { @@ -69,15 +69,15 @@ float shadow_pcf(float distance, vec3 lightDir, int light_index) { // PCF float shadow = 0.0; vec2 texelSize = 1.0 / textureSize(shadowMap2D[index], 0); - for(int x = -1; x <= 1; ++x) + for(int x = -3; x <= 3; ++x) { - for(int y = -1; y <= 1; ++y) + for(int y = -3; y <= 3; ++y) { float pcfDepth = texture(shadowMap2D[index], projCoords.xy + vec2(x, y) * texelSize).r; - shadow += projCoords.z - bias > pcfDepth ? 1.0 : 0.0; + shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; } } - shadow /= 9.0; + shadow /= 36.0; return 1.0 - shadow; } diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 1ce836a..9787ecc 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -17351,7 +17351,7 @@ API void shadowmap_destroy(shadowmap_t *s); API void shadowmap_begin(shadowmap_t *s); API bool shadowmap_step(shadowmap_t *s); -API void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view); //< can be called once per shadowmap_step +API void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, float cam_far, mat44 cam_view); //< can be called once per shadowmap_step API void shadowmap_end(shadowmap_t *s); // ----------------------------------------------------------------------------- @@ -17685,7 +17685,12 @@ enum RENDER_PASS { RENDER_PASS_TRANSPARENT, RENDER_PASS_OVERRIDES_BEGIN, - RENDER_PASS_SHADOW, + + RENDER_PASS_SHADOW_BEGIN, + RENDER_PASS_SHADOW_PCF, + RENDER_PASS_SHADOW_VSM, + RENDER_PASS_SHADOW_END, + RENDER_PASS_LIGHTMAP, RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this RENDER_PASS_OVERRIDES_END, @@ -383213,7 +383218,7 @@ light_t light() { l.innerCone = 0.85f;// 31 deg l.outerCone = 0.9f; // 25 deg l.cast_shadows = true; - l.shadow_distance = 100.0f; + l.shadow_distance = 200.0f; l.shadow_bias = 0.01f; return l; } @@ -383503,11 +383508,11 @@ void shadowmap_begin(shadowmap_t *s) { glGetIntegerv(GL_VIEWPORT, s->saved_vp); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb); - s->saved_pass = model_setpass(RENDER_PASS_SHADOW); s->step = 0; s->light_step = 0; s->cascade_index = 0; active_shadowmap = s; + s->saved_pass = model_getpass(); } static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { @@ -383528,6 +383533,7 @@ static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { copy44(s->PV, PV); s->shadow_technique = l->shadow_technique = SHADOW_VSM; + model_setpass(RENDER_PASS_SHADOW_VSM); } static array(vec3) frustum_corners = 0; @@ -383554,7 +383560,7 @@ void shadowmap_light_directional_calc_frustum_corners(mat44 cam_proj, mat44 cam_ } } -static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, float cam_fov, mat44 cam_view) { +static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, float cam_fov, float cam_far, mat44 cam_view) { if (dir != 0) { s->skip_render = true; return; @@ -383571,7 +383577,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo far_plane = l->shadow_distance * s->cascade_splits[s->cascade_index]; } else { near_plane = l->shadow_distance * s->cascade_splits[NUM_SHADOW_CASCADES-1]; - far_plane = l->shadow_distance; + far_plane = cam_far; } mat44 proj; perspective44(proj, cam_fov, window_width() / (float)window_height(), near_plane, far_plane); @@ -383608,25 +383614,11 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo maxZ = max(maxZ, corner.z); } - float zMult = 10.0f; - - // if (minZ < 0) { - // minZ *= zMult; - // } else { - // minZ /= zMult; - // } - // if (maxZ < 0) { - // maxZ /= zMult; - // } else { - // maxZ *= zMult; - // } - - mat44 P, PV; ortho44(P, minX, maxX, minY, maxY, - minZ, maxZ); + -maxZ, -minZ); multiply44x2(PV, P, V); @@ -383635,6 +383627,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo copy44(l->shadow_matrix[s->cascade_index], PV); s->shadow_technique = l->shadow_technique = SHADOW_PCF; + model_setpass(RENDER_PASS_SHADOW_PCF); } static inline @@ -383714,6 +383707,7 @@ bool shadowmap_step_finish(shadowmap_t *s) { s->step = 0; s->light_step++; s->cascade_index = 0; + model_setpass(s->saved_pass); return true; } @@ -383744,7 +383738,7 @@ void shadowmap_clear_fbo() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) { +void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, float cam_far, mat44 cam_view) { if (l->cast_shadows) { int step = s->step - 1; @@ -383753,7 +383747,7 @@ void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) } else if (l->type == LIGHT_SPOT) { shadowmap_light_point(s, l, step); } else if (l->type == LIGHT_DIRECTIONAL) { - shadowmap_light_directional(s, l, step, cam_fov, cam_view); + shadowmap_light_directional(s, l, step, cam_fov, cam_far, cam_view); } if (s->skip_render) { @@ -383787,7 +383781,6 @@ void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) void shadowmap_end(shadowmap_t *s) { glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]); glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb); - model_setpass(s->saved_pass); active_shadowmap = NULL; } @@ -386593,15 +386586,26 @@ void model_set_renderstates(model_t *m) { } // Shadow pass - renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW]; + renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; { - 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_enabled = 1; - shadow_rs->cull_face_mode = GL_BACK; - shadow_rs->front_face = GL_CW; - shadow_rs->depth_clamp_enabled = 1; + pcf_shadow_rs->blend_enabled = 1; + pcf_shadow_rs->blend_src = GL_SRC_ALPHA; + pcf_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + pcf_shadow_rs->cull_face_enabled = 1; + pcf_shadow_rs->cull_face_mode = GL_FRONT; + pcf_shadow_rs->front_face = GL_CCW; + pcf_shadow_rs->depth_clamp_enabled = 1; + } + + renderstate_t *vsm_shadow_rs = &m->rs[RENDER_PASS_SHADOW_VSM]; + { + vsm_shadow_rs->blend_enabled = 1; + vsm_shadow_rs->blend_src = GL_SRC_ALPHA; + vsm_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + vsm_shadow_rs->cull_face_enabled = 1; + vsm_shadow_rs->cull_face_mode = GL_BACK; + vsm_shadow_rs->front_face = GL_CW; + vsm_shadow_rs->depth_clamp_enabled = 1; } // Lightmap pass @@ -387082,7 +387086,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_ renderstate_apply(rs); } - if (rs_idx != RENDER_PASS_SHADOW) { + if (rs_idx < RENDER_PASS_SHADOW_BEGIN || rs_idx > RENDER_PASS_SHADOW_END) { if (m.shading != SHADING_PBR) { shader_texture_unit("u_texture2d", q->textures[i], texture_unit()); shader_texture("u_lightmap", m.lightmap); @@ -387137,7 +387141,7 @@ void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* model model_set_state(m); } - if (model_getpass() == RENDER_PASS_SHADOW) { + if (model_getpass() > RENDER_PASS_SHADOW_BEGIN && model_getpass() < RENDER_PASS_SHADOW_END) { shader = m.shadow_program; } diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index 2cb081e..a2c8096 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -1483,7 +1483,7 @@ light_t light() { l.innerCone = 0.85f;// 31 deg l.outerCone = 0.9f; // 25 deg l.cast_shadows = true; - l.shadow_distance = 100.0f; + l.shadow_distance = 200.0f; l.shadow_bias = 0.01f; return l; } @@ -1773,11 +1773,11 @@ void shadowmap_begin(shadowmap_t *s) { glGetIntegerv(GL_VIEWPORT, s->saved_vp); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb); - s->saved_pass = model_setpass(RENDER_PASS_SHADOW); s->step = 0; s->light_step = 0; s->cascade_index = 0; active_shadowmap = s; + s->saved_pass = model_getpass(); } static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { @@ -1798,6 +1798,7 @@ static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { copy44(s->PV, PV); s->shadow_technique = l->shadow_technique = SHADOW_VSM; + model_setpass(RENDER_PASS_SHADOW_VSM); } static array(vec3) frustum_corners = 0; @@ -1824,7 +1825,7 @@ void shadowmap_light_directional_calc_frustum_corners(mat44 cam_proj, mat44 cam_ } } -static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, float cam_fov, mat44 cam_view) { +static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, float cam_fov, float cam_far, mat44 cam_view) { if (dir != 0) { s->skip_render = true; return; @@ -1841,7 +1842,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo far_plane = l->shadow_distance * s->cascade_splits[s->cascade_index]; } else { near_plane = l->shadow_distance * s->cascade_splits[NUM_SHADOW_CASCADES-1]; - far_plane = l->shadow_distance; + far_plane = cam_far; } mat44 proj; perspective44(proj, cam_fov, window_width() / (float)window_height(), near_plane, far_plane); @@ -1878,25 +1879,11 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo maxZ = max(maxZ, corner.z); } - float zMult = 10.0f; - - // if (minZ < 0) { - // minZ *= zMult; - // } else { - // minZ /= zMult; - // } - // if (maxZ < 0) { - // maxZ /= zMult; - // } else { - // maxZ *= zMult; - // } - - mat44 P, PV; ortho44(P, minX, maxX, minY, maxY, - minZ, maxZ); + -maxZ, -minZ); multiply44x2(PV, P, V); @@ -1905,6 +1892,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo copy44(l->shadow_matrix[s->cascade_index], PV); s->shadow_technique = l->shadow_technique = SHADOW_PCF; + model_setpass(RENDER_PASS_SHADOW_PCF); } static inline @@ -1984,6 +1972,7 @@ bool shadowmap_step_finish(shadowmap_t *s) { s->step = 0; s->light_step++; s->cascade_index = 0; + model_setpass(s->saved_pass); return true; } @@ -2014,7 +2003,7 @@ void shadowmap_clear_fbo() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) { +void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, float cam_far, mat44 cam_view) { if (l->cast_shadows) { int step = s->step - 1; @@ -2023,7 +2012,7 @@ void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) } else if (l->type == LIGHT_SPOT) { shadowmap_light_point(s, l, step); } else if (l->type == LIGHT_DIRECTIONAL) { - shadowmap_light_directional(s, l, step, cam_fov, cam_view); + shadowmap_light_directional(s, l, step, cam_fov, cam_far, cam_view); } if (s->skip_render) { @@ -2057,7 +2046,6 @@ void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) void shadowmap_end(shadowmap_t *s) { glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]); glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb); - model_setpass(s->saved_pass); active_shadowmap = NULL; } @@ -4863,15 +4851,26 @@ void model_set_renderstates(model_t *m) { } // Shadow pass - renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW]; + renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; { - 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_enabled = 1; - shadow_rs->cull_face_mode = GL_BACK; - shadow_rs->front_face = GL_CW; - shadow_rs->depth_clamp_enabled = 1; + pcf_shadow_rs->blend_enabled = 1; + pcf_shadow_rs->blend_src = GL_SRC_ALPHA; + pcf_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + pcf_shadow_rs->cull_face_enabled = 1; + pcf_shadow_rs->cull_face_mode = GL_FRONT; + pcf_shadow_rs->front_face = GL_CCW; + pcf_shadow_rs->depth_clamp_enabled = 1; + } + + renderstate_t *vsm_shadow_rs = &m->rs[RENDER_PASS_SHADOW_VSM]; + { + vsm_shadow_rs->blend_enabled = 1; + vsm_shadow_rs->blend_src = GL_SRC_ALPHA; + vsm_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + vsm_shadow_rs->cull_face_enabled = 1; + vsm_shadow_rs->cull_face_mode = GL_BACK; + vsm_shadow_rs->front_face = GL_CW; + vsm_shadow_rs->depth_clamp_enabled = 1; } // Lightmap pass @@ -5352,7 +5351,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_ renderstate_apply(rs); } - if (rs_idx != RENDER_PASS_SHADOW) { + if (rs_idx < RENDER_PASS_SHADOW_BEGIN || rs_idx > RENDER_PASS_SHADOW_END) { if (m.shading != SHADING_PBR) { shader_texture_unit("u_texture2d", q->textures[i], texture_unit()); shader_texture("u_lightmap", m.lightmap); @@ -5407,7 +5406,7 @@ void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* model model_set_state(m); } - if (model_getpass() == RENDER_PASS_SHADOW) { + if (model_getpass() > RENDER_PASS_SHADOW_BEGIN && model_getpass() < RENDER_PASS_SHADOW_END) { shader = m.shadow_program; } diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index 1947b8e..3889369 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -383,7 +383,7 @@ API void shadowmap_destroy(shadowmap_t *s); API void shadowmap_begin(shadowmap_t *s); API bool shadowmap_step(shadowmap_t *s); -API void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view); //< can be called once per shadowmap_step +API void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, float cam_far, mat44 cam_view); //< can be called once per shadowmap_step API void shadowmap_end(shadowmap_t *s); // ----------------------------------------------------------------------------- @@ -717,7 +717,12 @@ enum RENDER_PASS { RENDER_PASS_TRANSPARENT, RENDER_PASS_OVERRIDES_BEGIN, - RENDER_PASS_SHADOW, + + RENDER_PASS_SHADOW_BEGIN, + RENDER_PASS_SHADOW_PCF, + RENDER_PASS_SHADOW_VSM, + RENDER_PASS_SHADOW_END, + RENDER_PASS_LIGHTMAP, RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this RENDER_PASS_OVERRIDES_END, diff --git a/engine/v4k.c b/engine/v4k.c index ca5af90..c8ed8db 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -18282,7 +18282,7 @@ light_t light() { l.innerCone = 0.85f;// 31 deg l.outerCone = 0.9f; // 25 deg l.cast_shadows = true; - l.shadow_distance = 100.0f; + l.shadow_distance = 200.0f; l.shadow_bias = 0.01f; return l; } @@ -18572,11 +18572,11 @@ void shadowmap_begin(shadowmap_t *s) { glGetIntegerv(GL_VIEWPORT, s->saved_vp); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb); - s->saved_pass = model_setpass(RENDER_PASS_SHADOW); s->step = 0; s->light_step = 0; s->cascade_index = 0; active_shadowmap = s; + s->saved_pass = model_getpass(); } static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { @@ -18597,6 +18597,7 @@ static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { copy44(s->PV, PV); s->shadow_technique = l->shadow_technique = SHADOW_VSM; + model_setpass(RENDER_PASS_SHADOW_VSM); } static array(vec3) frustum_corners = 0; @@ -18623,7 +18624,7 @@ void shadowmap_light_directional_calc_frustum_corners(mat44 cam_proj, mat44 cam_ } } -static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, float cam_fov, mat44 cam_view) { +static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, float cam_fov, float cam_far, mat44 cam_view) { if (dir != 0) { s->skip_render = true; return; @@ -18640,7 +18641,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo far_plane = l->shadow_distance * s->cascade_splits[s->cascade_index]; } else { near_plane = l->shadow_distance * s->cascade_splits[NUM_SHADOW_CASCADES-1]; - far_plane = l->shadow_distance; + far_plane = cam_far; } mat44 proj; perspective44(proj, cam_fov, window_width() / (float)window_height(), near_plane, far_plane); @@ -18677,25 +18678,11 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo maxZ = max(maxZ, corner.z); } - float zMult = 10.0f; - - // if (minZ < 0) { - // minZ *= zMult; - // } else { - // minZ /= zMult; - // } - // if (maxZ < 0) { - // maxZ /= zMult; - // } else { - // maxZ *= zMult; - // } - - mat44 P, PV; ortho44(P, minX, maxX, minY, maxY, - minZ, maxZ); + -maxZ, -minZ); multiply44x2(PV, P, V); @@ -18704,6 +18691,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo copy44(l->shadow_matrix[s->cascade_index], PV); s->shadow_technique = l->shadow_technique = SHADOW_PCF; + model_setpass(RENDER_PASS_SHADOW_PCF); } static inline @@ -18783,6 +18771,7 @@ bool shadowmap_step_finish(shadowmap_t *s) { s->step = 0; s->light_step++; s->cascade_index = 0; + model_setpass(s->saved_pass); return true; } @@ -18813,7 +18802,7 @@ void shadowmap_clear_fbo() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) { +void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, float cam_far, mat44 cam_view) { if (l->cast_shadows) { int step = s->step - 1; @@ -18822,7 +18811,7 @@ void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) } else if (l->type == LIGHT_SPOT) { shadowmap_light_point(s, l, step); } else if (l->type == LIGHT_DIRECTIONAL) { - shadowmap_light_directional(s, l, step, cam_fov, cam_view); + shadowmap_light_directional(s, l, step, cam_fov, cam_far, cam_view); } if (s->skip_render) { @@ -18856,7 +18845,6 @@ void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view) void shadowmap_end(shadowmap_t *s) { glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]); glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb); - model_setpass(s->saved_pass); active_shadowmap = NULL; } @@ -21662,15 +21650,26 @@ void model_set_renderstates(model_t *m) { } // Shadow pass - renderstate_t *shadow_rs = &m->rs[RENDER_PASS_SHADOW]; + renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; { - 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_enabled = 1; - shadow_rs->cull_face_mode = GL_BACK; - shadow_rs->front_face = GL_CW; - shadow_rs->depth_clamp_enabled = 1; + pcf_shadow_rs->blend_enabled = 1; + pcf_shadow_rs->blend_src = GL_SRC_ALPHA; + pcf_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + pcf_shadow_rs->cull_face_enabled = 1; + pcf_shadow_rs->cull_face_mode = GL_FRONT; + pcf_shadow_rs->front_face = GL_CCW; + pcf_shadow_rs->depth_clamp_enabled = 1; + } + + renderstate_t *vsm_shadow_rs = &m->rs[RENDER_PASS_SHADOW_VSM]; + { + vsm_shadow_rs->blend_enabled = 1; + vsm_shadow_rs->blend_src = GL_SRC_ALPHA; + vsm_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; + vsm_shadow_rs->cull_face_enabled = 1; + vsm_shadow_rs->cull_face_mode = GL_BACK; + vsm_shadow_rs->front_face = GL_CW; + vsm_shadow_rs->depth_clamp_enabled = 1; } // Lightmap pass @@ -22151,7 +22150,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_ renderstate_apply(rs); } - if (rs_idx != RENDER_PASS_SHADOW) { + if (rs_idx < RENDER_PASS_SHADOW_BEGIN || rs_idx > RENDER_PASS_SHADOW_END) { if (m.shading != SHADING_PBR) { shader_texture_unit("u_texture2d", q->textures[i], texture_unit()); shader_texture("u_lightmap", m.lightmap); @@ -22206,7 +22205,7 @@ void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* model model_set_state(m); } - if (model_getpass() == RENDER_PASS_SHADOW) { + if (model_getpass() > RENDER_PASS_SHADOW_BEGIN && model_getpass() < RENDER_PASS_SHADOW_END) { shader = m.shadow_program; } diff --git a/engine/v4k.h b/engine/v4k.h index 4be6b76..841eac2 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -3418,7 +3418,7 @@ API void shadowmap_destroy(shadowmap_t *s); API void shadowmap_begin(shadowmap_t *s); API bool shadowmap_step(shadowmap_t *s); -API void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, mat44 cam_view); //< can be called once per shadowmap_step +API void shadowmap_light(shadowmap_t *s, light_t *l, float cam_fov, float cam_far, mat44 cam_view); //< can be called once per shadowmap_step API void shadowmap_end(shadowmap_t *s); // ----------------------------------------------------------------------------- @@ -3752,7 +3752,12 @@ enum RENDER_PASS { RENDER_PASS_TRANSPARENT, RENDER_PASS_OVERRIDES_BEGIN, - RENDER_PASS_SHADOW, + + RENDER_PASS_SHADOW_BEGIN, + RENDER_PASS_SHADOW_PCF, + RENDER_PASS_SHADOW_VSM, + RENDER_PASS_SHADOW_END, + RENDER_PASS_LIGHTMAP, RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this RENDER_PASS_OVERRIDES_END,