فهرست منبع

basic contact shadows implementation, will most likely need some polishing

Juan Linietsky 8 سال پیش
والد
کامیت
07bbcf91f7

+ 33 - 14
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -2321,10 +2321,10 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index,const Transform&
 	ubo_data.light_params[3]=0;
 
 	Color shadow_color = li->light_ptr->shadow_color.to_linear();
-	ubo_data.light_shadow_color[0]=shadow_color.r;
-	ubo_data.light_shadow_color[1]=shadow_color.g;
-	ubo_data.light_shadow_color[2]=shadow_color.b;
-	ubo_data.light_shadow_color[3]=1.0;
+	ubo_data.light_shadow_color_contact[0]=shadow_color.r;
+	ubo_data.light_shadow_color_contact[1]=shadow_color.g;
+	ubo_data.light_shadow_color_contact[2]=shadow_color.b;
+	ubo_data.light_shadow_color_contact[3]=li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE];
 
 
 	if (p_use_shadows && li->light_ptr->shadow) {
@@ -2480,10 +2480,10 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu
 				ubo_data.light_params[3]=0;
 
 				Color shadow_color = li->light_ptr->shadow_color.to_linear();
-				ubo_data.light_shadow_color[0]=shadow_color.r;
-				ubo_data.light_shadow_color[1]=shadow_color.g;
-				ubo_data.light_shadow_color[2]=shadow_color.b;
-				ubo_data.light_shadow_color[3]=1.0;
+				ubo_data.light_shadow_color_contact[0]=shadow_color.r;
+				ubo_data.light_shadow_color_contact[1]=shadow_color.g;
+				ubo_data.light_shadow_color_contact[2]=shadow_color.b;
+				ubo_data.light_shadow_color_contact[3]=li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE];
 
 				if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) {
 					// fill in the shadow information
@@ -2573,10 +2573,10 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu
 				ubo_data.light_params[3]=0;
 
 				Color shadow_color = li->light_ptr->shadow_color.to_linear();
-				ubo_data.light_shadow_color[0]=shadow_color.r;
-				ubo_data.light_shadow_color[1]=shadow_color.g;
-				ubo_data.light_shadow_color[2]=shadow_color.b;
-				ubo_data.light_shadow_color[3]=1.0;
+				ubo_data.light_shadow_color_contact[0]=shadow_color.r;
+				ubo_data.light_shadow_color_contact[1]=shadow_color.g;
+				ubo_data.light_shadow_color_contact[2]=shadow_color.b;
+				ubo_data.light_shadow_color_contact[3]=li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE];
 
 				if (li->light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) {
 					// fill in the shadow information
@@ -3760,14 +3760,20 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 	state.ubo_data.shadow_dual_paraboloid_render_side=0;
 	state.ubo_data.shadow_dual_paraboloid_render_zfar=0;
 
+	if (storage->frame.current_rt) {
+		state.ubo_data.screen_pixel_size[0]=1.0/storage->frame.current_rt->width;
+		state.ubo_data.screen_pixel_size[1]=1.0/storage->frame.current_rt->height;
+	}
+
 	_setup_environment(env,p_cam_projection,p_cam_transform);
 
 	bool fb_cleared=false;
 
 	glDepthFunc(GL_LEQUAL);
 
+	state.used_contact_shadows=true;
 
-	if (storage->frame.current_rt && true) {
+	if (storage->frame.current_rt && true) { //detect with state.used_contact_shadows too
 		//pre z pass
 
 
@@ -3794,6 +3800,19 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 
 		glColorMask(1,1,1,1);
 
+		if (state.used_contact_shadows) {
+
+			glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
+			glReadBuffer(GL_COLOR_ATTACHMENT0);
+			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
+			glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+			glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+			//bind depth for read
+			glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-8);
+			glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth);
+		}
+
 		fb_cleared=true;
 		render_pass++;
 	}
@@ -4458,7 +4477,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa
 
 	state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH,true);
 
-	_render_list(render_list.elements,render_list.element_count,light_transform,light_projection,0,!flip_facing,false,true,false,false);
+	_render_list(render_list.elements,render_list.element_count,light_transform,light_projection,0,flip_facing,false,true,false,false);
 
 	state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH,false);
 	state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_DEPTH_DUAL_PARABOLOID,false);

+ 3 - 1
drivers/gles3/rasterizer_scene_gles3.h

@@ -91,6 +91,7 @@ public:
 			float shadow_slope_scale;
 			float shadow_dual_paraboloid_render_zfar;
 			float shadow_dual_paraboloid_render_side;
+			float screen_pixel_size[2];
 			float shadow_atlas_pixel_size[2];
 			float shadow_directional_pixel_size[2];
 			float reflection_multiplier;
@@ -136,6 +137,7 @@ public:
 		int max_ubo_reflections;
 		int max_skeleton_bones;
 
+		bool used_contact_shadows;
 
 
 		int spot_light_count;
@@ -467,7 +469,7 @@ public:
 		float light_color_energy[4];
 		float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled
 		float light_clamp[4];
-		float light_shadow_color[4];
+		float light_shadow_color_contact[4];
 		float shadow_matrix1[16]; //up to here for spot and omni, rest is for directional
 		float shadow_matrix2[16];
 		float shadow_matrix3[16];

+ 1 - 0
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -4290,6 +4290,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){
 	light->param[VS::LIGHT_PARAM_SPECULAR]=0.5;
 	light->param[VS::LIGHT_PARAM_RANGE]=1.0;
 	light->param[VS::LIGHT_PARAM_SPOT_ANGLE]=45;
+	light->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE]=45;
 	light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE]=0;
 	light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET]=0.1;
 	light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET]=0.3;

+ 113 - 18
drivers/gles3/shaders/scene.glsl

@@ -71,6 +71,7 @@ layout(std140) uniform SceneData { //ubo:0
 	float shadow_dual_paraboloid_render_zfar;
 	float shadow_dual_paraboloid_render_side;
 
+	highp vec2 screen_pixel_size;
 	vec2 shadow_atlas_pixel_size;
 	vec2 directional_shadow_pixel_size;
 
@@ -91,7 +92,7 @@ layout(std140) uniform DirectionalLightData { //ubo:3
 	mediump vec4 light_color_energy;
 	mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled,
 	mediump vec4 light_clamp;
-	mediump vec4 shadow_color;
+	mediump vec4 shadow_color_contact;
 	highp mat4 shadow_matrix1;
 	highp mat4 shadow_matrix2;
 	highp mat4 shadow_matrix3;
@@ -126,13 +127,6 @@ out vec3 binormal_interp;
 #endif
 
 
-#if !defined(USE_DEPTH_SHADOWS) && defined(USE_SHADOW_PASS)
-
-varying vec4 position_interp;
-
-#endif
-
-
 VERTEX_SHADER_GLOBALS
 
 
@@ -161,6 +155,8 @@ layout(std140) uniform SkeletonData { //ubo:7
 
 #endif
 
+out highp vec4 position_interp;
+
 void main() {
 
 	highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0);
@@ -293,7 +289,7 @@ VERTEX_SHADER_CODE
 	gl_Position = vertex;
 #endif
 
-
+	position_interp=gl_Position;
 }
 
 
@@ -375,6 +371,8 @@ layout(std140) uniform SceneData {
 
 	highp vec4 ambient_light_color;
 	highp vec4 bg_color;
+
+
 	float ambient_energy;
 	float bg_energy;
 
@@ -383,6 +381,7 @@ layout(std140) uniform SceneData {
 	float shadow_dual_paraboloid_render_zfar;
 	float shadow_dual_paraboloid_render_side;
 
+	highp vec2 screen_pixel_size;
 	vec2 shadow_atlas_pixel_size;
 	vec2 directional_shadow_pixel_size;
 
@@ -403,7 +402,7 @@ layout(std140) uniform DirectionalLightData {
 	mediump vec4 light_color_energy;
 	mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled,
 	mediump vec4 light_clamp;
-	mediump vec4 shadow_color;
+	mediump vec4 shadow_color_contact;
 	highp mat4 shadow_matrix1;
 	highp mat4 shadow_matrix2;
 	highp mat4 shadow_matrix3;
@@ -425,7 +424,7 @@ struct LightData {
 	mediump vec4 light_color_energy;
 	mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled,
 	mediump vec4 light_clamp;
-	mediump vec4 shadow_color;
+	mediump vec4 shadow_color_contact;
 	highp mat4 shadow_matrix;
 
 };
@@ -493,6 +492,69 @@ layout(location=0) out vec4 frag_color;
 
 #endif
 
+in highp vec4 position_interp;
+uniform highp sampler2D depth_buffer; //texunit:-8
+
+float contact_shadow_compute(vec3 pos, vec3 dir, float max_distance) {
+
+	if (abs(dir.z)>0.99)
+		return 1.0;
+
+	vec3 endpoint = pos+dir*max_distance;
+	vec4 source = position_interp;
+	vec4 dest = projection_matrix * vec4(endpoint, 1.0);
+
+	vec2 from_screen = (source.xy / source.w) * 0.5 + 0.5;
+	vec2 to_screen = (dest.xy / dest.w) * 0.5 + 0.5;
+
+	vec2 screen_rel = to_screen - from_screen;
+
+	/*float pixel_size; //approximate pixel size
+
+	if (screen_rel.x > screen_rel.y) {
+
+		pixel_size = abs((pos.x-endpoint.x)/(screen_rel.x/screen_pixel_size.x));
+	} else {
+		pixel_size = abs((pos.y-endpoint.y)/(screen_rel.y/screen_pixel_size.y));
+
+	}*/
+	vec4 bias = projection_matrix * vec4(pos+vec3(0.0,0.0,0.04), 1.0); //todo un-harcode the 0.04
+
+
+
+	vec2 pixel_incr = normalize(screen_rel)*screen_pixel_size;
+
+	float steps = length(screen_rel) / length(pixel_incr);
+
+	//steps=10.0;
+
+	vec4 incr = (dest - source)/steps;
+	float ratio=0.0;
+	float ratio_incr = 1.0/steps;
+
+	do {
+		source += incr*2;
+		bias+=incr*2;
+
+		vec3 uv_depth = (source.xyz / source.w) * 0.5 + 0.5;
+		float depth = texture(depth_buffer,uv_depth.xy).r;
+
+		if (depth < uv_depth.z) {
+			if (depth > (bias.z/bias.w) * 0.5 + 0.5) {
+				return min(pow(ratio,4.0),1.0);
+			} else {
+				return 1.0;
+			}
+		}
+
+
+		ratio+=ratio_incr;
+		steps-=1.0;
+	} while (steps>0.0);
+
+	return 1.0;
+}
+
 
 // GGX Specular
 // Source: http://www.filmicworlds.com/images/ggx-opt/optimized-ggx.hlsl
@@ -517,6 +579,8 @@ float GTR1(float NdotH, float a)
     return (a2-1.0) / (M_PI*log(a2)*t);
 }
 
+
+
 void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) {
 
 	float dotNL = max(dot(N,L), 0.0 );
@@ -660,7 +724,8 @@ vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 po
 void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 specular, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse_light, inout vec3 specular_light) {
 
 	vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex;
-	float normalized_distance = length( light_rel_vec )*omni_lights[idx].light_pos_inv_radius.w;
+	float light_length = length( light_rel_vec );
+	float normalized_distance = light_length*omni_lights[idx].light_pos_inv_radius.w;
 	vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w ));
 
 	if (omni_lights[idx].light_params.w>0.5) {
@@ -696,8 +761,15 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino
 		splane.z = shadow_len * omni_lights[idx].light_pos_inv_radius.w;
 
 		splane.xy = clamp_rect.xy+splane.xy*clamp_rect.zw;
+		float shadow = sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect);
+		if (shadow>0.01 && omni_lights[idx].shadow_color_contact.a>0.0) {
+
+			float contact_shadow = contact_shadow_compute(vertex,normalize(light_rel_vec),min(light_length,omni_lights[idx].shadow_color_contact.a));
+			shadow=min(shadow,contact_shadow);
 
-		light_attenuation*=mix(omni_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect));
+
+		}
+		light_attenuation*=mix(omni_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
 	}
 
 	light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,omni_lights[idx].light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
@@ -707,7 +779,8 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino
 void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent,vec3 albedo, vec3 specular, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) {
 
 	vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex;
-	float normalized_distance = length( light_rel_vec )*spot_lights[idx].light_pos_inv_radius.w;
+	float light_length = length( light_rel_vec );
+	float normalized_distance = light_length*spot_lights[idx].light_pos_inv_radius.w;
 	vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), spot_lights[idx].light_direction_attenuation.w ));
 	vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz;
 	float spot_cutoff=spot_lights[idx].light_params.y;
@@ -719,7 +792,17 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
 		//there is a shadowmap
 		highp vec4 splane=(spot_lights[idx].shadow_matrix * vec4(vertex,1.0));
 		splane.xyz/=splane.w;
-		light_attenuation*=mix(spot_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp));
+
+		float shadow = sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp);
+
+		if (shadow>0.01 && spot_lights[idx].shadow_color_contact.a>0.0) {
+
+			float contact_shadow = contact_shadow_compute(vertex,normalize(light_rel_vec),min(light_length,spot_lights[idx].shadow_color_contact.a));
+			shadow=min(shadow,contact_shadow);
+
+		}
+
+		light_attenuation*=mix(spot_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
 	}
 
 	light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,spot_lights[idx].light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
@@ -1268,6 +1351,8 @@ FRAGMENT_SHADER_CODE
 		}
 	}
 
+
+
 #endif //LIGHT_USE_PSSM4
 
 #ifdef LIGHT_USE_PSSM2
@@ -1306,16 +1391,26 @@ FRAGMENT_SHADER_CODE
 
 
 	//one one sample
-	light_attenuation=mix(shadow_color.rgb,vec3(1.0),sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp));
 
+	float shadow = sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp);
 
 #if defined(LIGHT_USE_PSSM_BLEND)
+
 	if (use_blend) {
-		vec3 light_attenuation2=mix(shadow_color.rgb,vec3(1.0),sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp));
-		light_attenuation=mix(light_attenuation,light_attenuation2,pssm_blend);
+		shadow=mix(shadow, sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp));
 	}
 #endif
 
+	if (shadow>0.01 && shadow_color_contact.a>0.0) {
+
+		float contact_shadow = contact_shadow_compute(vertex,-light_direction_attenuation.xyz,shadow_color_contact.a);
+		shadow=min(shadow,contact_shadow);
+
+	}
+
+	light_attenuation=mix(shadow_color_contact.rgb,vec3(1.0),shadow);
+
+
 	}
 
 #endif //LIGHT_DIRECTIONAL_SHADOW

+ 3 - 0
scene/3d/light.cpp

@@ -253,6 +253,7 @@ void Light::_bind_methods() {
 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow_enabled"), _SCS("set_shadow"), _SCS("has_shadow"));
 	ADD_PROPERTY( PropertyInfo( Variant::COLOR, "shadow_color",PROPERTY_HINT_COLOR_NO_ALPHA), _SCS("set_shadow_color"), _SCS("get_shadow_color"));
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_bias",PROPERTY_HINT_RANGE,"-16,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS);
+	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_contact",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_CONTACT_SHADOW_SIZE);
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_max_distance",PROPERTY_HINT_RANGE,"0,65536,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_MAX_DISTANCE);
 	ADD_GROUP("Editor","");
 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editor_only"), _SCS("set_editor_only"), _SCS("is_editor_only"));
@@ -264,6 +265,7 @@ void Light::_bind_methods() {
 	BIND_CONSTANT( PARAM_ATTENUATION );
 	BIND_CONSTANT( PARAM_SPOT_ANGLE );
 	BIND_CONSTANT( PARAM_SPOT_ATTENUATION );
+	BIND_CONSTANT( PARAM_CONTACT_SHADOW_SIZE );
 	BIND_CONSTANT( PARAM_SHADOW_MAX_DISTANCE );
 	BIND_CONSTANT( PARAM_SHADOW_SPLIT_1_OFFSET );
 	BIND_CONSTANT( PARAM_SHADOW_SPLIT_2_OFFSET );
@@ -297,6 +299,7 @@ Light::Light(VisualServer::LightType p_type) {
 	set_param(PARAM_ATTENUATION,1);
 	set_param(PARAM_SPOT_ANGLE,45);
 	set_param(PARAM_SPOT_ATTENUATION,1);
+	set_param(PARAM_CONTACT_SHADOW_SIZE,0);
 	set_param(PARAM_SHADOW_MAX_DISTANCE,0);
 	set_param(PARAM_SHADOW_SPLIT_1_OFFSET,0.1);
 	set_param(PARAM_SHADOW_SPLIT_2_OFFSET,0.2);

+ 1 - 0
scene/3d/light.h

@@ -55,6 +55,7 @@ public:
 		PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION,
 		PARAM_SPOT_ANGLE = VS::LIGHT_PARAM_SPOT_ANGLE,
 		PARAM_SPOT_ATTENUATION = VS::LIGHT_PARAM_SPOT_ATTENUATION,
+		PARAM_CONTACT_SHADOW_SIZE= VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE,
 		PARAM_SHADOW_MAX_DISTANCE = VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE,
 		PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
 		PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,

+ 1 - 0
servers/visual_server.h

@@ -365,6 +365,7 @@ public:
 		LIGHT_PARAM_ATTENUATION,
 		LIGHT_PARAM_SPOT_ANGLE,
 		LIGHT_PARAM_SPOT_ATTENUATION,
+		LIGHT_PARAM_CONTACT_SHADOW_SIZE,
 		LIGHT_PARAM_SHADOW_MAX_DISTANCE,
 		LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
 		LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,