diff --git a/bind/v4k.lua b/bind/v4k.lua index 05ca980..218060f 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -1187,7 +1187,6 @@ typedef struct shadowmap_t { int cascade_index; unsigned shadow_technique; float cascade_splits[6]; - float cascade_distances[6]; bool blur_pcf; float blur_scale; bool skip_render; @@ -1197,6 +1196,7 @@ typedef struct shadowmap_t { handle fbos[6], texture, depth_texture; handle fbo_2d[6], texture_2d[6], depth_texture_2d[6]; handle blur_fbo_2d, blur_texture_2d; + float cascade_distances[6]; } maps[MAX_LIGHTS]; handle saved_fb; handle saved_pass; diff --git a/demos/09-shadows-scene.c b/demos/09-shadows-scene.c index 21b65f3..eb1d6f8 100644 --- a/demos/09-shadows-scene.c +++ b/demos/09-shadows-scene.c @@ -28,7 +28,7 @@ int main() { // fx: load all post fx files in all subdirs. fx_load("fx**.fs"); - fx_enable(fx_find("fxTonemapACES.fs"), 1); + // fx_enable(fx_find("fxTonemapACES.fs"), 1); // load video, RGB texture, no audio video_t *v = video( "pexels-pachon-in-motion-17486489.mp4", VIDEO_RGB | VIDEO_NO_AUDIO | VIDEO_LOOP ); video_seek(v, 30); @@ -102,15 +102,15 @@ int main() { object_move(obj6, vec3(-9,-4,3)); object_scale(obj6, vec3(3,3,3)); - // create point light - // scene_spawn_light(); // sun - // light_t* l = scene_spawn_light(); - // light_type(l, LIGHT_POINT); - // l->diffuse = vec3(0,0,0); light_t* sun = scene_spawn_light(); light_type(sun, LIGHT_DIRECTIONAL); sun->dir = vec3(0.5,-1,-0.5); + + // create point light + // light_t* l = scene_spawn_light(); + // light_type(l, LIGHT_POINT); + // l->diffuse = vec3(0,0,0); // load skybox @@ -131,9 +131,9 @@ int main() { shadertoy_render(&sh, window_delta()); // draw scene - // fx_begin(); + fx_begin(); scene_render(SCENE_FOREGROUND|SCENE_BACKGROUND|SCENE_UPDATE_SH_COEF|SCENE_CAST_SHADOWS); - // fx_end(); + fx_end(); // fps camera bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R); diff --git a/demos/09-shadows.c b/demos/09-shadows.c index 0668459..538fdfa 100644 --- a/demos/09-shadows.c +++ b/demos/09-shadows.c @@ -32,15 +32,15 @@ int main(int argc, char** argv) { light_t lit = light(); { lit.type = LIGHT_POINT; lit.cast_shadows = true; - // lit.shadow_distance = 5.0f; - // lit.falloff.linear = 3.0f; + // lit.shadow_distance = 1.0f; + lit.falloff.linear = 2.0f; } light_t lit2 = light(); { lit2.type = LIGHT_POINT; lit2.cast_shadows = true; lit2.diffuse = vec3(1, 0.7, 0.8); - // lit2.shadow_distance = 5.0f; - // lit2.falloff.linear = 3.0f; + // lit2.shadow_distance = 1.0f; + lit2.falloff.linear = 2.0f; } light_t lit3 = light(); { lit3.type = LIGHT_SPOT; @@ -106,7 +106,7 @@ int main(int argc, char** argv) { enum { POINT, SPOT, DIR, ALL }; - static unsigned mode = DIR; + static unsigned mode = ALL; if (input_down(KEY_1)) mode = POINT; if (input_down(KEY_2)) mode = SPOT; diff --git a/engine/art/shaderlib/light.glsl b/engine/art/shaderlib/light.glsl index 87dcaa8..e919882 100644 --- a/engine/art/shaderlib/light.glsl +++ b/engine/art/shaderlib/light.glsl @@ -19,7 +19,7 @@ struct light_t { float innerCone; float outerCone; bool processed_shadows; - + // falloff float constant; float linear; diff --git a/engine/art/shaderlib/shadowmap.glsl b/engine/art/shaderlib/shadowmap.glsl index 8fd0eef..39b2b26 100644 --- a/engine/art/shaderlib/shadowmap.glsl +++ b/engine/art/shaderlib/shadowmap.glsl @@ -3,8 +3,7 @@ in vec4 vpeye; in vec4 vneye; uniform bool u_shadow_receiver; -uniform float u_cascade_splits[NUM_SHADOW_CASCADES]; -uniform float u_cascade_distances[NUM_SHADOW_CASCADES]; +uniform float u_cascade_distances[MAX_LIGHTS * NUM_SHADOW_CASCADES]; uniform samplerCube shadowMap[MAX_LIGHTS]; uniform sampler2D shadowMap2D[MAX_LIGHTS * NUM_SHADOW_CASCADES]; @@ -14,6 +13,11 @@ const float bias_modifier[NUM_SHADOW_CASCADES] = float[NUM_SHADOW_CASCADES](0.95 float shadow_vsm(float distance, vec3 dir, int light_index) { distance = distance/20; vec2 moments = texture(shadowMap[light_index], dir).rg; + + // If the shadow map is sampled outside of its bounds, return 1.0 + if (moments.x == 1.0 && moments.y == 1.0) { + return 1.0; + } // Surface is fully lit. as the current fragment is before the light occluder if (distance <= moments.x) { @@ -24,7 +28,8 @@ float shadow_vsm(float distance, vec3 dir, int light_index) { // How likely this pixel is to be lit (p_max) float variance = moments.y - (moments.x*moments.x); //variance = max(variance, 0.000002); - variance = max(variance, 0.00002); + // variance = max(variance, 0.00002); + variance = max(variance, 0.002); float d = distance - moments.x; float p_max = variance / (variance + d*d); @@ -35,18 +40,21 @@ float shadow_vsm(float distance, vec3 dir, int light_index) { float shadow_pcf(float distance, vec3 lightDir, int light_index) { // Determine which cascade to use int cascade_index = -1; - for (int i = 0; i < NUM_SHADOW_CASCADES; i++) { + int min_cascades_range = light_index * NUM_SHADOW_CASCADES; + int max_cascades_range = min_cascades_range + NUM_SHADOW_CASCADES; + for (int i = min_cascades_range; i < max_cascades_range; i++) { if (distance < u_cascade_distances[i]) { cascade_index = i; break; } } if (cascade_index == -1) { - cascade_index = NUM_SHADOW_CASCADES - 1; + cascade_index = max_cascades_range - 1; } - vec4 fragPosLightSpace = u_lights[light_index].shadow_matrix[cascade_index] * vec4(v_position_ws, 1.0); - int index = light_index * NUM_SHADOW_CASCADES + cascade_index; + int matrix_index = cascade_index - min_cascades_range; + + vec4 fragPosLightSpace = u_lights[light_index].shadow_matrix[matrix_index] * vec4(v_position_ws, 1.0); // Perform perspective divide vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; @@ -63,18 +71,18 @@ 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); - bias *= 1 / (u_cascade_distances[cascade_index] * bias_modifier[cascade_index]); + bias *= 1 / (u_cascade_distances[cascade_index] * bias_modifier[matrix_index]); // PCF float shadow = 0.0; - vec2 texelSize = 1.0 / textureSize(shadowMap2D[index], 0); + vec2 texelSize = 1.0 / textureSize(shadowMap2D[cascade_index], 0); #if 1 for(int x = -3; x <= 3; ++x) { for(int y = -3; y <= 3; ++y) { - float pcfDepth = texture(shadowMap2D[index], projCoords.xy + vec2(x, y) * texelSize * (rand(vec2(projCoords.x + x, projCoords.y + y))*0.75f + 0.25f)).r; + float pcfDepth = texture(shadowMap2D[cascade_index], projCoords.xy + vec2(x, y) * texelSize * (rand(vec2(projCoords.x + x, projCoords.y + y))*0.75f + 0.25f)).r; shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; } } @@ -84,7 +92,7 @@ float shadow_pcf(float distance, vec3 lightDir, int light_index) { { for(int y = -1; y <= 1; ++y) { - float pcfDepth = texture(shadowMap2D[index], projCoords.xy + vec2(x, y) * texelSize).r; + float pcfDepth = texture(shadowMap2D[cascade_index], projCoords.xy + vec2(x, y) * texelSize).r; shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; } } @@ -94,33 +102,34 @@ float shadow_pcf(float distance, vec3 lightDir, int light_index) { } vec4 shadowmap(in vec4 peye, in vec4 neye) { - float shadowFactor = 0.0; vec3 fragment = vec3(peye); - int total_casters = 0; + float shadowFactor = 1.0; + float totalWeight = 0.0; for (int i = 0; i < u_num_lights; i++) { light_t light = u_lights[i]; - float factor = 0.0; + float factor = 1.0; + float weight = 1.0; if (light.processed_shadows) { if (light.type == LIGHT_DIRECTIONAL) { - total_casters++; - factor += shadow_pcf(-peye.z, light.dir, i); + factor = shadow_pcf(-peye.z, light.dir, i); + weight = 0.7; } else if (light.type == LIGHT_POINT || light.type == LIGHT_SPOT) { - total_casters++; vec3 light_pos = (view * vec4(light.pos, 1.0)).xyz; vec3 dir = light_pos - fragment; vec4 sc = inv_view * vec4(dir, 0.0); - factor += shadow_vsm(length(dir), -sc.xyz, i); + factor = shadow_vsm(length(dir), -sc.xyz, i); + weight = 1.0; } + shadowFactor *= mix(1.0, factor, weight); + totalWeight += weight; } - shadowFactor += factor; } - if (total_casters == 0) { - shadowFactor = 1.0; - } else { - shadowFactor /= total_casters; + // Normalize the shadow factor based on total weight + if (totalWeight > 0.0) { + shadowFactor = pow(shadowFactor, 1.0 / totalWeight); } return vec4(vec3(shadowFactor), 1.0); diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 4c16446..2e0f013 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -17327,7 +17327,6 @@ typedef struct shadowmap_t { int cascade_index; unsigned shadow_technique; float cascade_splits[NUM_SHADOW_CASCADES]; - float cascade_distances[NUM_SHADOW_CASCADES]; bool blur_pcf; float blur_scale; @@ -17340,6 +17339,7 @@ typedef struct shadowmap_t { handle fbos[6], texture, depth_texture; handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES]; handle blur_fbo_2d, blur_texture_2d; + float cascade_distances[NUM_SHADOW_CASCADES]; } maps[MAX_LIGHTS]; handle saved_fb; @@ -381736,6 +381736,7 @@ AUTOTEST { #line 1 "v4k_render.c" // ----------------------------------------------------------------------------- + // opengl #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 @@ -383443,8 +383444,8 @@ shadowmap_t shadowmap(int vsm_texture_width, int pcf_texture_width) { // = 512, s.cascade_splits[1] = 0.3f; s.cascade_splits[2] = 0.5f; s.cascade_splits[3] = 0.7f; - s.cascade_splits[5] = 1.0f; - s.cascade_splits[6] = 1.0f; /* sticks to camera far plane */ + s.cascade_splits[4] = 1.0f; + s.cascade_splits[5] = 1.0f; /* sticks to camera far plane */ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s.saved_fb); @@ -383455,6 +383456,9 @@ shadowmap_t shadowmap(int vsm_texture_width, int pcf_texture_width) { // = 512, #else for (int i = 0; i < MAX_LIGHTS; i++) { s.maps[i].shadow_technique = 0xFFFF; + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + s.maps[i].cascade_distances[j] = 0.0f; + } } #endif @@ -383599,7 +383603,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo center = scale3(center, 1.0f / array_count(frustum_corners)); - s->cascade_distances[s->cascade_index] = far_plane; + s->maps[s->light_step].cascade_distances[s->cascade_index] = far_plane; float minX = FLT_MAX, maxX = FLT_MIN; float minY = FLT_MAX, maxY = FLT_MIN; @@ -383717,7 +383721,7 @@ void shadowmap_blur_pcf(shadowmap_t *s, int light_index) { static inline bool shadowmap_step_finish(shadowmap_t *s) { if (s->shadow_technique == SHADOW_PCF) { - if (s->cascade_index < NUM_SHADOW_CASCADES - 1) { + if (s->cascade_index < NUM_SHADOW_CASCADES-1) { s->cascade_index++; s->step = 0; return false; @@ -383742,10 +383746,6 @@ bool shadowmap_step(shadowmap_t *s) { } } - unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->pcf_texture_width; - - glViewport(0, 0, texture_width, texture_width); - s->step++; s->skip_render = false; s->lights_pushed = 0; @@ -383807,6 +383807,9 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view) glBindFramebuffer(GL_FRAMEBUFFER, s->maps[s->light_step].fbos[step]); shadowmap_clear_fbo(); } + + unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->pcf_texture_width; + glViewport(0, 0, texture_width, texture_width); } } @@ -385989,28 +385992,28 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, shader_mat44("cameraToShadowView", sm->V); shader_mat44("cameraToShadowProjector", sm->PV); shader_int("shadow_technique", sm->shadow_technique); - } + } else { + // shadow receiving - // shadow receiving - if (m.shadow_map && m.shadow_receiver) { - shader_bool("u_shadow_receiver", m.shadow_receiver); - for (int i = 0; i < MAX_LIGHTS; i++) { - shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); - for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { - shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].texture_2d[j], texture_unit()); - shader_float(va("u_cascade_splits[%d]", j), m.shadow_map->cascade_splits[j]); - shader_float(va("u_cascade_distances[%d]", j), m.shadow_map->cascade_distances[j]); + if (m.shadow_map && m.shadow_receiver) { + shader_bool("u_shadow_receiver", GL_TRUE); + for (int i = 0; i < MAX_LIGHTS; i++) { + shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].texture_2d[j], texture_unit()); + shader_float(va("u_cascade_distances[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].cascade_distances[j]); + } } } - } - else if (m.shadow_map == NULL || !m.shadow_receiver) { - for (int i = 0; i < MAX_LIGHTS; i++) { - shader_cubemap(va("shadowMap[%d]", i), 0); - for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { - shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit()); + else if (m.shadow_map == NULL || !m.shadow_receiver) { + for (int i = 0; i < MAX_LIGHTS; i++) { + shader_cubemap(va("shadowMap[%d]", i), 0); + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit()); + } } + shader_bool("u_shadow_receiver", GL_FALSE); } - shader_bool("u_shadow_receiver", GL_FALSE); } if (m.shading == SHADING_PBR) { @@ -386629,7 +386632,9 @@ void model_set_renderstates(model_t *m) { // Shadow pass renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; { - pcf_shadow_rs->blend_enabled = 0; + 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_BACK; pcf_shadow_rs->front_face = GL_CW; diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index a29b7ae..b023d17 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -1,4 +1,5 @@ // ----------------------------------------------------------------------------- + // opengl #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 @@ -1706,8 +1707,8 @@ shadowmap_t shadowmap(int vsm_texture_width, int pcf_texture_width) { // = 512, s.cascade_splits[1] = 0.3f; s.cascade_splits[2] = 0.5f; s.cascade_splits[3] = 0.7f; - s.cascade_splits[5] = 1.0f; - s.cascade_splits[6] = 1.0f; /* sticks to camera far plane */ + s.cascade_splits[4] = 1.0f; + s.cascade_splits[5] = 1.0f; /* sticks to camera far plane */ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s.saved_fb); @@ -1718,6 +1719,9 @@ shadowmap_t shadowmap(int vsm_texture_width, int pcf_texture_width) { // = 512, #else for (int i = 0; i < MAX_LIGHTS; i++) { s.maps[i].shadow_technique = 0xFFFF; + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + s.maps[i].cascade_distances[j] = 0.0f; + } } #endif @@ -1862,7 +1866,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo center = scale3(center, 1.0f / array_count(frustum_corners)); - s->cascade_distances[s->cascade_index] = far_plane; + s->maps[s->light_step].cascade_distances[s->cascade_index] = far_plane; float minX = FLT_MAX, maxX = FLT_MIN; float minY = FLT_MAX, maxY = FLT_MIN; @@ -1980,7 +1984,7 @@ void shadowmap_blur_pcf(shadowmap_t *s, int light_index) { static inline bool shadowmap_step_finish(shadowmap_t *s) { if (s->shadow_technique == SHADOW_PCF) { - if (s->cascade_index < NUM_SHADOW_CASCADES - 1) { + if (s->cascade_index < NUM_SHADOW_CASCADES-1) { s->cascade_index++; s->step = 0; return false; @@ -2005,10 +2009,6 @@ bool shadowmap_step(shadowmap_t *s) { } } - unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->pcf_texture_width; - - glViewport(0, 0, texture_width, texture_width); - s->step++; s->skip_render = false; s->lights_pushed = 0; @@ -2070,6 +2070,9 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view) glBindFramebuffer(GL_FRAMEBUFFER, s->maps[s->light_step].fbos[step]); shadowmap_clear_fbo(); } + + unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->pcf_texture_width; + glViewport(0, 0, texture_width, texture_width); } } @@ -4252,28 +4255,28 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, shader_mat44("cameraToShadowView", sm->V); shader_mat44("cameraToShadowProjector", sm->PV); shader_int("shadow_technique", sm->shadow_technique); - } + } else { + // shadow receiving - // shadow receiving - if (m.shadow_map && m.shadow_receiver) { - shader_bool("u_shadow_receiver", m.shadow_receiver); - for (int i = 0; i < MAX_LIGHTS; i++) { - shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); - for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { - shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].texture_2d[j], texture_unit()); - shader_float(va("u_cascade_splits[%d]", j), m.shadow_map->cascade_splits[j]); - shader_float(va("u_cascade_distances[%d]", j), m.shadow_map->cascade_distances[j]); + if (m.shadow_map && m.shadow_receiver) { + shader_bool("u_shadow_receiver", GL_TRUE); + for (int i = 0; i < MAX_LIGHTS; i++) { + shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].texture_2d[j], texture_unit()); + shader_float(va("u_cascade_distances[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].cascade_distances[j]); + } } } - } - else if (m.shadow_map == NULL || !m.shadow_receiver) { - for (int i = 0; i < MAX_LIGHTS; i++) { - shader_cubemap(va("shadowMap[%d]", i), 0); - for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { - shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit()); + else if (m.shadow_map == NULL || !m.shadow_receiver) { + for (int i = 0; i < MAX_LIGHTS; i++) { + shader_cubemap(va("shadowMap[%d]", i), 0); + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit()); + } } + shader_bool("u_shadow_receiver", GL_FALSE); } - shader_bool("u_shadow_receiver", GL_FALSE); } if (m.shading == SHADING_PBR) { @@ -4892,7 +4895,9 @@ void model_set_renderstates(model_t *m) { // Shadow pass renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; { - pcf_shadow_rs->blend_enabled = 0; + 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_BACK; pcf_shadow_rs->front_face = GL_CW; diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index 9e792a2..9ce7e55 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -359,7 +359,6 @@ typedef struct shadowmap_t { int cascade_index; unsigned shadow_technique; float cascade_splits[NUM_SHADOW_CASCADES]; - float cascade_distances[NUM_SHADOW_CASCADES]; bool blur_pcf; float blur_scale; @@ -372,6 +371,7 @@ typedef struct shadowmap_t { handle fbos[6], texture, depth_texture; handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES]; handle blur_fbo_2d, blur_texture_2d; + float cascade_distances[NUM_SHADOW_CASCADES]; } maps[MAX_LIGHTS]; handle saved_fb; diff --git a/engine/v4k.c b/engine/v4k.c index da3b04d..31016c5 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -16798,6 +16798,7 @@ AUTOTEST { #line 1 "v4k_render.c" // ----------------------------------------------------------------------------- + // opengl #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 @@ -18505,8 +18506,8 @@ shadowmap_t shadowmap(int vsm_texture_width, int pcf_texture_width) { // = 512, s.cascade_splits[1] = 0.3f; s.cascade_splits[2] = 0.5f; s.cascade_splits[3] = 0.7f; - s.cascade_splits[5] = 1.0f; - s.cascade_splits[6] = 1.0f; /* sticks to camera far plane */ + s.cascade_splits[4] = 1.0f; + s.cascade_splits[5] = 1.0f; /* sticks to camera far plane */ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s.saved_fb); @@ -18517,6 +18518,9 @@ shadowmap_t shadowmap(int vsm_texture_width, int pcf_texture_width) { // = 512, #else for (int i = 0; i < MAX_LIGHTS; i++) { s.maps[i].shadow_technique = 0xFFFF; + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + s.maps[i].cascade_distances[j] = 0.0f; + } } #endif @@ -18661,7 +18665,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo center = scale3(center, 1.0f / array_count(frustum_corners)); - s->cascade_distances[s->cascade_index] = far_plane; + s->maps[s->light_step].cascade_distances[s->cascade_index] = far_plane; float minX = FLT_MAX, maxX = FLT_MIN; float minY = FLT_MAX, maxY = FLT_MIN; @@ -18779,7 +18783,7 @@ void shadowmap_blur_pcf(shadowmap_t *s, int light_index) { static inline bool shadowmap_step_finish(shadowmap_t *s) { if (s->shadow_technique == SHADOW_PCF) { - if (s->cascade_index < NUM_SHADOW_CASCADES - 1) { + if (s->cascade_index < NUM_SHADOW_CASCADES-1) { s->cascade_index++; s->step = 0; return false; @@ -18804,10 +18808,6 @@ bool shadowmap_step(shadowmap_t *s) { } } - unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->pcf_texture_width; - - glViewport(0, 0, texture_width, texture_width); - s->step++; s->skip_render = false; s->lights_pushed = 0; @@ -18869,6 +18869,9 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view) glBindFramebuffer(GL_FRAMEBUFFER, s->maps[s->light_step].fbos[step]); shadowmap_clear_fbo(); } + + unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->pcf_texture_width; + glViewport(0, 0, texture_width, texture_width); } } @@ -21051,28 +21054,28 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view, shader_mat44("cameraToShadowView", sm->V); shader_mat44("cameraToShadowProjector", sm->PV); shader_int("shadow_technique", sm->shadow_technique); - } + } else { + // shadow receiving - // shadow receiving - if (m.shadow_map && m.shadow_receiver) { - shader_bool("u_shadow_receiver", m.shadow_receiver); - for (int i = 0; i < MAX_LIGHTS; i++) { - shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); - for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { - shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].texture_2d[j], texture_unit()); - shader_float(va("u_cascade_splits[%d]", j), m.shadow_map->cascade_splits[j]); - shader_float(va("u_cascade_distances[%d]", j), m.shadow_map->cascade_distances[j]); + if (m.shadow_map && m.shadow_receiver) { + shader_bool("u_shadow_receiver", GL_TRUE); + for (int i = 0; i < MAX_LIGHTS; i++) { + shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].texture_2d[j], texture_unit()); + shader_float(va("u_cascade_distances[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].cascade_distances[j]); + } } } - } - else if (m.shadow_map == NULL || !m.shadow_receiver) { - for (int i = 0; i < MAX_LIGHTS; i++) { - shader_cubemap(va("shadowMap[%d]", i), 0); - for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { - shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit()); + else if (m.shadow_map == NULL || !m.shadow_receiver) { + for (int i = 0; i < MAX_LIGHTS; i++) { + shader_cubemap(va("shadowMap[%d]", i), 0); + for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { + shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit()); + } } + shader_bool("u_shadow_receiver", GL_FALSE); } - shader_bool("u_shadow_receiver", GL_FALSE); } if (m.shading == SHADING_PBR) { @@ -21691,7 +21694,9 @@ void model_set_renderstates(model_t *m) { // Shadow pass renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; { - pcf_shadow_rs->blend_enabled = 0; + 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_BACK; pcf_shadow_rs->front_face = GL_CW; diff --git a/engine/v4k.h b/engine/v4k.h index 3434419..9cae95d 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -3394,7 +3394,6 @@ typedef struct shadowmap_t { int cascade_index; unsigned shadow_technique; float cascade_splits[NUM_SHADOW_CASCADES]; - float cascade_distances[NUM_SHADOW_CASCADES]; bool blur_pcf; float blur_scale; @@ -3407,6 +3406,7 @@ typedef struct shadowmap_t { handle fbos[6], texture, depth_texture; handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES]; handle blur_fbo_2d, blur_texture_2d; + float cascade_distances[NUM_SHADOW_CASCADES]; } maps[MAX_LIGHTS]; handle saved_fb;