TombEngine/Build/Light.fx

296 lines
No EOL
7.7 KiB
HLSL

#define LIGHTTYPE_SUN 0
#define LIGHTTYPE_POINT 1
#define LIGHTTYPE_SPOT 2
#define LIGHTTYPE_SHADOW 3
#define MODELTYPE_HORIZON 0
#define MODELTYPE_ROOM 1
#define MODELTYPE_MOVEABLE 2
#define MODELTYPE_STATIC 3
#define MODELTYPE_INVENTORY 4
#define MODELTYPE_PICKUP 5
#define MODELTYPE_LARA 6
#define MODELTYPE_SKY 7
#define MODELTYPE_WATER_SURFACE 8
#define MODELTYPE_ROOM_UNDERWATER 9
struct VertexShaderInput
{
float3 Position : POSITION0;
float2 TextureCoordinate : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TextureCoordinate : TEXCOORD0;
float4 ScreenPosition : TEXCOORD1;
};
struct PixelShaderOutput
{
float4 Light : COLOR0;
float4 Shadow : COLOR1;
};
float4 LightPosition;
float4 LightDirection;
float4 LightColor;
int LightType;
float LightIn;
float LightOut;
float LightIntensity;
float LightRange;
bool LightDynamic;
bool CastShadows;
float3 CameraPosition;
float4x4 World;
float4x4 View;
float4x4 Projection;
float4x4 ViewProjectionInverse;
float4x4 LightView;
float4x4 LightProjection;
bool AmbientPass;
float HalfPixelX;
float HalfPixelY;
texture2D ColorMap;
sampler ColorSampler = sampler_state
{
Texture = (ColorMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = LINEAR;
MinFilter = LINEAR;
Mipfilter = LINEAR;
};
texture2D DepthMap;
sampler DepthSampler = sampler_state
{
Texture = (DepthMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = POINT;
MinFilter = POINT;
Mipfilter = POINT;
};
texture2D NormalMap;
sampler NormalSampler = sampler_state
{
Texture = (NormalMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = POINT;
MinFilter = POINT;
Mipfilter = POINT;
};
texture2D VertexColorMap;
sampler VertexColorSampler = sampler_state
{
Texture = (VertexColorMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = LINEAR;
MinFilter = LINEAR;
Mipfilter = LINEAR;
};
/*texture2D CausticsMap;
sampler CausticsSampler = sampler_state
{
Texture = (CausticsMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = LINEAR;
MinFilter = LINEAR;
Mipfilter = LINEAR;
};*/
/*textureCUBE ShadowMapCube;
samplerCUBE ShadowMapCubeSampler = sampler_state {
texture = (ShadowMapCube);
MinFilter = Point;
MagFilter = Point;
MipFilter = None;
AddressU = Clamp;
AddressV = Clamp;
};*/
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
if (LightType == LIGHTTYPE_SUN)
output.Position = float4(input.Position, 1.0f);
else
{
float4 worldPosition = mul(float4(input.Position, 1.0f), World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
}
output.TextureCoordinate = input.TextureCoordinate - float2(HalfPixelX, HalfPixelY);
output.ScreenPosition = output.Position;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float4 output;
output = float4(0.0f, 0.0f, 0.0f, 0.0f);
float2 texCoord = input.TextureCoordinate;
if (LightType != LIGHTTYPE_SUN)
{
input.ScreenPosition.xy /= input.ScreenPosition.w;
texCoord = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1);
texCoord -= float2(HalfPixelX, HalfPixelY);
}
// Get the normal and transform back to -1 ... 1
float4 normalData = tex2D(NormalSampler, texCoord);
int modelType = round(normalData.w * 16.0f);
float3 normal = normalize(2.0f * normalData.xyz - 1.0f);
//normal.z = sqrt(1.0f - normal.x * normal.x - normal.y * normal.y);
float specularPower = 1.0f; // normalData.w;
// Get the depth value
float depthVal = tex2D(DepthSampler, texCoord).r;
// Sample caustics if needed
/*float4 caustics = float4(0.0f, 0.0f, 0.0f, 0.0f);
if (modelType == MODELTYPE_ROOM_UNDERWATER)
{
//return float4(1, 0, 0, 1);
// Compute screen-space position
float4 position;
position.xy = input.ScreenPosition.xy;
position.z = depthVal;
position.w = 1.0f;
// Transform to world space
position = mul(position, ViewProjectionInverse);
position /= position.w;
float fracX = position.x - floor(position.x / 2048.0f) * 2048.0f;
float fracY = position.y - floor(position.y / 2048.0f) * 2048.0f;
float fracZ = position.z - floor(position.z / 2048.0f) * 2048.0f;
float attenuation = saturate(dot(float3(0.0f, -1.0f, 0.0f), normal));
float3 blending = abs(normal);
blending = normalize(max(blending, 0.00001f));
float b = (blending.x + blending.y + blending.z);
blending /= float3(b, b, b);
float3 p = float3(fracX, fracY, fracZ) / 2048.0f;
float3 xaxis = tex2D(CausticsSampler, p.yz).rgb;
float3 yaxis = tex2D(CausticsSampler, p.xz).rgb;
float3 zaxis = tex2D(CausticsSampler, p.xy).rgb;
output += float4((xaxis * blending.x + yaxis * blending.y + zaxis * blending.z).xyz, 0.0f) * 0.10f * attenuation;
}*/
// We lit room geometry only in the case of dynamic lights
if ((modelType == MODELTYPE_ROOM || modelType == MODELTYPE_ROOM_UNDERWATER) && !LightDynamic)
{
// Is this light dynamic? In not, then I don't do any further calculations
return (output);
}
// Get specular intensity
float specularIntensity = tex2D(ColorSampler, texCoord).a;
// Now the shader is different according to light type
if (LightType == LIGHTTYPE_SUN)
{
// Compute screen-space position
float4 position;
position.x = input.TextureCoordinate.x * 2.0f - 1.0f;
position.y = -(input.TextureCoordinate.y * 2.0f - 1.0f);
position.z = depthVal;
position.w = 1.0f;
// Transform to world space
position = mul(position, ViewProjectionInverse);
position /= position.w;
// Surface-to-light vector
float3 lightVector = -normalize(LightDirection);
// Compute diffuse light
float NdL = max(0, dot(normal, lightVector));
float3 diffuseLight = NdL * LightColor.rgb;
// Reflection vector
float3 reflectionVector = normalize(reflect(lightVector, normal));
// Camera-to-surface vector
float3 directionToCamera = normalize(CameraPosition - position);
// Compute specular light
float specularLight = specularIntensity * pow(saturate(dot(reflectionVector, directionToCamera)), specularPower);
// Output the two lights
output = float4(diffuseLight.rgb, specularLight);
}
else if (LightType == LIGHTTYPE_POINT)
{
// Compute screen-space position
float4 position;
position.xy = input.ScreenPosition.xy;
position.z = depthVal;
position.w = 1.0f;
// Transform to world space
position = mul(position, ViewProjectionInverse);
position /= position.w;
// Surface-to-light vector
float3 lightVector = LightPosition - position;
// Compute attenuation based on distance - linear attenuation
float attenuation = saturate(1.0f - length(lightVector) / LightOut);
// Normalize light vector
lightVector = normalize(lightVector);
// Compute diffuse light
float NdL = pow((dot(normal, lightVector) * 0.5f) + 0.5f, 2); //max(0, dot(normal, lightVector));
float3 diffuseLight = NdL * LightColor.rgb;
// Reflection vector
float3 reflectionVector = normalize(reflect(-lightVector, normal));
// Camera-to-surface vector
float3 directionToCamera = normalize(CameraPosition - position);
// Compute specular light
float specularLight = specularIntensity * pow(saturate(dot(reflectionVector, directionToCamera)), specularPower);
// Take into account attenuation and lightIntensity.
output = attenuation * LightIntensity * float4(diffuseLight.rgb, specularLight) * 0.75f;
}
//output.a = 0.5f;
return output;
}
technique Light
{
pass Pass1
{
VertexShader = compile vs_3_0 VertexShaderFunction();
PixelShader = compile ps_3_0 PixelShaderFunction();
}
}