You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
Refactored shadowmapping.
- Made shadow bias size independent, so it will remain when changing light or camera size. - Implemented normal offset bias, which greatly enhances quality. - Added transmission to subsurface scattering - Reimplemented shadow filter modes Closes #17260
This commit is contained in:
@@ -285,6 +285,13 @@ void main() {
|
||||
frag_color = color;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_LINEARIZE_DEPTH_COPY
|
||||
float depth = texture(source_color, uv_interp, 0.0).r;
|
||||
depth = depth * 2.0 - 1.0;
|
||||
depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
|
||||
frag_color = vec4(depth / blur.camera_z_far);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_SSAO_MERGE
|
||||
vec4 color = texture(source_color, uv_interp, 0.0);
|
||||
float ssao = texture(source_ssao, uv_interp, 0.0).r;
|
||||
|
||||
@@ -57,6 +57,7 @@ void main() {
|
||||
}
|
||||
|
||||
float depth = texture(source_cube, normal).r;
|
||||
depth_buffer = depth;
|
||||
|
||||
// absolute values for direction cosines, bigger value equals closer to basis axis
|
||||
vec3 unorm = abs(normal);
|
||||
@@ -80,7 +81,7 @@ void main() {
|
||||
|
||||
depth = 2.0 * depth - 1.0;
|
||||
float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
|
||||
depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
|
||||
depth_buffer = (linear_depth * depth_fix) / params.z_far;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -244,19 +244,13 @@ VERTEX_SHADER_CODE
|
||||
|
||||
//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
|
||||
|
||||
vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
|
||||
vec3 vtx = vertex_interp;
|
||||
float distance = length(vtx);
|
||||
vtx = normalize(vtx);
|
||||
vtx.xy /= 1.0 - vtx.z;
|
||||
vtx.z = (distance / scene_data.z_far);
|
||||
vtx.z = vtx.z * 2.0 - 1.0;
|
||||
|
||||
vertex_interp = vtx;
|
||||
#else
|
||||
|
||||
float z_ofs = scene_data.z_offset;
|
||||
z_ofs += max(0.0, 1.0 - abs(normalize(normal_interp).z)) * scene_data.z_slope_scale;
|
||||
vertex_interp.z -= z_ofs;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -267,6 +261,14 @@ VERTEX_SHADER_CODE
|
||||
#else
|
||||
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_RENDER_DEPTH
|
||||
if (scene_data.pancake_shadows) {
|
||||
if (gl_Position.z <= 0.00001) {
|
||||
gl_Position.z = 0.00001;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
@@ -315,6 +317,11 @@ layout(location = 8) in float dp_clip;
|
||||
#define world_normal_matrix instances.data[instance_index].normal_transform
|
||||
#define projection_matrix scene_data.projection_matrix
|
||||
|
||||
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
|
||||
//both required for transmittance to be enabled
|
||||
#define LIGHT_TRANSMITTANCE_USED
|
||||
#endif
|
||||
|
||||
#ifdef USE_MATERIAL_UNIFORMS
|
||||
layout(set = 5, binding = 0, std140) uniform MaterialUniforms{
|
||||
/* clang-format off */
|
||||
@@ -434,9 +441,16 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
|
||||
return mix(vec3(dielectric), albedo, vec3(metallic));
|
||||
}
|
||||
|
||||
void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
vec3 transmission,
|
||||
void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, vec3 shadow_attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
vec4 transmittance_color,
|
||||
float transmittance_depth,
|
||||
float transmittance_curve,
|
||||
float transmittance_boost,
|
||||
float transmittance_z,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
float rim, float rim_tint,
|
||||
@@ -538,16 +552,48 @@ LIGHT_SHADER_CODE
|
||||
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
|
||||
#endif
|
||||
|
||||
diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
|
||||
diffuse_light += light_color * diffuse_color * shadow_attenuation * diffuse_brdf_NL * attenuation;
|
||||
|
||||
#if defined(LIGHT_TRANSMISSION_USED)
|
||||
diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
|
||||
#if defined(LIGHT_BACKLIGHT_USED)
|
||||
diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
|
||||
#endif
|
||||
|
||||
#if defined(LIGHT_RIM_USED)
|
||||
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
|
||||
diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
|
||||
#endif
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
|
||||
#ifdef SSS_MODE_SKIN
|
||||
|
||||
{
|
||||
float scale = 8.25 / transmittance_depth;
|
||||
float d = scale * abs(transmittance_z);
|
||||
float dd = -d * d;
|
||||
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
|
||||
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
|
||||
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
|
||||
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
|
||||
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
|
||||
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
|
||||
|
||||
diffuse_light += profile * transmittance_color.a * diffuse_color * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI) * attenuation;
|
||||
}
|
||||
#else
|
||||
|
||||
if (transmittance_depth > 0.0) {
|
||||
float fade = clamp(abs(transmittance_z / transmittance_depth), 0.0, 1.0);
|
||||
|
||||
fade = pow(max(0.0, 1.0 - fade), transmittance_curve);
|
||||
fade *= clamp(transmittance_boost - NdotL, 0.0, 1.0);
|
||||
|
||||
diffuse_light += diffuse_color * transmittance_color.rgb * light_color * (1.0 / M_PI) * transmittance_color.a * fade * attenuation;
|
||||
}
|
||||
|
||||
#endif //SSS_MODE_SKIN
|
||||
|
||||
#endif //LIGHT_TRANSMITTANCE_USED
|
||||
}
|
||||
|
||||
if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
|
||||
@@ -562,7 +608,7 @@ LIGHT_SHADER_CODE
|
||||
blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
|
||||
float intensity = blinn;
|
||||
|
||||
specular_light += light_color * intensity * specular_blob_intensity * attenuation;
|
||||
specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
|
||||
|
||||
#elif defined(SPECULAR_PHONG)
|
||||
|
||||
@@ -573,7 +619,7 @@ LIGHT_SHADER_CODE
|
||||
phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
|
||||
float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
|
||||
|
||||
specular_light += light_color * intensity * specular_blob_intensity * attenuation;
|
||||
specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
|
||||
|
||||
#elif defined(SPECULAR_TOON)
|
||||
|
||||
@@ -582,7 +628,7 @@ LIGHT_SHADER_CODE
|
||||
float mid = 1.0 - roughness;
|
||||
mid *= mid;
|
||||
float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
|
||||
diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
|
||||
diffuse_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
|
||||
|
||||
#elif defined(SPECULAR_DISABLED)
|
||||
// none..
|
||||
@@ -613,7 +659,7 @@ LIGHT_SHADER_CODE
|
||||
|
||||
vec3 specular_brdf_NL = cNdotL * D * F * G;
|
||||
|
||||
specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
|
||||
specular_light += specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
|
||||
#endif
|
||||
|
||||
#if defined(LIGHT_CLEARCOAT_USED)
|
||||
@@ -627,12 +673,12 @@ LIGHT_SHADER_CODE
|
||||
|
||||
float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
|
||||
|
||||
specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
|
||||
specular_light += clearcoat_specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_SHADOW_TO_OPACITY
|
||||
alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0));
|
||||
alpha = min(alpha, clamp(1.0 - length(shadow_attenuation * attenuation), 0.0, 1.0));
|
||||
#endif
|
||||
|
||||
#endif //defined(USE_LIGHT_SHADER_CODE)
|
||||
@@ -642,51 +688,54 @@ LIGHT_SHADER_CODE
|
||||
|
||||
float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
|
||||
|
||||
//todo optimize
|
||||
vec2 pos = coord.xy;
|
||||
float depth = coord.z;
|
||||
|
||||
#ifdef SHADOW_MODE_PCF_13
|
||||
switch (scene_data.shadow_filter_mode) {
|
||||
case SHADOW_MODE_NO_FILTER: {
|
||||
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
||||
};
|
||||
case SHADOW_MODE_PCF5: {
|
||||
float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
|
||||
return avg * (1.0 / 5.0);
|
||||
};
|
||||
case SHADOW_MODE_PCF13: {
|
||||
|
||||
float avg = textureProj(shadow, vec4(pos, depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
|
||||
return avg * (1.0 / 13.0);
|
||||
#endif
|
||||
float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
|
||||
return avg * (1.0 / 13.0);
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef SHADOW_MODE_PCF_5
|
||||
|
||||
float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
|
||||
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
|
||||
return avg * (1.0 / 5.0);
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
|
||||
|
||||
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif //USE_NO_SHADOWS
|
||||
|
||||
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
vec3 transmission,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
vec4 transmittance_color,
|
||||
float transmittance_depth,
|
||||
float transmittance_curve,
|
||||
float transmittance_boost,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
float rim, float rim_tint,
|
||||
@@ -707,18 +756,33 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
||||
float normalized_distance = light_length * lights.data[idx].inv_radius;
|
||||
vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
|
||||
float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
|
||||
vec3 light_attenuation = vec3(omni_attenuation);
|
||||
float light_attenuation = omni_attenuation;
|
||||
vec3 shadow_attenuation = vec3(1.0);
|
||||
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
|
||||
color_specular.rgb *= attenuation_energy.y;
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
float transmittance_z = transmittance_depth; //no transmittance by default
|
||||
#endif
|
||||
|
||||
#ifndef USE_NO_SHADOWS
|
||||
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
|
||||
if (shadow_color_enabled.w > 0.5) {
|
||||
// there is a shadowmap
|
||||
|
||||
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
|
||||
float shadow_len = length(splane);
|
||||
splane = normalize(splane);
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
vec4 splane = (lights.data[idx].shadow_matrix * v);
|
||||
float shadow_len = length(splane.xyz);
|
||||
|
||||
{
|
||||
vec3 nofs = normal_interp * lights.data[idx].shadow_normal_bias / lights.data[idx].inv_radius;
|
||||
nofs *= (1.0 - max(0.0, dot(normalize(light_rel_vec), normalize(normal_interp))));
|
||||
v.xyz += nofs;
|
||||
splane = (lights.data[idx].shadow_matrix * v);
|
||||
}
|
||||
|
||||
splane.xyz = normalize(splane.xyz);
|
||||
vec4 clamp_rect = lights.data[idx].atlas_rect;
|
||||
|
||||
if (splane.z >= 0.0) {
|
||||
@@ -728,24 +792,60 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
||||
clamp_rect.y += clamp_rect.w;
|
||||
|
||||
} else {
|
||||
|
||||
splane.z = 1.0 - splane.z;
|
||||
}
|
||||
|
||||
splane.xy /= splane.z;
|
||||
|
||||
splane.xy = splane.xy * 0.5 + 0.5;
|
||||
splane.z = shadow_len * lights.data[idx].inv_radius;
|
||||
splane.z = (shadow_len - lights.data[idx].shadow_bias) * lights.data[idx].inv_radius;
|
||||
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
|
||||
splane.w = 1.0; //needed? i think it should be 1 already
|
||||
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
|
||||
|
||||
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
{
|
||||
|
||||
//redo shadowmapping, but shrink the model a bit to avoid arctifacts
|
||||
splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
|
||||
|
||||
shadow_len = length(splane);
|
||||
splane = normalize(splane);
|
||||
|
||||
if (splane.z >= 0.0) {
|
||||
|
||||
splane.z += 1.0;
|
||||
|
||||
} else {
|
||||
|
||||
splane.z = 1.0 - splane.z;
|
||||
}
|
||||
|
||||
splane.xy /= splane.z;
|
||||
splane.xy = splane.xy * 0.5 + 0.5;
|
||||
splane.z = shadow_len * lights.data[idx].inv_radius;
|
||||
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
|
||||
splane.w = 1.0; //needed? i think it should be 1 already
|
||||
|
||||
float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
|
||||
transmittance_z = (splane.z - shadow_z) / lights.data[idx].inv_radius;
|
||||
}
|
||||
#endif
|
||||
|
||||
shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
|
||||
}
|
||||
#endif //USE_NO_SHADOWS
|
||||
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
transmission,
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
transmittance_color,
|
||||
transmittance_depth,
|
||||
transmittance_curve,
|
||||
transmittance_boost,
|
||||
transmittance_z,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
rim * omni_attenuation, rim_tint,
|
||||
@@ -764,8 +864,14 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
||||
}
|
||||
|
||||
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
vec3 transmission,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
vec4 transmittance_color,
|
||||
float transmittance_depth,
|
||||
float transmittance_curve,
|
||||
float transmittance_boost,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
float rim, float rim_tint,
|
||||
@@ -792,7 +898,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
||||
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
|
||||
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
|
||||
spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
|
||||
vec3 light_attenuation = vec3(spot_attenuation);
|
||||
float light_attenuation = spot_attenuation;
|
||||
vec3 shadow_attenuation = vec3(1.0);
|
||||
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
|
||||
color_specular.rgb *= attenuation_energy.y;
|
||||
|
||||
@@ -801,22 +908,58 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
|
||||
//use projector texture
|
||||
}
|
||||
*/
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
float transmittance_z = transmittance_depth;
|
||||
#endif
|
||||
|
||||
#ifndef USE_NO_SHADOWS
|
||||
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
|
||||
if (shadow_color_enabled.w > 0.5) {
|
||||
//there is a shadowmap
|
||||
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
v.xyz -= spot_dir * lights.data[idx].shadow_bias;
|
||||
|
||||
float depth_bias_scale = 1.0 / (max(0.0001, dot(spot_dir, -light_rel_vec) * lights.data[idx].inv_radius)); //the closer to the light origin, the more you have to offset to reach 1px in the map
|
||||
vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * lights.data[idx].shadow_normal_bias * depth_bias_scale;
|
||||
normal_bias -= spot_dir * dot(spot_dir, normal_bias); //only XY, no Z
|
||||
v.xyz += normal_bias;
|
||||
|
||||
vec4 splane = (lights.data[idx].shadow_matrix * v);
|
||||
splane /= splane.w;
|
||||
splane.z = dot(spot_dir, v.xyz - lights.data[idx].position) * lights.data[idx].inv_radius;
|
||||
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
|
||||
|
||||
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
|
||||
shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
{
|
||||
|
||||
splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
|
||||
splane /= splane.w;
|
||||
|
||||
float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
|
||||
//reconstruct depth
|
||||
shadow_z / lights.data[idx].inv_radius;
|
||||
//distance to light plane
|
||||
float z = dot(spot_dir, -light_rel_vec);
|
||||
transmittance_z = z - shadow_z;
|
||||
}
|
||||
#endif //LIGHT_TRANSMITTANCE_USED
|
||||
}
|
||||
|
||||
#endif //USE_NO_SHADOWS
|
||||
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
transmission,
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
transmittance_color,
|
||||
transmittance_depth,
|
||||
transmittance_curve,
|
||||
transmittance_boost,
|
||||
transmittance_z,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
rim * spot_attenuation, rim_tint,
|
||||
@@ -1185,7 +1328,11 @@ void main() {
|
||||
vec3 vertex = vertex_interp;
|
||||
vec3 view = -normalize(vertex_interp);
|
||||
vec3 albedo = vec3(1.0);
|
||||
vec3 transmission = vec3(0.0);
|
||||
vec3 backlight = vec3(0.0);
|
||||
vec4 transmittance_color = vec4(0.0);
|
||||
float transmittance_depth = 0.0;
|
||||
float transmittance_curve = 1.0;
|
||||
float transmittance_boost = 0.0;
|
||||
float metallic = 0.0;
|
||||
float specular = 0.5;
|
||||
vec3 emission = vec3(0.0);
|
||||
@@ -1254,6 +1401,14 @@ FRAGMENT_SHADER_CODE
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
#if defined(LIGHT_TRANSMITTANCE_USED)
|
||||
#ifdef SSS_MODE_SKIN
|
||||
transmittance_color.a = sss_strength;
|
||||
#else
|
||||
transmittance_color.a *= sss_strength;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(USE_SHADOW_TO_OPACITY)
|
||||
|
||||
#if defined(ALPHA_SCISSOR_USED)
|
||||
@@ -1462,21 +1617,109 @@ FRAGMENT_SHADER_CODE
|
||||
continue; //not masked
|
||||
}
|
||||
|
||||
vec3 light_attenuation = vec3(1.0);
|
||||
vec3 shadow_attenuation = vec3(1.0);
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
float transmittance_z = transmittance_depth;
|
||||
#endif
|
||||
|
||||
if (directional_lights.data[i].shadow_enabled) {
|
||||
float depth_z = -vertex.z;
|
||||
|
||||
vec4 pssm_coord;
|
||||
vec3 shadow_color = vec3(0.0);
|
||||
vec3 light_dir = directional_lights.data[i].direction;
|
||||
|
||||
#define BIAS_FUNC(m_var, m_idx) \
|
||||
m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
|
||||
vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))) * directional_lights.data[i].shadow_normal_bias[m_idx]; \
|
||||
normal_bias -= light_dir * dot(light_dir, normal_bias); \
|
||||
m_var.xyz += normal_bias;
|
||||
|
||||
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0));
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
BIAS_FUNC(v, 0)
|
||||
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
|
||||
shadow_color = directional_lights.data[i].shadow_color1.rgb;
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
{
|
||||
vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
|
||||
vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
|
||||
trans_coord /= trans_coord.w;
|
||||
|
||||
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
|
||||
shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
|
||||
float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
|
||||
|
||||
transmittance_z = z - shadow_z;
|
||||
}
|
||||
#endif
|
||||
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
|
||||
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
BIAS_FUNC(v, 1)
|
||||
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
|
||||
shadow_color = directional_lights.data[i].shadow_color2.rgb;
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
{
|
||||
vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
|
||||
vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
|
||||
trans_coord /= trans_coord.w;
|
||||
|
||||
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
|
||||
shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
|
||||
float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
|
||||
|
||||
transmittance_z = z - shadow_z;
|
||||
}
|
||||
#endif
|
||||
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
|
||||
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
BIAS_FUNC(v, 2)
|
||||
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
|
||||
shadow_color = directional_lights.data[i].shadow_color3.rgb;
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
{
|
||||
vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
|
||||
vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
|
||||
trans_coord /= trans_coord.w;
|
||||
|
||||
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
|
||||
shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
|
||||
float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
|
||||
|
||||
transmittance_z = z - shadow_z;
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
|
||||
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
BIAS_FUNC(v, 3)
|
||||
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
|
||||
shadow_color = directional_lights.data[i].shadow_color4.rgb;
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
{
|
||||
vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
|
||||
vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
|
||||
trans_coord /= trans_coord.w;
|
||||
|
||||
float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
|
||||
shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
|
||||
float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
|
||||
|
||||
transmittance_z = z - shadow_z;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
pssm_coord /= pssm_coord.w;
|
||||
@@ -1485,17 +1728,27 @@ FRAGMENT_SHADER_CODE
|
||||
|
||||
if (directional_lights.data[i].blend_splits) {
|
||||
|
||||
vec3 shadow_color_blend = vec3(0.0);
|
||||
float pssm_blend;
|
||||
|
||||
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
BIAS_FUNC(v, 1)
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
|
||||
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
|
||||
shadow_color_blend = directional_lights.data[i].shadow_color2.rgb;
|
||||
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
BIAS_FUNC(v, 2)
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
|
||||
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
|
||||
shadow_color_blend = directional_lights.data[i].shadow_color3.rgb;
|
||||
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
BIAS_FUNC(v, 3)
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
|
||||
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
|
||||
shadow_color_blend = directional_lights.data[i].shadow_color4.rgb;
|
||||
} else {
|
||||
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
|
||||
}
|
||||
@@ -1504,16 +1757,26 @@ FRAGMENT_SHADER_CODE
|
||||
|
||||
float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
|
||||
shadow = mix(shadow, shadow2, pssm_blend);
|
||||
shadow_color = mix(shadow_color, shadow_color_blend, pssm_blend);
|
||||
}
|
||||
|
||||
shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
|
||||
|
||||
light_attenuation = mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow);
|
||||
shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
|
||||
|
||||
#undef BIAS_FUNC
|
||||
}
|
||||
|
||||
light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, light_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
transmission,
|
||||
light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, 1.0, shadow_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
transmittance_color,
|
||||
transmittance_depth,
|
||||
transmittance_curve,
|
||||
transmittance_boost,
|
||||
transmittance_z,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
rim, rim_tint,
|
||||
@@ -1546,8 +1809,14 @@ FRAGMENT_SHADER_CODE
|
||||
}
|
||||
|
||||
light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
transmission,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
transmittance_color,
|
||||
transmittance_depth,
|
||||
transmittance_curve,
|
||||
transmittance_boost,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
rim,
|
||||
@@ -1579,8 +1848,14 @@ FRAGMENT_SHADER_CODE
|
||||
}
|
||||
|
||||
light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
|
||||
#ifdef LIGHT_TRANSMISSION_USED
|
||||
transmission,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
transmittance_color,
|
||||
transmittance_depth,
|
||||
transmittance_curve,
|
||||
transmittance_boost,
|
||||
#endif
|
||||
#ifdef LIGHT_RIM_USED
|
||||
rim,
|
||||
|
||||
@@ -22,6 +22,10 @@ draw_call;
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
|
||||
|
||||
#define SHADOW_MODE_NO_FILTER 0
|
||||
#define SHADOW_MODE_PCF5 1
|
||||
#define SHADOW_MODE_PCF13 2
|
||||
|
||||
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
|
||||
|
||||
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
|
||||
@@ -37,13 +41,12 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
|
||||
vec2 viewport_size;
|
||||
vec2 screen_pixel_size;
|
||||
|
||||
//used for shadow mapping only
|
||||
float z_offset;
|
||||
float z_slope_scale;
|
||||
|
||||
float time;
|
||||
float reflection_multiplier; // one normally, zero when rendering reflections
|
||||
|
||||
bool pancake_shadows;
|
||||
uint shadow_filter_mode;
|
||||
|
||||
vec4 ambient_light_color_energy;
|
||||
|
||||
float ambient_color_sky_mix;
|
||||
@@ -134,7 +137,7 @@ layout(set = 0, binding = 4, std430) buffer Instances {
|
||||
}
|
||||
instances;
|
||||
|
||||
struct LightData { //this structure needs to be 128 bits
|
||||
struct LightData { //this structure needs to be as packed as possible
|
||||
vec3 position;
|
||||
float inv_radius;
|
||||
vec3 direction;
|
||||
@@ -143,12 +146,16 @@ struct LightData { //this structure needs to be 128 bits
|
||||
uint cone_attenuation_angle; // attenuation and angle, (16bit float)
|
||||
uint mask;
|
||||
uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
|
||||
vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
|
||||
vec4 atlas_rect; // used for spot
|
||||
mat4 shadow_matrix;
|
||||
float shadow_bias;
|
||||
float shadow_normal_bias;
|
||||
float transmittance_bias;
|
||||
uint pad;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 5, std140) uniform Lights {
|
||||
LightData data[MAX_LIGHT_DATA_STRUCTS];
|
||||
layout(set = 0, binding = 5, std430) buffer Lights {
|
||||
LightData data[];
|
||||
}
|
||||
lights;
|
||||
|
||||
@@ -174,17 +181,27 @@ struct DirectionalLightData {
|
||||
float energy;
|
||||
vec3 color;
|
||||
float specular;
|
||||
vec3 shadow_color;
|
||||
uint mask;
|
||||
uint pad0;
|
||||
uint pad1;
|
||||
uint pad2;
|
||||
bool blend_splits;
|
||||
bool shadow_enabled;
|
||||
float fade_from;
|
||||
float fade_to;
|
||||
vec4 shadow_bias;
|
||||
vec4 shadow_normal_bias;
|
||||
vec4 shadow_transmittance_bias;
|
||||
vec4 shadow_transmittance_z_scale;
|
||||
vec4 shadow_split_offsets;
|
||||
mat4 shadow_matrix1;
|
||||
mat4 shadow_matrix2;
|
||||
mat4 shadow_matrix3;
|
||||
mat4 shadow_matrix4;
|
||||
vec4 shadow_color1;
|
||||
vec4 shadow_color2;
|
||||
vec4 shadow_color3;
|
||||
vec4 shadow_color4;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 7, std140) uniform DirectionalLights {
|
||||
|
||||
Reference in New Issue
Block a user