improve shadowmap factor blending

main
Dominik Madarász 2024-08-30 14:25:47 +02:00
parent 6c678a478a
commit 320e653558
10 changed files with 143 additions and 119 deletions

View File

@ -1187,7 +1187,6 @@ typedef struct shadowmap_t {
int cascade_index; int cascade_index;
unsigned shadow_technique; unsigned shadow_technique;
float cascade_splits[6]; float cascade_splits[6];
float cascade_distances[6];
bool blur_pcf; bool blur_pcf;
float blur_scale; float blur_scale;
bool skip_render; bool skip_render;
@ -1197,6 +1196,7 @@ typedef struct shadowmap_t {
handle fbos[6], texture, depth_texture; handle fbos[6], texture, depth_texture;
handle fbo_2d[6], texture_2d[6], depth_texture_2d[6]; handle fbo_2d[6], texture_2d[6], depth_texture_2d[6];
handle blur_fbo_2d, blur_texture_2d; handle blur_fbo_2d, blur_texture_2d;
float cascade_distances[6];
} maps[MAX_LIGHTS]; } maps[MAX_LIGHTS];
handle saved_fb; handle saved_fb;
handle saved_pass; handle saved_pass;

View File

@ -28,7 +28,7 @@ int main() {
// fx: load all post fx files in all subdirs. // fx: load all post fx files in all subdirs.
fx_load("fx**.fs"); fx_load("fx**.fs");
fx_enable(fx_find("fxTonemapACES.fs"), 1); // fx_enable(fx_find("fxTonemapACES.fs"), 1);
// load video, RGB texture, no audio // 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); 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_move(obj6, vec3(-9,-4,3));
object_scale(obj6, vec3(3,3,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_t* sun = scene_spawn_light();
light_type(sun, LIGHT_DIRECTIONAL); light_type(sun, LIGHT_DIRECTIONAL);
sun->dir = vec3(0.5,-1,-0.5); 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 // load skybox
@ -131,9 +131,9 @@ int main() {
shadertoy_render(&sh, window_delta()); shadertoy_render(&sh, window_delta());
// draw scene // draw scene
// fx_begin(); fx_begin();
scene_render(SCENE_FOREGROUND|SCENE_BACKGROUND|SCENE_UPDATE_SH_COEF|SCENE_CAST_SHADOWS); scene_render(SCENE_FOREGROUND|SCENE_BACKGROUND|SCENE_UPDATE_SH_COEF|SCENE_CAST_SHADOWS);
// fx_end(); fx_end();
// fps camera // fps camera
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R); bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);

View File

@ -32,15 +32,15 @@ int main(int argc, char** argv) {
light_t lit = light(); { light_t lit = light(); {
lit.type = LIGHT_POINT; lit.type = LIGHT_POINT;
lit.cast_shadows = true; lit.cast_shadows = true;
// lit.shadow_distance = 5.0f; // lit.shadow_distance = 1.0f;
// lit.falloff.linear = 3.0f; lit.falloff.linear = 2.0f;
} }
light_t lit2 = light(); { light_t lit2 = light(); {
lit2.type = LIGHT_POINT; lit2.type = LIGHT_POINT;
lit2.cast_shadows = true; lit2.cast_shadows = true;
lit2.diffuse = vec3(1, 0.7, 0.8); lit2.diffuse = vec3(1, 0.7, 0.8);
// lit2.shadow_distance = 5.0f; // lit2.shadow_distance = 1.0f;
// lit2.falloff.linear = 3.0f; lit2.falloff.linear = 2.0f;
} }
light_t lit3 = light(); { light_t lit3 = light(); {
lit3.type = LIGHT_SPOT; lit3.type = LIGHT_SPOT;
@ -106,7 +106,7 @@ int main(int argc, char** argv) {
enum { enum {
POINT, SPOT, DIR, ALL POINT, SPOT, DIR, ALL
}; };
static unsigned mode = DIR; static unsigned mode = ALL;
if (input_down(KEY_1)) mode = POINT; if (input_down(KEY_1)) mode = POINT;
if (input_down(KEY_2)) mode = SPOT; if (input_down(KEY_2)) mode = SPOT;

View File

@ -19,7 +19,7 @@ struct light_t {
float innerCone; float innerCone;
float outerCone; float outerCone;
bool processed_shadows; bool processed_shadows;
// falloff // falloff
float constant; float constant;
float linear; float linear;

View File

@ -3,8 +3,7 @@
in vec4 vpeye; in vec4 vpeye;
in vec4 vneye; in vec4 vneye;
uniform bool u_shadow_receiver; uniform bool u_shadow_receiver;
uniform float u_cascade_splits[NUM_SHADOW_CASCADES]; uniform float u_cascade_distances[MAX_LIGHTS * NUM_SHADOW_CASCADES];
uniform float u_cascade_distances[NUM_SHADOW_CASCADES];
uniform samplerCube shadowMap[MAX_LIGHTS]; uniform samplerCube shadowMap[MAX_LIGHTS];
uniform sampler2D shadowMap2D[MAX_LIGHTS * NUM_SHADOW_CASCADES]; 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) { float shadow_vsm(float distance, vec3 dir, int light_index) {
distance = distance/20; distance = distance/20;
vec2 moments = texture(shadowMap[light_index], dir).rg; 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 // Surface is fully lit. as the current fragment is before the light occluder
if (distance <= moments.x) { 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) // How likely this pixel is to be lit (p_max)
float variance = moments.y - (moments.x*moments.x); float variance = moments.y - (moments.x*moments.x);
//variance = max(variance, 0.000002); //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 d = distance - moments.x;
float p_max = variance / (variance + d*d); 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) { float shadow_pcf(float distance, vec3 lightDir, int light_index) {
// Determine which cascade to use // Determine which cascade to use
int cascade_index = -1; 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]) { if (distance < u_cascade_distances[i]) {
cascade_index = i; cascade_index = i;
break; break;
} }
} }
if (cascade_index == -1) { 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 matrix_index = cascade_index - min_cascades_range;
int index = light_index * NUM_SHADOW_CASCADES + cascade_index;
vec4 fragPosLightSpace = u_lights[light_index].shadow_matrix[matrix_index] * vec4(v_position_ws, 1.0);
// Perform perspective divide // Perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
@ -63,18 +71,18 @@ 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);
bias *= 1 / (u_cascade_distances[cascade_index] * bias_modifier[cascade_index]); bias *= 1 / (u_cascade_distances[cascade_index] * bias_modifier[matrix_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[cascade_index], 0);
#if 1 #if 1
for(int x = -3; x <= 3; ++x) for(int x = -3; x <= 3; ++x)
{ {
for(int y = -3; y <= 3; ++y) 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; 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) 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; 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) { vec4 shadowmap(in vec4 peye, in vec4 neye) {
float shadowFactor = 0.0;
vec3 fragment = vec3(peye); 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++) { for (int i = 0; i < u_num_lights; i++) {
light_t light = u_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.processed_shadows) {
if (light.type == LIGHT_DIRECTIONAL) { 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) { } else if (light.type == LIGHT_POINT || light.type == LIGHT_SPOT) {
total_casters++;
vec3 light_pos = (view * vec4(light.pos, 1.0)).xyz; vec3 light_pos = (view * vec4(light.pos, 1.0)).xyz;
vec3 dir = light_pos - fragment; vec3 dir = light_pos - fragment;
vec4 sc = inv_view * vec4(dir, 0.0); 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) { // Normalize the shadow factor based on total weight
shadowFactor = 1.0; if (totalWeight > 0.0) {
} else { shadowFactor = pow(shadowFactor, 1.0 / totalWeight);
shadowFactor /= total_casters;
} }
return vec4(vec3(shadowFactor), 1.0); return vec4(vec3(shadowFactor), 1.0);

View File

@ -17327,7 +17327,6 @@ typedef struct shadowmap_t {
int cascade_index; int cascade_index;
unsigned shadow_technique; unsigned shadow_technique;
float cascade_splits[NUM_SHADOW_CASCADES]; float cascade_splits[NUM_SHADOW_CASCADES];
float cascade_distances[NUM_SHADOW_CASCADES];
bool blur_pcf; bool blur_pcf;
float blur_scale; float blur_scale;
@ -17340,6 +17339,7 @@ typedef struct shadowmap_t {
handle fbos[6], texture, depth_texture; handle fbos[6], texture, depth_texture;
handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES]; handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES];
handle blur_fbo_2d, blur_texture_2d; handle blur_fbo_2d, blur_texture_2d;
float cascade_distances[NUM_SHADOW_CASCADES];
} maps[MAX_LIGHTS]; } maps[MAX_LIGHTS];
handle saved_fb; handle saved_fb;
@ -381736,6 +381736,7 @@ AUTOTEST {
#line 1 "v4k_render.c" #line 1 "v4k_render.c"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// opengl // opengl
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #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[1] = 0.3f;
s.cascade_splits[2] = 0.5f; s.cascade_splits[2] = 0.5f;
s.cascade_splits[3] = 0.7f; s.cascade_splits[3] = 0.7f;
s.cascade_splits[5] = 1.0f; s.cascade_splits[4] = 1.0f;
s.cascade_splits[6] = 1.0f; /* sticks to camera far plane */ s.cascade_splits[5] = 1.0f; /* sticks to camera far plane */
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s.saved_fb); 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 #else
for (int i = 0; i < MAX_LIGHTS; i++) { for (int i = 0; i < MAX_LIGHTS; i++) {
s.maps[i].shadow_technique = 0xFFFF; s.maps[i].shadow_technique = 0xFFFF;
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
s.maps[i].cascade_distances[j] = 0.0f;
}
} }
#endif #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)); 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 minX = FLT_MAX, maxX = FLT_MIN;
float minY = FLT_MAX, maxY = 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 static inline
bool shadowmap_step_finish(shadowmap_t *s) { bool shadowmap_step_finish(shadowmap_t *s) {
if (s->shadow_technique == SHADOW_PCF) { 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->cascade_index++;
s->step = 0; s->step = 0;
return false; 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->step++;
s->skip_render = false; s->skip_render = false;
s->lights_pushed = 0; 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]); glBindFramebuffer(GL_FRAMEBUFFER, s->maps[s->light_step].fbos[step]);
shadowmap_clear_fbo(); 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("cameraToShadowView", sm->V);
shader_mat44("cameraToShadowProjector", sm->PV); shader_mat44("cameraToShadowProjector", sm->PV);
shader_int("shadow_technique", sm->shadow_technique); shader_int("shadow_technique", sm->shadow_technique);
} } else {
// shadow receiving
// shadow receiving if (m.shadow_map && m.shadow_receiver) {
if (m.shadow_map && m.shadow_receiver) { shader_bool("u_shadow_receiver", GL_TRUE);
shader_bool("u_shadow_receiver", m.shadow_receiver); for (int i = 0; i < MAX_LIGHTS; i++) {
for (int i = 0; i < MAX_LIGHTS; i++) { shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture);
shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
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_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]);
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]);
} }
} }
} else if (m.shadow_map == NULL || !m.shadow_receiver) {
else if (m.shadow_map == NULL || !m.shadow_receiver) { for (int i = 0; i < MAX_LIGHTS; i++) {
for (int i = 0; i < MAX_LIGHTS; i++) { shader_cubemap(va("shadowMap[%d]", i), 0);
shader_cubemap(va("shadowMap[%d]", i), 0); for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit());
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) { if (m.shading == SHADING_PBR) {
@ -386629,7 +386632,9 @@ void model_set_renderstates(model_t *m) {
// Shadow pass // Shadow pass
renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; 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_enabled = 1;
pcf_shadow_rs->cull_face_mode = GL_BACK; pcf_shadow_rs->cull_face_mode = GL_BACK;
pcf_shadow_rs->front_face = GL_CW; pcf_shadow_rs->front_face = GL_CW;

View File

@ -1,4 +1,5 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// opengl // opengl
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #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[1] = 0.3f;
s.cascade_splits[2] = 0.5f; s.cascade_splits[2] = 0.5f;
s.cascade_splits[3] = 0.7f; s.cascade_splits[3] = 0.7f;
s.cascade_splits[5] = 1.0f; s.cascade_splits[4] = 1.0f;
s.cascade_splits[6] = 1.0f; /* sticks to camera far plane */ s.cascade_splits[5] = 1.0f; /* sticks to camera far plane */
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s.saved_fb); 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 #else
for (int i = 0; i < MAX_LIGHTS; i++) { for (int i = 0; i < MAX_LIGHTS; i++) {
s.maps[i].shadow_technique = 0xFFFF; s.maps[i].shadow_technique = 0xFFFF;
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
s.maps[i].cascade_distances[j] = 0.0f;
}
} }
#endif #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)); 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 minX = FLT_MAX, maxX = FLT_MIN;
float minY = FLT_MAX, maxY = 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 static inline
bool shadowmap_step_finish(shadowmap_t *s) { bool shadowmap_step_finish(shadowmap_t *s) {
if (s->shadow_technique == SHADOW_PCF) { 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->cascade_index++;
s->step = 0; s->step = 0;
return false; 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->step++;
s->skip_render = false; s->skip_render = false;
s->lights_pushed = 0; 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]); glBindFramebuffer(GL_FRAMEBUFFER, s->maps[s->light_step].fbos[step]);
shadowmap_clear_fbo(); 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("cameraToShadowView", sm->V);
shader_mat44("cameraToShadowProjector", sm->PV); shader_mat44("cameraToShadowProjector", sm->PV);
shader_int("shadow_technique", sm->shadow_technique); shader_int("shadow_technique", sm->shadow_technique);
} } else {
// shadow receiving
// shadow receiving if (m.shadow_map && m.shadow_receiver) {
if (m.shadow_map && m.shadow_receiver) { shader_bool("u_shadow_receiver", GL_TRUE);
shader_bool("u_shadow_receiver", m.shadow_receiver); for (int i = 0; i < MAX_LIGHTS; i++) {
for (int i = 0; i < MAX_LIGHTS; i++) { shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture);
shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
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_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]);
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]);
} }
} }
} else if (m.shadow_map == NULL || !m.shadow_receiver) {
else if (m.shadow_map == NULL || !m.shadow_receiver) { for (int i = 0; i < MAX_LIGHTS; i++) {
for (int i = 0; i < MAX_LIGHTS; i++) { shader_cubemap(va("shadowMap[%d]", i), 0);
shader_cubemap(va("shadowMap[%d]", i), 0); for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit());
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) { if (m.shading == SHADING_PBR) {
@ -4892,7 +4895,9 @@ void model_set_renderstates(model_t *m) {
// Shadow pass // Shadow pass
renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; 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_enabled = 1;
pcf_shadow_rs->cull_face_mode = GL_BACK; pcf_shadow_rs->cull_face_mode = GL_BACK;
pcf_shadow_rs->front_face = GL_CW; pcf_shadow_rs->front_face = GL_CW;

View File

@ -359,7 +359,6 @@ typedef struct shadowmap_t {
int cascade_index; int cascade_index;
unsigned shadow_technique; unsigned shadow_technique;
float cascade_splits[NUM_SHADOW_CASCADES]; float cascade_splits[NUM_SHADOW_CASCADES];
float cascade_distances[NUM_SHADOW_CASCADES];
bool blur_pcf; bool blur_pcf;
float blur_scale; float blur_scale;
@ -372,6 +371,7 @@ typedef struct shadowmap_t {
handle fbos[6], texture, depth_texture; handle fbos[6], texture, depth_texture;
handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES]; handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES];
handle blur_fbo_2d, blur_texture_2d; handle blur_fbo_2d, blur_texture_2d;
float cascade_distances[NUM_SHADOW_CASCADES];
} maps[MAX_LIGHTS]; } maps[MAX_LIGHTS];
handle saved_fb; handle saved_fb;

View File

@ -16798,6 +16798,7 @@ AUTOTEST {
#line 1 "v4k_render.c" #line 1 "v4k_render.c"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// opengl // opengl
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #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[1] = 0.3f;
s.cascade_splits[2] = 0.5f; s.cascade_splits[2] = 0.5f;
s.cascade_splits[3] = 0.7f; s.cascade_splits[3] = 0.7f;
s.cascade_splits[5] = 1.0f; s.cascade_splits[4] = 1.0f;
s.cascade_splits[6] = 1.0f; /* sticks to camera far plane */ s.cascade_splits[5] = 1.0f; /* sticks to camera far plane */
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &s.saved_fb); 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 #else
for (int i = 0; i < MAX_LIGHTS; i++) { for (int i = 0; i < MAX_LIGHTS; i++) {
s.maps[i].shadow_technique = 0xFFFF; s.maps[i].shadow_technique = 0xFFFF;
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
s.maps[i].cascade_distances[j] = 0.0f;
}
} }
#endif #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)); 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 minX = FLT_MAX, maxX = FLT_MIN;
float minY = FLT_MAX, maxY = 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 static inline
bool shadowmap_step_finish(shadowmap_t *s) { bool shadowmap_step_finish(shadowmap_t *s) {
if (s->shadow_technique == SHADOW_PCF) { 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->cascade_index++;
s->step = 0; s->step = 0;
return false; 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->step++;
s->skip_render = false; s->skip_render = false;
s->lights_pushed = 0; 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]); glBindFramebuffer(GL_FRAMEBUFFER, s->maps[s->light_step].fbos[step]);
shadowmap_clear_fbo(); 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("cameraToShadowView", sm->V);
shader_mat44("cameraToShadowProjector", sm->PV); shader_mat44("cameraToShadowProjector", sm->PV);
shader_int("shadow_technique", sm->shadow_technique); shader_int("shadow_technique", sm->shadow_technique);
} } else {
// shadow receiving
// shadow receiving if (m.shadow_map && m.shadow_receiver) {
if (m.shadow_map && m.shadow_receiver) { shader_bool("u_shadow_receiver", GL_TRUE);
shader_bool("u_shadow_receiver", m.shadow_receiver); for (int i = 0; i < MAX_LIGHTS; i++) {
for (int i = 0; i < MAX_LIGHTS; i++) { shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture);
shader_cubemap(va("shadowMap[%d]", i), m.shadow_map->maps[i].texture); for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
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_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]);
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]);
} }
} }
} else if (m.shadow_map == NULL || !m.shadow_receiver) {
else if (m.shadow_map == NULL || !m.shadow_receiver) { for (int i = 0; i < MAX_LIGHTS; i++) {
for (int i = 0; i < MAX_LIGHTS; i++) { shader_cubemap(va("shadowMap[%d]", i), 0);
shader_cubemap(va("shadowMap[%d]", i), 0); for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) { shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit());
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) { if (m.shading == SHADING_PBR) {
@ -21691,7 +21694,9 @@ void model_set_renderstates(model_t *m) {
// Shadow pass // Shadow pass
renderstate_t *pcf_shadow_rs = &m->rs[RENDER_PASS_SHADOW_PCF]; 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_enabled = 1;
pcf_shadow_rs->cull_face_mode = GL_BACK; pcf_shadow_rs->cull_face_mode = GL_BACK;
pcf_shadow_rs->front_face = GL_CW; pcf_shadow_rs->front_face = GL_CW;

View File

@ -3394,7 +3394,6 @@ typedef struct shadowmap_t {
int cascade_index; int cascade_index;
unsigned shadow_technique; unsigned shadow_technique;
float cascade_splits[NUM_SHADOW_CASCADES]; float cascade_splits[NUM_SHADOW_CASCADES];
float cascade_distances[NUM_SHADOW_CASCADES];
bool blur_pcf; bool blur_pcf;
float blur_scale; float blur_scale;
@ -3407,6 +3406,7 @@ typedef struct shadowmap_t {
handle fbos[6], texture, depth_texture; handle fbos[6], texture, depth_texture;
handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES]; handle fbo_2d[NUM_SHADOW_CASCADES], texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES];
handle blur_fbo_2d, blur_texture_2d; handle blur_fbo_2d, blur_texture_2d;
float cascade_distances[NUM_SHADOW_CASCADES];
} maps[MAX_LIGHTS]; } maps[MAX_LIGHTS];
handle saved_fb; handle saved_fb;