mirror of
https://github.com/ncblakely/GiantsTools
synced 2024-11-14 18:55:37 +01:00
364 lines
9.7 KiB
HLSL
364 lines
9.7 KiB
HLSL
//--------------------------------------------------------------------------------------
|
|
// LandBump.fx
|
|
|
|
// Land bumpmapping and lighting shader.
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
#include "../fxh/Constants.fxh"
|
|
#include "../fxh/Lighting.fxh"
|
|
#include "../fxh/Transform.fxh"
|
|
#include "../fxh/Fog.fxh"
|
|
|
|
shared WorldTransforms g_WorldTransforms;
|
|
shared ViewTransforms g_ViewTransforms;
|
|
|
|
shared texture g_Texture0;
|
|
shared texture g_Texture1;
|
|
shared texture g_Texture2;
|
|
shared float4x4 g_TexGenMatrix0;
|
|
shared float4x4 g_TexGenMatrix1;
|
|
shared float4x4 g_TexGenMatrix2;
|
|
|
|
shared DirectionalLightInfo g_DirectionalLights;
|
|
shared PointLightInfo g_PointLights;
|
|
|
|
shared FogParams g_Fog;
|
|
|
|
float g_DetailFadeStart = 150;
|
|
float g_DetailFadeEnd = 500;
|
|
|
|
//////////////////////////////////////////////////////
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Texture samplers
|
|
//--------------------------------------------------------------------------------------
|
|
sampler g_LandTextureSampler =
|
|
sampler_state
|
|
{
|
|
Texture = <g_Texture0>;
|
|
MipFilter = LINEAR;
|
|
MinFilter = LINEAR;
|
|
MagFilter = LINEAR;
|
|
};
|
|
|
|
sampler g_LandBumpTextureSampler =
|
|
sampler_state
|
|
{
|
|
Texture = <g_Texture1>;
|
|
MipFilter = LINEAR;
|
|
MinFilter = LINEAR;
|
|
MagFilter = LINEAR;
|
|
};
|
|
|
|
sampler g_LandDetailTextureSampler =
|
|
sampler_state
|
|
{
|
|
Texture = <g_Texture2>;
|
|
MipFilter = LINEAR;
|
|
MinFilter = LINEAR;
|
|
MagFilter = LINEAR;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Vertex shader output structure
|
|
//--------------------------------------------------------------------------------------
|
|
struct LandBumpDetailVSOutput
|
|
{
|
|
float4 Position : POSITION;
|
|
float4 LandBumpDiffuse : COLOR1;
|
|
float4 LandDiffuse : COLOR0;
|
|
float2 LandBumpTextureUV : TEXCOORD0;
|
|
float2 LandTextureUV : TEXCOORD1;
|
|
float2 LandDetailTextureUV : TEXCOORD2;
|
|
float3 WorldPos : TEXCOORD3;
|
|
float3 Normal : TEXCOORD4;
|
|
float Fog : FOG;
|
|
};
|
|
|
|
inline float4 bx2(float4 x)
|
|
{
|
|
return float4(2.0f * x.xyzw - 1.0f);
|
|
}
|
|
|
|
float4 CalculateDetailTexture(float3 worldPos, float4 originalColor, float2 detailTextureUV)
|
|
{
|
|
if (detailTextureUV.x != 0 || detailTextureUV.y != 0)
|
|
{
|
|
float distance = length(worldPos - g_ViewTransforms.CameraPosition);
|
|
if (distance < g_DetailFadeEnd)
|
|
{
|
|
float4 detailTextureColor = tex2D(g_LandDetailTextureSampler, detailTextureUV) * 1.8f;
|
|
|
|
if (distance > g_DetailFadeStart)
|
|
{
|
|
float distNormalized = distance / (g_DetailFadeEnd - g_DetailFadeStart);
|
|
detailTextureColor = lerp(detailTextureColor, float4(1.f, 1.f, 1.f, 1.f), distNormalized);
|
|
}
|
|
|
|
originalColor *= detailTextureColor;
|
|
}
|
|
}
|
|
|
|
return originalColor;
|
|
}
|
|
|
|
LandBumpDetailVSOutput LandBumpDetailVS(
|
|
float4 position : POSITION,
|
|
float3 normal : NORMAL,
|
|
float4 landBumpDiffuse : COLOR0,
|
|
float4 landDiffuse : COLOR1)
|
|
{
|
|
LandBumpDetailVSOutput output;
|
|
|
|
// Transform the position from object space to homogeneous projection space
|
|
output.Position = mul(position, g_WorldTransforms.WorldViewProjection);
|
|
|
|
output.LandDiffuse = landDiffuse * .5f;
|
|
output.LandDiffuse.a = 1.0f;
|
|
|
|
output.LandBumpDiffuse.rgb = landBumpDiffuse;
|
|
output.LandBumpDiffuse.a = 1.0f;
|
|
|
|
output.WorldPos = mul(position, g_WorldTransforms.World);
|
|
|
|
// Set dynamically generated tex coords
|
|
output.LandBumpTextureUV = mul(position, g_TexGenMatrix0);
|
|
output.LandTextureUV = mul(position, g_TexGenMatrix1);
|
|
output.LandDetailTextureUV = mul(position, g_TexGenMatrix2);
|
|
|
|
float3 P = mul(position, g_WorldTransforms.WorldView);
|
|
output.Fog = CalculateFogFactor(g_Fog.FogMax, g_Fog.FogMin, length(P));
|
|
|
|
// Transform the normal from object space to world space
|
|
output.Normal = normalize(mul(normal, (float3x3)g_WorldTransforms.World)); // normal (world space)
|
|
|
|
return output;
|
|
}
|
|
|
|
float4 CalculateDot3BumpMap(float4 diffuseColor, float2 uv)
|
|
{
|
|
float4 landBumpTextureColor = bx2(tex2D(g_LandBumpTextureSampler, uv));
|
|
diffuseColor = bx2(diffuseColor);
|
|
|
|
float4 bumpMapColor;
|
|
bumpMapColor.xyz = saturate(dot(landBumpTextureColor, diffuseColor.rgb));
|
|
bumpMapColor.w = 1.0f;
|
|
|
|
return bumpMapColor;
|
|
}
|
|
|
|
struct TNBFrame
|
|
{
|
|
float3 Tangent;
|
|
float3 Normal;
|
|
float3 Binormal;
|
|
};
|
|
|
|
/*
|
|
TNBFrame CalculateTNBFrame(float3 worldPos, float3 N, float2 uv)
|
|
{
|
|
float3 dp1 = ddx(worldPos);
|
|
float3 dp2 = ddy(worldPos);
|
|
float2 duv1 = ddx(uv);
|
|
float2 duv2 = ddy(uv);
|
|
|
|
|
|
float3 dp2perp = cross(dp2, N);
|
|
float3 dp1perp = cross(N, dp1);
|
|
float3 T = dp2perp * duv1.x + dp1perp * duv2.x;
|
|
float3 B = dp2perp * duv1.y + dp1perp * duv2.y;
|
|
|
|
float invmax = rsqrt(max(dot(T, T), dot(B, B)));
|
|
|
|
TNBFrame frame;
|
|
frame.Tangent = T * invmax;
|
|
frame.Normal = N;
|
|
frame.Binormal = B * invmax;
|
|
return frame;
|
|
}
|
|
*/
|
|
|
|
TNBFrame CalculateTNBFrame(float3 worldPos, float3 N, float2 uv)
|
|
{
|
|
float3 dp1 = ddx(worldPos);
|
|
float3 dp2 = ddy(worldPos);
|
|
float2 duv1 = ddx(uv);
|
|
float2 duv2 = ddy(uv);
|
|
|
|
float3 t = normalize(duv2.y * dp1 - duv1.y * dp2);
|
|
float3 b = normalize(duv2.x * dp1 - duv1.x * dp2);
|
|
float3 n = normalize(N);
|
|
float3 x = cross(n, t);
|
|
t = cross(x, n);
|
|
t = normalize(t);
|
|
|
|
x = cross(b, n);
|
|
b = cross(n, x);
|
|
b = normalize(b);
|
|
|
|
TNBFrame frame;
|
|
frame.Tangent = t;
|
|
frame.Normal = n;
|
|
frame.Binormal = b;
|
|
return frame;
|
|
}
|
|
|
|
float4 CalculateNormalMap(float3 worldPos, float3 normal, float2 uv, float4 diffuse)
|
|
{
|
|
TNBFrame tnbFrame = CalculateTNBFrame(worldPos, normal, uv);
|
|
|
|
// Sample the pixel in the bump map.
|
|
float4 bumpMap = tex2D(g_LandBumpTextureSampler, uv) + diffuse;
|
|
|
|
// Expand the range of the normal value from (0, +1) to (-1, +1).
|
|
bumpMap = (bumpMap * 2.0f) - 1.0f;
|
|
|
|
// Calculate the normal from the data in the bump map.
|
|
float3 bumpNormal = (bumpMap.x * tnbFrame.Tangent) + (bumpMap.y * tnbFrame.Binormal) + (bumpMap.z * tnbFrame.Normal);
|
|
|
|
// Normalize the resulting bump normal.
|
|
bumpNormal = normalize(bumpNormal);
|
|
|
|
// Invert the light direction for calculations.
|
|
float3 lightDir = -g_DirectionalLights.Direction[g_DirectionalLights.SunIndex];
|
|
|
|
// Calculate the amount of light on this pixel based on the bump map normal value.
|
|
float lightIntensity = saturate(dot(bumpNormal, lightDir));
|
|
|
|
// Determine the final diffuse color based on the diffuse color and the amount of light intensity.
|
|
float4 color = saturate(lightIntensity);
|
|
|
|
return color;
|
|
}
|
|
|
|
float4 LandBumpDetailPS(LandBumpDetailVSOutput input) : COLOR0
|
|
{
|
|
float4 landTextureColor = tex2D(g_LandTextureSampler, input.LandTextureUV);
|
|
|
|
|
|
#if 1
|
|
float4 bumpMapColor = CalculateDot3BumpMap(input.LandBumpDiffuse, input.LandBumpTextureUV);
|
|
float4 finalColor = 2.0 * (bumpMapColor * (landTextureColor) + input.LandDiffuse);
|
|
#else
|
|
float4 bumpMapColor = CalculateNormalMap(input.WorldPos, input.Normal, input.LandTextureUV, input.LandBumpDiffuse);
|
|
float4 bumpMapColor = CalculateDirectionalDiffuse(input.Normal, -g_DirectionalLights.Direction[g_DirectionalLights.SunIndex], float4(1, 1, 1, 1));
|
|
|
|
float4 finalColor = (bumpMapColor * landTextureColor) + input.LandDiffuse;
|
|
#endif
|
|
|
|
finalColor = CalculateDetailTexture(input.WorldPos, finalColor, input.LandDetailTextureUV);
|
|
|
|
for (int i = 0; i < g_PointLights.Count; i++)
|
|
{
|
|
float3 worldPos = g_PointLights.Position[i] - input.WorldPos;
|
|
float3 lightDirection = normalize(input.WorldPos - (g_PointLights.Position[i]));
|
|
|
|
finalColor += CalculatePointDiffuse(
|
|
worldPos,
|
|
input.Normal,
|
|
-lightDirection,
|
|
g_PointLights.Range[i],
|
|
g_PointLights.Diffuse[i]);
|
|
}
|
|
|
|
if (g_Fog.Enabled)
|
|
{
|
|
finalColor = ApplyPixelFog(finalColor, input.Fog, g_Fog.Color);
|
|
}
|
|
|
|
finalColor.a = 1.0f;
|
|
return finalColor;
|
|
}
|
|
|
|
technique LandBumpDetail
|
|
{
|
|
pass P0
|
|
{
|
|
VertexShader = compile vs_3_0 LandBumpDetailVS();
|
|
PixelShader = compile ps_3_0 LandBumpDetailPS();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Vertex shader output structure
|
|
//--------------------------------------------------------------------------------------
|
|
struct VS_OUTPUT
|
|
{
|
|
float4 Position : POSITION;
|
|
float4 Diffuse : COLOR0;
|
|
float2 TextureUV : TEXCOORD0;
|
|
float3 Normal : TEXCOORD1;
|
|
float3 WorldPos : TEXCOORD2;
|
|
};
|
|
|
|
matrix Identity =
|
|
{
|
|
{ 1, 0, 0, 0 },
|
|
{ 0, 1, 0, 0 },
|
|
{ 0, 0, 1, 0 },
|
|
{ 0, 0, 0, 1 }
|
|
};
|
|
|
|
VS_OUTPUT LandscapeVS(
|
|
float4 vPos : POSITION,
|
|
float3 vNormal : NORMAL,
|
|
float4 vDiffuse : COLOR0)
|
|
{
|
|
VS_OUTPUT Output;
|
|
|
|
// Transform the position from object space to homogeneous projection space
|
|
Output.Position = mul(vPos, g_WorldTransforms.WorldViewProjection);
|
|
|
|
// Transform the normal from object space to world space
|
|
Output.Normal = normalize(mul(vNormal, (float3x3)g_WorldTransforms.World)); // normal (world space)
|
|
|
|
Output.Diffuse.rgb = vDiffuse;
|
|
Output.Diffuse.a = 1.0f;
|
|
|
|
Output.WorldPos = mul(vPos, g_WorldTransforms.World);
|
|
|
|
//float3 P = mul(vPos, g_WorldView); //position in view space
|
|
// Set dynamically generated tex coords
|
|
//P* (iTexGenType == TEXGEN_TYPE_CAMERASPACEPOSITION), 0)
|
|
/*
|
|
float4x4 scaleMatrix = Identity;
|
|
int index = G_TexUaxis[g_PrimBufferIndex];
|
|
scaleMatrix[0][0] = g_TexUScale;
|
|
scaleMatrix[1][G_TexVaxis[g_PrimBufferIndex]] = g_TexVScale;
|
|
*/
|
|
|
|
//Output.TextureUV = mul(vPos, (scaleMatrix * g_World));
|
|
Output.TextureUV = mul(vPos, g_TexGenMatrix0);
|
|
|
|
return Output;
|
|
}
|
|
|
|
float4 LandscapePS(VS_OUTPUT input) : COLOR0
|
|
{
|
|
float4 finalColor = 0;
|
|
|
|
for (int i = 0; i < g_PointLights.Count; i++)
|
|
{
|
|
float3 worldPos = g_PointLights.Position[i] - input.WorldPos;
|
|
float3 lightDirection = normalize(input.WorldPos - (g_PointLights.Position[i]));
|
|
|
|
finalColor += CalculatePointDiffuse(
|
|
worldPos,
|
|
input.Normal,
|
|
-lightDirection,
|
|
g_PointLights.Range[i],
|
|
g_PointLights.Diffuse[i]);
|
|
}
|
|
|
|
float3 texel = tex2D(g_LandTextureSampler, input.TextureUV);
|
|
return float4(saturate((texel.xyz + input.Diffuse) + (finalColor)), 1.0f);
|
|
}
|
|
|
|
technique Landscape
|
|
{
|
|
pass P0
|
|
{
|
|
VertexShader = compile vs_2_0 LandscapeVS();
|
|
PixelShader = compile ps_2_0 LandscapePS();
|
|
}
|
|
} |