Directional lights and shadow mapping are functional.

This commit is contained in:
Juan Linietsky 2019-09-07 14:38:17 -03:00
parent 920db604d2
commit 88a7debbbc
11 changed files with 232 additions and 50 deletions

View file

@ -281,6 +281,7 @@ void Light::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET);
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET);
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET);
BIND_ENUM_CONSTANT(PARAM_SHADOW_FADE_START);
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE);
@ -325,8 +326,10 @@ Light::Light(VisualServer::LightType p_type) {
set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1);
set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2);
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
set_param(PARAM_SHADOW_FADE_START, 0.8);
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0);
set_param(PARAM_SHADOW_BIAS, 0.15);
set_param(PARAM_SHADOW_FADE_START, 1);
set_disable_scale(true);
}
@ -393,6 +396,7 @@ void DirectionalLight::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE);
@ -413,6 +417,7 @@ DirectionalLight::DirectionalLight() :
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8);
set_param(PARAM_SHADOW_BIAS, 0.1);
set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
set_param(PARAM_SHADOW_FADE_START, 0.8);
set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25);
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);

View file

@ -54,6 +54,7 @@ public:
PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
PARAM_SHADOW_FADE_START = VS::LIGHT_PARAM_SHADOW_FADE_START,
PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS,
PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,

View file

@ -1377,6 +1377,66 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
continue;
}
DirectionalLightData &light_data = scene_state.directional_lights[scene_state.ubo.directional_light_count];
Transform light_transform = light_instance_get_base_transform(li);
Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized();
light_data.direction[0] = direction.x;
light_data.direction[1] = direction.y;
light_data.direction[2] = direction.z;
float sign = storage->light_is_negative(base) ? -1 : 1;
light_data.energy = sign * storage->light_get_param(base, VS::LIGHT_PARAM_ENERGY) * Math_PI;
Color linear_col = storage->light_get_color(base).to_linear();
light_data.color[0] = linear_col.r;
light_data.color[1] = linear_col.g;
light_data.color[2] = linear_col.b;
light_data.specular = storage->light_get_param(base, VS::LIGHT_PARAM_SPECULAR);
light_data.mask = storage->light_get_cull_mask(base);
Color shadow_col = storage->light_get_shadow_color(base).to_linear();
light_data.shadow_color[0] = shadow_col.r;
light_data.shadow_color[1] = shadow_col.g;
light_data.shadow_color[2] = shadow_col.b;
light_data.shadow_enabled = storage->light_has_shadow(base);
if (light_data.shadow_enabled) {
VS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
int limit = smode == VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
light_data.blend_splits = storage->light_directional_get_blend_splits(base);
for (int j = 0; j < 4; j++) {
Rect2 atlas_rect = light_instance_get_directional_shadow_atlas_rect(li, j);
CameraMatrix matrix = light_instance_get_shadow_camera(li, j);
float split = light_instance_get_directional_shadow_split(li, MIN(limit, j));
CameraMatrix bias;
bias.set_light_bias();
CameraMatrix rectm;
rectm.set_light_atlas_rect(atlas_rect);
Transform modelview = (p_camera_inverse_transform * light_instance_get_shadow_transform(li, j)).inverse();
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
store_camera(shadow_mtx, light_data.shadow_matrices[j]);
}
float fade_start = storage->light_get_param(base, VS::LIGHT_PARAM_SHADOW_FADE_START);
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999);
light_data.fade_to = -light_data.shadow_split_offsets[3];
}
scene_state.ubo.directional_light_count++;
} break;
case VS::LIGHT_SPOT:
case VS::LIGHT_OMNI: {
@ -1476,7 +1536,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
}
if (scene_state.ubo.directional_light_count) {
RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * light_count, scene_state.directional_lights, true);
RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * scene_state.ubo.directional_light_count, scene_state.directional_lights, true);
}
}
@ -2092,7 +2152,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
storage->render_target_disable_clear_request(render_buffer->render_target);
if (true) {
if (false) {
if (p_shadow_atlas.is_valid()) {
RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
@ -2101,6 +2161,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
}
}
if (true) {
if (directional_shadow_get_texture().is_valid()) {
RID shadow_atlas_texture = directional_shadow_get_texture();
Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2));
}
}
#if 0
_post_process(env, p_cam_projection);
// Needed only for debugging

View file

@ -235,16 +235,14 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
float energy;
float color[3];
float specular;
uint32_t mask;
uint32_t pad[3];
float shadow_color[3];
uint32_t mask;
uint32_t blend_splits;
uint32_t shadow_enabled;
float shadow_atlas_rect[4];
float fade_from;
float fade_to;
float shadow_split_offsets[4];
float shadow_matrix1[16];
float shadow_matrix2[16];
float shadow_matrix3[16];
float shadow_matrix4[16];
float shadow_matrices[4][16];
};
struct InstanceData {

View file

@ -898,6 +898,8 @@ void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) {
return;
}
directional_shadow.size = p_size;
if (directional_shadow.depth.is_valid()) {
RD::get_singleton()->free(directional_shadow.depth);
directional_shadow.depth = RID();
@ -925,17 +927,34 @@ void RasterizerSceneRD::set_directional_shadow_count(int p_count) {
directional_shadow.current_light = 0;
}
static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) {
int split_h = 1;
int split_v = 1;
while (split_h * split_v < p_shadow_count) {
if (split_h == split_v) {
split_h <<= 1;
} else {
split_v <<= 1;
}
}
Rect2i rect(0, 0, p_size, p_size);
rect.size.width /= split_h;
rect.size.height /= split_v;
rect.position.x = rect.size.width * (p_shadow_index % split_h);
rect.position.y = rect.size.height * (p_shadow_index / split_h);
return rect;
}
int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
int shadow_size;
if (directional_shadow.light_count == 1) {
shadow_size = directional_shadow.size;
} else {
shadow_size = directional_shadow.size / 2; //more than 4 not supported anyway
}
Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0);
LightInstance *light_instance = light_instance_owner.getornull(p_light_intance);
ERR_FAIL_COND_V(!light_instance, 0);
@ -943,11 +962,11 @@ int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
break; //none
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: r.size.height /= 2; break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: r.size /= 2; break;
}
return shadow_size;
return MAX(r.size.width, r.size.height);
}
//////////////////////////////////////////////////
@ -1112,27 +1131,9 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
if (storage->light_get_type(light_instance->light) == VS::LIGHT_DIRECTIONAL) {
//set pssm stuff
if (light_instance->last_scene_shadow_pass != scene_pass) {
//assign rect if unassigned
light_instance->light_directional_index = directional_shadow.current_light;
light_instance->last_scene_shadow_pass = scene_pass;
light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
directional_shadow.current_light++;
if (directional_shadow.light_count == 1) {
light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size);
} else if (directional_shadow.light_count == 2) {
light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size / 2);
if (light_instance->light_directional_index == 1) {
light_instance->directional_rect.position.x += light_instance->directional_rect.size.x;
}
} else { //3 and 4
light_instance->directional_rect = Rect2(0, 0, directional_shadow.size / 2, directional_shadow.size / 2);
if (light_instance->light_directional_index & 1) {
light_instance->directional_rect.position.x += light_instance->directional_rect.size.x;
}
if (light_instance->light_directional_index / 2) {
light_instance->directional_rect.position.y += light_instance->directional_rect.size.y;
}
}
light_instance->last_scene_shadow_pass = scene_pass;
}
light_projection = light_instance->shadow_transform[p_pass].camera;
@ -1168,6 +1169,11 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
}
}
light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect;
light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE));
zfar = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_RANGE);
bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;

View file

@ -180,6 +180,7 @@ private:
float farplane;
float split;
float bias_scale;
Rect2 atlas_rect;
};
VS::LightType light_type;
@ -409,6 +410,24 @@ public:
return li->shadow_transform[p_index].camera;
}
_FORCE_INLINE_ Transform light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].transform;
}
_FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].atlas_rect;
}
_FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].split;
}
_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
li->last_pass = p_pass;

View file

@ -2104,6 +2104,7 @@ RID RasterizerStorageRD::light_create(VS::LightType p_type) {
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
light.param[VS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
light.param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
light.param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;

View file

@ -584,7 +584,11 @@ LIGHT_SHADER_CODE
#ifndef USE_NO_SHADOWS
float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec2 pos, float depth) {
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
@ -657,7 +661,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
if (shadow_color_enabled.w > 0.5) {
// there is a shadowmap
vec3 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
float shadow_len = length(splane);
splane = normalize(splane);
vec4 clamp_rect = lights.data[idx].atlas_rect;
@ -677,9 +681,9 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
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;
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
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);
}
@ -750,9 +754,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
if (shadow_color_enabled.w > 0.5) {
//there is a shadowmap
vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
splane.xyz /= splane.w;
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
splane /= splane.w;
float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
}
@ -1132,7 +1135,84 @@ FRAGMENT_SHADER_CODE
#endif
}
//directional light
{ //directional light
for (uint i = 0; i < scene_data.directional_light_count; i++) {
if (!bool(directional_lights.data[i].mask&instances.data[instance_index].layer_mask)) {
continue; //not masked
}
vec3 light_attenuation = vec3(1.0);
if (directional_lights.data[i].shadow_enabled) {
float depth_z = -vertex.z;
vec4 pssm_coord;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0));
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
} else {
pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
}
pssm_coord/=pssm_coord.w;
float shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
if (directional_lights.data[i].blend_splits) {
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));
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
} else {
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
}
pssm_coord/=pssm_coord.w;
float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
shadow = mix(shadow,shadow2,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 = vec3(shadow); //mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow);
}
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,
#endif
#ifdef LIGHT_RIM_USED
rim * omni_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha
#endif
diffuse_light, specular_light);
}
}
{ //omni lights
uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;

View file

@ -184,11 +184,12 @@ struct DirectionalLightData {
float energy;
vec3 color;
float specular;
uint mask;
uint pad0,pad1,pad2;
vec3 shadow_color;
uint mask;
bool blend_splits;
bool shadow_enabled;
vec4 shadow_atlas_rect;
float fade_from;
float fade_to;
vec4 shadow_split_offsets;
mat4 shadow_matrix1;
mat4 shadow_matrix2;

View file

@ -2047,6 +2047,7 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE);

View file

@ -404,6 +404,7 @@ public:
LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
LIGHT_PARAM_SHADOW_FADE_START,
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
LIGHT_PARAM_SHADOW_BIAS,
LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,