Skip to content

Instantly share code, notes, and snippets.

@jcdickinson
Created April 14, 2012 12:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jcdickinson/2384073 to your computer and use it in GitHub Desktop.
Save jcdickinson/2384073 to your computer and use it in GitHub Desktop.
Shadows HLSL
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