I have shader for geometry pass and for light pass, I understand theory how it should works, but when I try to implement this, my brain explode. Could some one explain me how could I implement shadows from my directional light here ?
******************** GEOMETRY SHADER *************************cbuffer ProjectionBuffer : register(b0)
{
matrix projectionMatrix;
};
cbuffer ViewBuffer : register(b1)
{
matrix viewMatrix;
};
cbuffer WorldBuffer : register(b2)
{
matrix worldMatrix;
};
struct VSInput
{
float3 Position : POSITION;
float2 TexCoord : TEXCOORD;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
};
struct VSOutput
{
float4 Position : SV_Position;
float2 TexCoord : TEXCOORD;
float3 WorldPos : WORLD_POS;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
};
VSOutput main(VSInput input)
{
VSOutput output;
float4 worldPos = mul(float4(input.Position, 1.0f), worldMatrix);
float4 viewPos = mul(worldPos, viewMatrix);
output.Position = mul(viewPos, projectionMatrix);
output.WorldPos = worldPos.xyz;
output.Normal = mul((float3x3)worldMatrix, input.Normal);
output.Tangent = mul((float3x3)worldMatrix, input.Tangent);
output.TexCoord = input.TexCoord;
return output;
}
*******************************************************cbuffer AmbientLight : register(b1)
{
float3 ambientLight;
float padding;
};
Texture2D myTexture : register(t0);
SamplerState samplerState : register(s0);
struct PSInput
{
float4 Position : SV_Position;
float2 TexCoord : TEXCOORD;
float3 WorldPos : WORLD_POS;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
};
struct PSOutput
{
float4 Diffuse : SV_Target0;
float4 Normal : SV_Target1;
float4 Position : SV_Target2;
float4 Plane : SV_Target3;
};
PSOutput main(PSInput input)
{
PSOutput output;
output.Diffuse = myTexture.Sample(samplerState, input.TexCoord) * float4(ambientLight, 1.0f);
output.Normal = float4(normalize(input.Normal), 1.0);
output.Position = float4(input.WorldPos, 1.0);
return output;
}
***************** LIGHT SHADER **************struct VSInput
{
float3 Position : POSITION;
float2 TexCoord : TEXCOORD;
};
struct VSOutput
{
float4 Position : SV_Position;
float2 TexCoord : TEXCOORD;
};
VSOutput main(VSInput input)
{
VSOutput output;
output.Position = float4(input.Position, 1.0);
output.TexCoord = input.TexCoord;
return output;
}
***********************************************struct Light
{
int Type;
float3 Position;
float3 Direction;
float3 Color;
float Intensity;
float Range;
float SpotAngle;
};
struct DirectionalLight
{
float3 Direction;
float Intensity;
float3 Color;
float Padding;
};
StructuredBuffer<Light> Lights : register(t4);
cbuffer LightInfo : register(b0)
{
int LightCount;
int align[3];
};
cbuffer DirectionalLight : register(b2)
{
DirectionalLight directionalLight;
};
float3 CalculateDirectionalLight(DirectionalLight directionalLight, float3 normal)
{
float3 lightDir = normalize(-directionalLight.Direction);
float diff = max(dot(normal, lightDir), 0.0);
return directionalLight.Color * diff * directionalLight.Intensity;
}
float3 CalculatePointLight(Light light, float3 worldPos, float3 normal)
{
float3 lightDir = light.Position - worldPos;
float distance = length(lightDir);
lightDir = normalize(lightDir);
float diff = max(dot(normal, lightDir), 0.0);
float attenuation = 1.0 / (distance * distance + 1e-4);
if (distance < light.Range)
{
return light.Color * diff * attenuation * light.Intensity;
}
return float3(0, 0, 0);
}
float3 CalculateSpotLight(Light light, float3 worldPos, float3 normal)
{
float3 lightDir = light.Position - worldPos;
float distance = length(lightDir);
lightDir = normalize(lightDir);
float theta = dot(lightDir, normalize(-light.Direction));
float epsilon = cos(radians(light.SpotAngle) * 0.5);
if (theta > epsilon && distance < light.Range)
{
float diff = max(dot(normal, lightDir), 0.0);
float attenuation = 1.0 / (distance * distance + 1e-4);
float spotEffect = smoothstep(epsilon, 1.0, theta);
return light.Color * diff * attenuation * spotEffect * light.Intensity;
}
return float3(0, 0, 0);
}
Texture2D DiffuseTexture : register(t0);
Texture2D NormalTexture : register(t1);
Texture2D PositionTexture : register(t2);
SamplerState samplerState : register(s0);
struct PSInput
{
float4 Position : SV_Position;
float2 TexCoord : TEXCOORD;
};
float4 main(PSInput input) : SV_Target
{
float4 diffuse = DiffuseTexture.Sample(samplerState, input.TexCoord);
float3 normal = normalize(NormalTexture.Sample(samplerState, input.TexCoord).xyz);
float3 worldPos = PositionTexture.Sample(samplerState, input.TexCoord).xyz;
float3 finalColor = float3(1.0f, 1.0f, 1.0f);
finalColor += CalculateDirectionalLight(directionalLight, normal);
for (int i = 0; i < LightCount; ++i)
{
Light light = Lights[i];
if (light.Type == 0)
{
finalColor += CalculatePointLight(light, worldPos, normal);
}
else if (light.Type == 1)
{
finalColor += CalculateSpotLight(light, worldPos, normal);
}
}
return float4(finalColor * diffuse.rgb, diffuse.a);
}