sampler_states = {
	shadow_map = {
		states = {
			srgb = "false"

			defined_RENDERER_D3D11 = {
				comparison_func = "less"
				filter = "comparison_min_mag_linear_mip_point"
				address_u = "address_clamp"
				address_v = "address_clamp"
				address_w = "address_clamp"
			}
			defined_RENDERER_D3D12 = {
				comparison_func = "less"
				filter = "comparison_min_mag_linear_mip_point"
				address_u = "address_clamp"
				address_v = "address_clamp"
				address_w = "address_clamp"
			}
			defined_RENDERER_GNM = {
				comparison_func = "less"
				filter = "min_mag_mip_linear"
				address_u = "address_clamp"
				address_v = "address_clamp"
				address_w = "address_clamp"				
			}
			defined_RENDERER_GL = {
				comparison_func = "less"
				filter = "min_mag_linear"
				address_u = "address_clamp_to_edge"
				address_v = "address_clamp_to_edge"
				address_w = "address_clamp_to_edge"				
			}
		}
	}
}

hlsl_shaders = {
	shadow_bias = {
		fp_code = { ref = "code" }
		vp_code = { ref = "code" }
		code = """
			CBUFFER_START(shadow_data)
				float3 local_shadow_map_bias;
				float3 sun_shadow_map_bias;
				float3 ssm_shadow_map_bias;
			CBUFFER_END

			float apply_shadow_depth_comparison_bias(float linear_depth, float shadow_comparison_depth, float3 shadow_map_bias) {
				// Do not need a sun shadow map bias on d3d12 as we're using 32bit shadow maps, and they handle the shitz!
				#if defined(RENDERER_D3D12)
					return shadow_comparison_depth;
				#else
					const float min_bias = shadow_map_bias.x;
					const float max_bias = shadow_map_bias.y;
					const float blend_distance = shadow_map_bias.z;
					return shadow_comparison_depth - lerp(min_bias, max_bias, saturate(linear_depth / blend_distance));
				#endif
			}
		"""
	}

	shadow_map_filtering = {
		vp_code = { ref = "code" }
		fp_code = { ref = "code" }
		code = """
				#if defined(RENDERER_D3D11) || defined(RENDERER_D3D12) || defined(RENDERER_GNM)
					float shadow_intensity_2d(ComparisonSampler2D shadow_map, float2 shadow_map_size, float2 uv, float comparison_depth) {
						float2 tscale = 1.f / shadow_map_size;

						#if defined(PCF_5X5)
							uv *= shadow_map_size;

							float2 base_uv = floor(uv + 0.5);
							float s = (uv.x + 0.5 - base_uv.x);
							float t = (uv.y + 0.5 - base_uv.y);
							base_uv = (base_uv - float2(0.5, 0.5)) * tscale;

							float a = 0;

							float2 w0 = float2(4 - 3 * s, 4 - 3 * t);
							float2 w1 = float2(7, 7);
							float2 w2 = float2(1 + 3 * s, 1 + 3 * t);

							float2 uv0 = float2((3 - 2 * s) / w0.x - 2, (3 - 2 * t) / w0.y - 2) * tscale;
							float2 uv1 = float2((3 + s) / w1.x, (3 + t) / w1.y) * tscale;
							float2 uv2 = float2(s / w2.x + 2, t / w2.y + 2) * tscale;

							a += w0.x * w0.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv0.x, uv0.y), comparison_depth);
							a += w1.x * w0.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv1.x, uv0.y), comparison_depth);
							a += w2.x * w0.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv2.x, uv0.y), comparison_depth);

							a += w0.x * w1.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv0.x, uv1.y), comparison_depth);
							a += w1.x * w1.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv1.x, uv1.y), comparison_depth);
							a += w2.x * w1.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv2.x, uv1.y), comparison_depth);

							a += w0.x * w2.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv0.x, uv2.y), comparison_depth);
							a += w1.x * w2.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv1.x, uv2.y), comparison_depth);
							a += w2.x * w2.y * TEX2DCMPLOD0(shadow_map, base_uv + float2(uv2.x, uv2.y), comparison_depth);

							return a / 144.f;
						#else
							float2 half_pixel = tscale * 0.5f;

							float a =
								TEX2DCMPLOD0(shadow_map, uv + float2(-half_pixel.x,  half_pixel.y), comparison_depth) +
								TEX2DCMPLOD0(shadow_map, uv + float2( half_pixel.x,  half_pixel.y), comparison_depth) +
								TEX2DCMPLOD0(shadow_map, uv + float2(-half_pixel.x, -half_pixel.y), comparison_depth) +
								TEX2DCMPLOD0(shadow_map, uv + float2( half_pixel.x, -half_pixel.y), comparison_depth);

							a *= 0.25;

							return a;
						#endif
					}
				#else
					lowp float shadow_intensity_2d(ComparisonSampler2D shadow_map, mediump vec2 shadow_map_size, highp vec2 uv, highp float comparison_depth) {
						highp vec2 half_pixel = vec2(0.5, 0.5) / shadow_map_size;

						lowp float shadow =
							TEX2DCMP(shadow_map, vec3(uv + vec2(-half_pixel.x,  half_pixel.y), comparison_depth))
							+ TEX2DCMP(shadow_map, vec3(uv + vec2( half_pixel.x,  half_pixel.y), comparison_depth))
							+ TEX2DCMP(shadow_map, vec3(uv + vec2( half_pixel.x, -half_pixel.y), comparison_depth))
							+ TEX2DCMP(shadow_map, vec3(uv + vec2(-half_pixel.x, -half_pixel.y), comparison_depth));

						return shadow * 0.25;
					}
				#endif
		"""
	}	
}
