Skip to content

Instantly share code, notes, and snippets.

@demonixis
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save demonixis/0abd8cf52deb30761beb to your computer and use it in GitHub Desktop.
Save demonixis/0abd8cf52deb30761beb to your computer and use it in GitHub Desktop.
A shader to render a textured scene object with a shadow map in a XNA/MonoGame application
float4x4 World;
float4x4 View;
float4x4 Projection;
float4x4 lightView;
float4x4 lightProjection;
float3 lightPosition;
float3 lightRadius = float3(100.0, 100.0, 100.0);
float shadowMapSize = 512;
float bias = 7.0 / 1000.0;
float random(float3 seed, int i)
{
float4 seed4 = float4(seed, i);
float dotProduct = dot(seed4, float4(12.9898, 78.233, 45.164, 94.673));
return frac(sin(dotProduct) * 43758.5453);
}
texture mainTexture;
sampler textureSampler = sampler_state
{
texture = (mainTexture);
minfilter = linear;
magfilter = linear;
mipfilter = linear;
addressu = wrap;
addressv = wrap;
};
texture shadowTexture;
sampler shadowSampler = sampler_state
{
texture = (shadowTexture);
minfilter = point;
magfilter = point;
mipfilter = point;
addressu = clamp;
addressv = clamp;
};
struct VertexShaderInput
{
float4 Position : POSITION0;
float2 tex_coord:TEXCOORD0;
float3 normal:NORMAL0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 tex_coord:TEXCOORD0;
float4 worldPosition:TEXCOORD1;
float2 screenPosition:TEXCOORD2;
float3 normal:TEXCOORD3;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.tex_coord = input.tex_coord;
output.worldPosition = worldPosition;
output.screenPosition = output.Position.xy/output.Position.w;
output.normal = mul(input.normal,World);
return output;
}
float calcShadowPCF(float lightSpaceDepth, float2 shadowCoordinates)
{
float size = 1.0 / shadowMapSize;
float shadowTerm = 0;
float samples[4];
samples[0] = (lightSpaceDepth - bias < tex2D(shadowSampler, shadowCoordinates).r);
samples[1] = (lightSpaceDepth - bias < tex2D(shadowSampler, shadowCoordinates + float2(size, 0)).r);
samples[2] = (lightSpaceDepth - bias < tex2D(shadowSampler, shadowCoordinates + float2(0, size)).r);
samples[3] = (lightSpaceDepth - bias < tex2D(shadowSampler, shadowCoordinates + float2(size, size)).r);
shadowTerm = (samples[0] + samples[1] + samples[2] + samples[3]) / 4.0;
return shadowTerm;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float4 color = tex2D(textureSampler, input.tex_coord);
float4 worldPosition = input.worldPosition;
float3 lightDirection = lightPosition - worldPosition;
float inverseLightRadiusSquared = 1.0 / (lightRadius * lightRadius);
float lightFactor = 0;
float attenuation = 0;
float ndl = 0;
//transform to light space
float4 lightSpacePosition = mul(mul(worldPosition, lightView), lightProjection);
lightSpacePosition -= bias;
lightSpacePosition /= lightSpacePosition.w;
float2 screenPosition = 0.5 + float2(lightSpacePosition.x, -lightSpacePosition.y) * 0.5;
float lightSpaceDepth = lightSpacePosition.z;
//light influence
attenuation = 1 - saturate(dot(lightDirection, lightDirection) * inverseLightRadiusSquared);
ndl = saturate(dot(input.normal, lightDirection));
lightFactor = attenuation*ndl;
float shadowTerm = 1;
if((saturate(screenPosition).x == screenPosition.x) && (saturate(screenPosition).y == screenPosition.y))
shadowTerm = calcShadowPCF(lightSpaceDepth, screenPosition);
return color * lightFactor * shadowTerm;
}
technique Technique1
{
pass Pass1
{
#if SM4
VertexShader = compile vs_4_0_level_9_3 VertexShaderFunction();
PixelShader = compile ps_4_0_level_9_3 PixelShaderFunction();
#else
VertexShader = compile vs_3_0 VertexShaderFunction();
PixelShader = compile ps_3_0 PixelShaderFunction();
#endif
}
}
@tomspilman
Copy link

The MojoShader translation to a GLSL shader looses all default values in any shader constants. So for example the values in poissonDisk will all default to zero.

You either need to set these from your C# code, or change it to static float2 poissonDisk[4].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment