improve csm

main
Dominik Madarász 2024-08-30 10:19:57 +02:00
parent 7edd72015c
commit 8d2fd2660e
8 changed files with 127 additions and 111 deletions

View File

@ -1205,7 +1205,7 @@ typedef struct shadowmap_t {
void shadowmap_destroy(shadowmap_t *s); void shadowmap_destroy(shadowmap_t *s);
void shadowmap_begin(shadowmap_t *s); void shadowmap_begin(shadowmap_t *s);
bool shadowmap_step(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); 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(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); 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_OPAQUE,
RENDER_PASS_TRANSPARENT, RENDER_PASS_TRANSPARENT,
RENDER_PASS_OVERRIDES_BEGIN, 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_LIGHTMAP,
RENDER_PASS_CUSTOM, RENDER_PASS_CUSTOM,
RENDER_PASS_OVERRIDES_END, RENDER_PASS_OVERRIDES_END,

View File

@ -51,7 +51,7 @@ int main(int argc, char** argv) {
light_t lit4 = light(); { light_t lit4 = light(); {
lit4.type = LIGHT_DIRECTIONAL; lit4.type = LIGHT_DIRECTIONAL;
lit4.cast_shadows = true; lit4.cast_shadows = true;
lit4.shadow_distance = 2000.0f; // lit4.shadow_distance = 2000.0f;
lit4.diffuse = vec3(1, 0.7, 0.8); lit4.diffuse = vec3(1, 0.7, 0.8);
} }
@ -87,6 +87,7 @@ int main(int argc, char** argv) {
initialized = 1; initialized = 1;
sky = skybox(flag("--mie") ? 0 : SKY_DIRS[SKY_DIR], 0); sky = skybox(flag("--mie") ? 0 : SKY_DIRS[SKY_DIR], 0);
sm = shadowmap(512, 2048); sm = shadowmap(512, 2048);
// sm.blur_pcf = 0;
mdl = model(OBJ_MDLS[OBJ_MDL], 0); mdl = model(OBJ_MDLS[OBJ_MDL], 0);
shader_bind(mdl.program); shader_bind(mdl.program);
cubemap_sh_shader(&sky.cubemap); cubemap_sh_shader(&sky.cubemap);
@ -166,7 +167,7 @@ int main(int argc, char** argv) {
{ {
for (int i = 0; i < array_count(lights); i++) { for (int i = 0; i < array_count(lights); i++) {
while (shadowmap_step(&sm)) { 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); model_render(mdl, cam.proj, cam.view, mdl.pivot, 0);
} }
} }

View File

@ -59,7 +59,7 @@ float shadow_pcf(float distance, vec3 lightDir, int light_index) {
// Calculate bias // Calculate bias
vec3 normal = normalize(vneye.xyz); vec3 normal = normalize(vneye.xyz);
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); 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) { if (cascade_index == NUM_SHADOW_CASCADES-1) {
bias *= 1 / (u_cascade_distances[NUM_SHADOW_CASCADES-1] * bias_modifier); bias *= 1 / (u_cascade_distances[NUM_SHADOW_CASCADES-1] * bias_modifier);
} else { } else {
@ -69,15 +69,15 @@ float shadow_pcf(float distance, vec3 lightDir, int light_index) {
// PCF // PCF
float shadow = 0.0; float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(shadowMap2D[index], 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; 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; return 1.0 - shadow;
} }

View File

@ -17351,7 +17351,7 @@ API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_begin(shadowmap_t *s); API void shadowmap_begin(shadowmap_t *s);
API bool shadowmap_step(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); API void shadowmap_end(shadowmap_t *s);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -17685,7 +17685,12 @@ enum RENDER_PASS {
RENDER_PASS_TRANSPARENT, RENDER_PASS_TRANSPARENT,
RENDER_PASS_OVERRIDES_BEGIN, 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_LIGHTMAP,
RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this
RENDER_PASS_OVERRIDES_END, RENDER_PASS_OVERRIDES_END,
@ -383213,7 +383218,7 @@ light_t light() {
l.innerCone = 0.85f;// 31 deg l.innerCone = 0.85f;// 31 deg
l.outerCone = 0.9f; // 25 deg l.outerCone = 0.9f; // 25 deg
l.cast_shadows = true; l.cast_shadows = true;
l.shadow_distance = 100.0f; l.shadow_distance = 200.0f;
l.shadow_bias = 0.01f; l.shadow_bias = 0.01f;
return l; return l;
} }
@ -383503,11 +383508,11 @@ void shadowmap_begin(shadowmap_t *s) {
glGetIntegerv(GL_VIEWPORT, s->saved_vp); glGetIntegerv(GL_VIEWPORT, s->saved_vp);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb);
s->saved_pass = model_setpass(RENDER_PASS_SHADOW);
s->step = 0; s->step = 0;
s->light_step = 0; s->light_step = 0;
s->cascade_index = 0; s->cascade_index = 0;
active_shadowmap = s; active_shadowmap = s;
s->saved_pass = model_getpass();
} }
static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { 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); copy44(s->PV, PV);
s->shadow_technique = l->shadow_technique = SHADOW_VSM; s->shadow_technique = l->shadow_technique = SHADOW_VSM;
model_setpass(RENDER_PASS_SHADOW_VSM);
} }
static array(vec3) frustum_corners = 0; 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) { if (dir != 0) {
s->skip_render = true; s->skip_render = true;
return; 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]; far_plane = l->shadow_distance * s->cascade_splits[s->cascade_index];
} else { } else {
near_plane = l->shadow_distance * s->cascade_splits[NUM_SHADOW_CASCADES-1]; 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); 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); 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; mat44 P, PV;
ortho44(P, ortho44(P,
minX, maxX, minX, maxX,
minY, maxY, minY, maxY,
minZ, maxZ); -maxZ, -minZ);
multiply44x2(PV, P, V); 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); copy44(l->shadow_matrix[s->cascade_index], PV);
s->shadow_technique = l->shadow_technique = SHADOW_PCF; s->shadow_technique = l->shadow_technique = SHADOW_PCF;
model_setpass(RENDER_PASS_SHADOW_PCF);
} }
static inline static inline
@ -383714,6 +383707,7 @@ bool shadowmap_step_finish(shadowmap_t *s) {
s->step = 0; s->step = 0;
s->light_step++; s->light_step++;
s->cascade_index = 0; s->cascade_index = 0;
model_setpass(s->saved_pass);
return true; return true;
} }
@ -383744,7 +383738,7 @@ void shadowmap_clear_fbo() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 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) { if (l->cast_shadows) {
int step = s->step - 1; 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) { } else if (l->type == LIGHT_SPOT) {
shadowmap_light_point(s, l, step); shadowmap_light_point(s, l, step);
} else if (l->type == LIGHT_DIRECTIONAL) { } 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) { 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) { void shadowmap_end(shadowmap_t *s) {
glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]); glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]);
glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb); glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb);
model_setpass(s->saved_pass);
active_shadowmap = NULL; active_shadowmap = NULL;
} }
@ -386593,15 +386586,26 @@ void model_set_renderstates(model_t *m) {
} }
// Shadow pass // 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; pcf_shadow_rs->blend_enabled = 1;
shadow_rs->blend_src = GL_SRC_ALPHA; pcf_shadow_rs->blend_src = GL_SRC_ALPHA;
shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; pcf_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
shadow_rs->cull_face_enabled = 1; pcf_shadow_rs->cull_face_enabled = 1;
shadow_rs->cull_face_mode = GL_BACK; pcf_shadow_rs->cull_face_mode = GL_FRONT;
shadow_rs->front_face = GL_CW; pcf_shadow_rs->front_face = GL_CCW;
shadow_rs->depth_clamp_enabled = 1; 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 // 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); 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) { if (m.shading != SHADING_PBR) {
shader_texture_unit("u_texture2d", q->textures[i], texture_unit()); shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
shader_texture("u_lightmap", m.lightmap); 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); 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; shader = m.shadow_program;
} }

View File

@ -1483,7 +1483,7 @@ light_t light() {
l.innerCone = 0.85f;// 31 deg l.innerCone = 0.85f;// 31 deg
l.outerCone = 0.9f; // 25 deg l.outerCone = 0.9f; // 25 deg
l.cast_shadows = true; l.cast_shadows = true;
l.shadow_distance = 100.0f; l.shadow_distance = 200.0f;
l.shadow_bias = 0.01f; l.shadow_bias = 0.01f;
return l; return l;
} }
@ -1773,11 +1773,11 @@ void shadowmap_begin(shadowmap_t *s) {
glGetIntegerv(GL_VIEWPORT, s->saved_vp); glGetIntegerv(GL_VIEWPORT, s->saved_vp);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb);
s->saved_pass = model_setpass(RENDER_PASS_SHADOW);
s->step = 0; s->step = 0;
s->light_step = 0; s->light_step = 0;
s->cascade_index = 0; s->cascade_index = 0;
active_shadowmap = s; active_shadowmap = s;
s->saved_pass = model_getpass();
} }
static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { 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); copy44(s->PV, PV);
s->shadow_technique = l->shadow_technique = SHADOW_VSM; s->shadow_technique = l->shadow_technique = SHADOW_VSM;
model_setpass(RENDER_PASS_SHADOW_VSM);
} }
static array(vec3) frustum_corners = 0; 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) { if (dir != 0) {
s->skip_render = true; s->skip_render = true;
return; 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]; far_plane = l->shadow_distance * s->cascade_splits[s->cascade_index];
} else { } else {
near_plane = l->shadow_distance * s->cascade_splits[NUM_SHADOW_CASCADES-1]; 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); 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); 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; mat44 P, PV;
ortho44(P, ortho44(P,
minX, maxX, minX, maxX,
minY, maxY, minY, maxY,
minZ, maxZ); -maxZ, -minZ);
multiply44x2(PV, P, V); 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); copy44(l->shadow_matrix[s->cascade_index], PV);
s->shadow_technique = l->shadow_technique = SHADOW_PCF; s->shadow_technique = l->shadow_technique = SHADOW_PCF;
model_setpass(RENDER_PASS_SHADOW_PCF);
} }
static inline static inline
@ -1984,6 +1972,7 @@ bool shadowmap_step_finish(shadowmap_t *s) {
s->step = 0; s->step = 0;
s->light_step++; s->light_step++;
s->cascade_index = 0; s->cascade_index = 0;
model_setpass(s->saved_pass);
return true; return true;
} }
@ -2014,7 +2003,7 @@ void shadowmap_clear_fbo() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 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) { if (l->cast_shadows) {
int step = s->step - 1; 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) { } else if (l->type == LIGHT_SPOT) {
shadowmap_light_point(s, l, step); shadowmap_light_point(s, l, step);
} else if (l->type == LIGHT_DIRECTIONAL) { } 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) { 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) { void shadowmap_end(shadowmap_t *s) {
glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]); glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]);
glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb); glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb);
model_setpass(s->saved_pass);
active_shadowmap = NULL; active_shadowmap = NULL;
} }
@ -4863,15 +4851,26 @@ void model_set_renderstates(model_t *m) {
} }
// Shadow pass // 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; pcf_shadow_rs->blend_enabled = 1;
shadow_rs->blend_src = GL_SRC_ALPHA; pcf_shadow_rs->blend_src = GL_SRC_ALPHA;
shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; pcf_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
shadow_rs->cull_face_enabled = 1; pcf_shadow_rs->cull_face_enabled = 1;
shadow_rs->cull_face_mode = GL_BACK; pcf_shadow_rs->cull_face_mode = GL_FRONT;
shadow_rs->front_face = GL_CW; pcf_shadow_rs->front_face = GL_CCW;
shadow_rs->depth_clamp_enabled = 1; 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 // 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); 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) { if (m.shading != SHADING_PBR) {
shader_texture_unit("u_texture2d", q->textures[i], texture_unit()); shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
shader_texture("u_lightmap", m.lightmap); 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); 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; shader = m.shadow_program;
} }

View File

@ -383,7 +383,7 @@ API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_begin(shadowmap_t *s); API void shadowmap_begin(shadowmap_t *s);
API bool shadowmap_step(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); API void shadowmap_end(shadowmap_t *s);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -717,7 +717,12 @@ enum RENDER_PASS {
RENDER_PASS_TRANSPARENT, RENDER_PASS_TRANSPARENT,
RENDER_PASS_OVERRIDES_BEGIN, 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_LIGHTMAP,
RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this
RENDER_PASS_OVERRIDES_END, RENDER_PASS_OVERRIDES_END,

View File

@ -18282,7 +18282,7 @@ light_t light() {
l.innerCone = 0.85f;// 31 deg l.innerCone = 0.85f;// 31 deg
l.outerCone = 0.9f; // 25 deg l.outerCone = 0.9f; // 25 deg
l.cast_shadows = true; l.cast_shadows = true;
l.shadow_distance = 100.0f; l.shadow_distance = 200.0f;
l.shadow_bias = 0.01f; l.shadow_bias = 0.01f;
return l; return l;
} }
@ -18572,11 +18572,11 @@ void shadowmap_begin(shadowmap_t *s) {
glGetIntegerv(GL_VIEWPORT, s->saved_vp); glGetIntegerv(GL_VIEWPORT, s->saved_vp);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s->saved_fb);
s->saved_pass = model_setpass(RENDER_PASS_SHADOW);
s->step = 0; s->step = 0;
s->light_step = 0; s->light_step = 0;
s->cascade_index = 0; s->cascade_index = 0;
active_shadowmap = s; active_shadowmap = s;
s->saved_pass = model_getpass();
} }
static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) { 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); copy44(s->PV, PV);
s->shadow_technique = l->shadow_technique = SHADOW_VSM; s->shadow_technique = l->shadow_technique = SHADOW_VSM;
model_setpass(RENDER_PASS_SHADOW_VSM);
} }
static array(vec3) frustum_corners = 0; 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) { if (dir != 0) {
s->skip_render = true; s->skip_render = true;
return; 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]; far_plane = l->shadow_distance * s->cascade_splits[s->cascade_index];
} else { } else {
near_plane = l->shadow_distance * s->cascade_splits[NUM_SHADOW_CASCADES-1]; 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); 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); 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; mat44 P, PV;
ortho44(P, ortho44(P,
minX, maxX, minX, maxX,
minY, maxY, minY, maxY,
minZ, maxZ); -maxZ, -minZ);
multiply44x2(PV, P, V); 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); copy44(l->shadow_matrix[s->cascade_index], PV);
s->shadow_technique = l->shadow_technique = SHADOW_PCF; s->shadow_technique = l->shadow_technique = SHADOW_PCF;
model_setpass(RENDER_PASS_SHADOW_PCF);
} }
static inline static inline
@ -18783,6 +18771,7 @@ bool shadowmap_step_finish(shadowmap_t *s) {
s->step = 0; s->step = 0;
s->light_step++; s->light_step++;
s->cascade_index = 0; s->cascade_index = 0;
model_setpass(s->saved_pass);
return true; return true;
} }
@ -18813,7 +18802,7 @@ void shadowmap_clear_fbo() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 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) { if (l->cast_shadows) {
int step = s->step - 1; 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) { } else if (l->type == LIGHT_SPOT) {
shadowmap_light_point(s, l, step); shadowmap_light_point(s, l, step);
} else if (l->type == LIGHT_DIRECTIONAL) { } 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) { 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) { void shadowmap_end(shadowmap_t *s) {
glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]); glViewport(s->saved_vp[0], s->saved_vp[1], s->saved_vp[2], s->saved_vp[3]);
glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb); glBindFramebuffer(GL_FRAMEBUFFER, s->saved_fb);
model_setpass(s->saved_pass);
active_shadowmap = NULL; active_shadowmap = NULL;
} }
@ -21662,15 +21650,26 @@ void model_set_renderstates(model_t *m) {
} }
// Shadow pass // 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; pcf_shadow_rs->blend_enabled = 1;
shadow_rs->blend_src = GL_SRC_ALPHA; pcf_shadow_rs->blend_src = GL_SRC_ALPHA;
shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA; pcf_shadow_rs->blend_dst = GL_ONE_MINUS_SRC_ALPHA;
shadow_rs->cull_face_enabled = 1; pcf_shadow_rs->cull_face_enabled = 1;
shadow_rs->cull_face_mode = GL_BACK; pcf_shadow_rs->cull_face_mode = GL_FRONT;
shadow_rs->front_face = GL_CW; pcf_shadow_rs->front_face = GL_CCW;
shadow_rs->depth_clamp_enabled = 1; 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 // 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); 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) { if (m.shading != SHADING_PBR) {
shader_texture_unit("u_texture2d", q->textures[i], texture_unit()); shader_texture_unit("u_texture2d", q->textures[i], texture_unit());
shader_texture("u_lightmap", m.lightmap); 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); 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; shader = m.shadow_program;
} }

View File

@ -3418,7 +3418,7 @@ API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_begin(shadowmap_t *s); API void shadowmap_begin(shadowmap_t *s);
API bool shadowmap_step(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); API void shadowmap_end(shadowmap_t *s);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -3752,7 +3752,12 @@ enum RENDER_PASS {
RENDER_PASS_TRANSPARENT, RENDER_PASS_TRANSPARENT,
RENDER_PASS_OVERRIDES_BEGIN, 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_LIGHTMAP,
RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this RENDER_PASS_CUSTOM, // make sure to apply renderstate before calling this
RENDER_PASS_OVERRIDES_END, RENDER_PASS_OVERRIDES_END,