Created
April 14, 2012 12:28
-
-
Save jcdickinson/2384073 to your computer and use it in GitHub Desktop.
Shadows HLSL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
uniform extern texture Texture : TXSOURCE; | |
uniform extern texture ShadowMapTexture : TXSHADOWMAP; | |
uniform extern float2 RenderTargetSize : SZRT; | |
sampler inputSampler = sampler_state | |
{ | |
Texture = <Texture>; | |
MipFilter = Point; | |
MinFilter = Linear; | |
MagFilter = Linear; | |
AddressU = Clamp; | |
AddressV = Clamp; | |
}; | |
sampler shadowMapSampler = sampler_state | |
{ | |
Texture = <ShadowMapTexture>; | |
MipFilter = Point; | |
MinFilter = Point; | |
MagFilter = Point; | |
AddressU = Clamp; | |
AddressV = Clamp; | |
}; | |
struct OutputVS | |
{ | |
float4 position : POSITION; | |
float2 texcoord : TEXCOORD0; | |
}; | |
OutputVS FullScreenVS ( | |
float3 inPos : POSITION, | |
float2 inTex : TEXCOORD0 | |
) | |
{ | |
OutputVS output = (OutputVS)0; | |
output.texcoord = inTex; | |
// Offset the position by half a pixel to correctly align texels to pixels | |
output.position = | |
float4(inPos, 1) + 0.5f * | |
float4(-1.0f / RenderTargetSize.x, 1.0f / RenderTargetSize.y, 0, 0); | |
return output; | |
} | |
float4 DistortPS( | |
float2 texCoord : TEXCOORD0 | |
) : COLOR0 | |
{ | |
//translate u and v into [-1 , 1] domain | |
float u0 = texCoord.x * 2 - 1; | |
float v0 = texCoord.y * 2 - 1; | |
//then, as u0 approaches 0 (the center), v should also approach 0 | |
v0 = v0 * abs(u0); | |
//convert back from [-1,1] domain to [0,1] domain | |
v0 = (v0 + 1) / 2; | |
//we now have the coordinates for reading from the initial image | |
float2 newCoords = float2(texCoord.x, v0); | |
//read for both horizontal and vertical direction and store them in separate channels | |
float horizontal = tex2D(inputSampler, newCoords).a; | |
float distanceH = (horizontal > 0.3f ? length(newCoords - 0.5f) : 1.0f); | |
float vertical = tex2D(inputSampler, newCoords.yx).a; | |
float distanceV = (vertical > 0.3f ? length(newCoords - 0.5f) : 1.0f); | |
return float4(distanceH, distanceV, 0, 1); | |
} | |
float GetShadowDistanceH(float2 TexCoord, float displacementV) | |
{ | |
float u = TexCoord.x; | |
float v = TexCoord.y; | |
u = abs(u-0.5f) * 2; | |
v = v * 2 - 1; | |
float v0 = v/u; | |
v0+=displacementV; | |
v0 = (v0 + 1) / 2; | |
float2 newCoords = float2(TexCoord.x,v0); | |
//horizontal info was stored in the Red component | |
return tex2D(shadowMapSampler, newCoords).r; | |
} | |
float GetShadowDistanceV(float2 TexCoord, float displacementV) | |
{ | |
float u = TexCoord.y; | |
float v = TexCoord.x; | |
u = abs(u-0.5f) * 2; | |
v = v * 2 - 1; | |
float v0 = v/u; | |
v0+=displacementV; | |
v0 = (v0 + 1) / 2; | |
float2 newCoords = float2(TexCoord.y,v0); | |
//vertical info was stored in the Green component | |
return tex2D(shadowMapSampler, newCoords).g; | |
} | |
float4 DrawShadowsPS( | |
float2 texCoord : TEXCOORD0 | |
) : COLOR0 | |
{ | |
// distance of this pixel from the center | |
float distance = length(texCoord - 0.5f); | |
distance *= RenderTargetSize.x; | |
// apply a 2-pixel bias | |
distance -= 2; | |
// distance stored in the shadow map | |
float shadowMapDistance; | |
// coords in [-1,1] | |
float nY = 2.0f * (texCoord.y - 0.5f); | |
float nX = 2.0f * (texCoord.x - 0.5f); | |
//we use these to determine which quadrant we are in | |
if (abs(nY) < abs(nX)) | |
{ | |
shadowMapDistance = GetShadowDistanceH(texCoord,0); | |
} | |
else | |
{ | |
shadowMapDistance = GetShadowDistanceV(texCoord,0); | |
} | |
shadowMapDistance *= RenderTargetSize.x; | |
//if distance to this pixel is lower than distance from shadowMap, | |
//then we are not in shadow | |
float light = distance < shadowMapDistance ? 1 : 0; | |
float4 result = light; | |
result.b = length(texCoord - 0.5f); | |
result.a = 1; | |
return result; | |
} | |
static const float2 oneZero = { 1, 0 }; | |
static const float2 zeroOne = { 0, 1 }; | |
static const float minBlur = 0.0f; | |
static const float maxBlur = 5.0f; | |
static const int blurSamples = 13; | |
static const float2 offsetAndWeight[blurSamples] = | |
{ | |
{ -6, 0.002216 }, | |
{ -5, 0.008764 }, | |
{ -4, 0.026995 }, | |
{ -3, 0.064759 }, | |
{ -2, 0.120985 }, | |
{ -1, 0.176033 }, | |
{ 0, 0.199471 }, | |
{ 1, 0.176033 }, | |
{ 2, 0.120985 }, | |
{ 3, 0.064759 }, | |
{ 4, 0.026995 }, | |
{ 5, 0.008764 }, | |
{ 6, 0.002216 }, | |
}; | |
float4 BlurHorizontallyPS( | |
float2 texCoord : TEXCOORD0 | |
) : COLOR0 | |
{ | |
float sum = 0; | |
float distance = tex2D(inputSampler, texCoord).b; | |
for (int i = 0; i < blurSamples; i++) | |
{ | |
sum += tex2D( | |
inputSampler, | |
texCoord + | |
offsetAndWeight[i].x * | |
lerp(minBlur, maxBlur, distance) / | |
RenderTargetSize.x * | |
oneZero | |
).r * offsetAndWeight[i].y; | |
} | |
float4 result = sum; | |
result.b = distance; | |
result.a = 1; | |
return result; | |
} | |
float4 BlurVerticallyPS( | |
float2 texCoord : TEXCOORD0 | |
) : COLOR0 | |
{ | |
float sum = 0; | |
float distance = tex2D(inputSampler, texCoord).b; | |
for (int i = 0; i < blurSamples; i++) | |
{ | |
sum += tex2D( | |
inputSampler, | |
texCoord + offsetAndWeight[i].x * | |
lerp(minBlur, maxBlur , distance) / | |
RenderTargetSize.x * | |
zeroOne | |
).r * offsetAndWeight[i].y; | |
} | |
float d = 2 * length(texCoord - 0.5f); | |
float attenuation = pow(saturate(1.0f - d), 1.0f); | |
float4 result = sum * attenuation; | |
result.a = 1; | |
return result; | |
} | |
technique Distort | |
{ | |
pass P0 | |
{ | |
VertexShader = compile vs_2_0 FullScreenVS(); | |
PixelShader = compile ps_2_0 DistortPS(); | |
} | |
} | |
technique DrawShadows | |
{ | |
pass P0 | |
{ | |
VertexShader = compile vs_3_0 FullScreenVS(); | |
PixelShader = compile ps_3_0 DrawShadowsPS(); | |
} | |
} | |
technique BlurHorizontally | |
{ | |
pass P0 | |
{ | |
VertexShader = compile vs_2_0 FullScreenVS(); | |
PixelShader = compile ps_2_0 BlurHorizontallyPS(); | |
} | |
} | |
technique BlurVertically | |
{ | |
pass P0 | |
{ | |
VertexShader = compile vs_2_0 FullScreenVS(); | |
PixelShader = compile ps_2_0 BlurVerticallyPS(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment