259 lines
5.2 KiB
HLSL
259 lines
5.2 KiB
HLSL
|
uniform float4x4 mvProj;
|
||
|
uniform float3 origin;
|
||
|
uniform float spacing;
|
||
|
uniform float3 extinction;
|
||
|
uniform float3 sunDir;
|
||
|
uniform float3 sunColor;
|
||
|
uniform float3 viewer;
|
||
|
|
||
|
uniform float3x3 basis;
|
||
|
uniform float3x3 invBasis;
|
||
|
uniform float2 textureSize;
|
||
|
uniform float3 viewDir;
|
||
|
uniform float visibility;
|
||
|
uniform float fade;
|
||
|
|
||
|
struct VSInput {
|
||
|
float4 position :
|
||
|
POSITION;
|
||
|
};
|
||
|
|
||
|
#ifdef DX9
|
||
|
|
||
|
struct VSOutput {
|
||
|
float4 position :
|
||
|
POSITION;
|
||
|
float3 intensity :
|
||
|
TEXCOORD0;
|
||
|
float3 view :
|
||
|
TEXCOORD1;
|
||
|
};
|
||
|
|
||
|
struct PSSceneIn {
|
||
|
float4 pos :
|
||
|
POSITION0;
|
||
|
float3 intensity :
|
||
|
TEXCOORD0;
|
||
|
float3 view :
|
||
|
TEXCOORD1;
|
||
|
};
|
||
|
|
||
|
struct PSSceneOut {
|
||
|
float4 color :
|
||
|
COLOR;
|
||
|
};
|
||
|
|
||
|
TEXTURE displacementMap;
|
||
|
TEXTURE slopeFoamMap;
|
||
|
|
||
|
sampler2D gDisplacementSampler = sampler_state {
|
||
|
Texture = (displacementMap);
|
||
|
MipFilter = LINEAR;
|
||
|
MinFilter = LINEAR;
|
||
|
MagFilter = LINEAR;
|
||
|
AddressU = WRAP;
|
||
|
AddressV = WRAP;
|
||
|
};
|
||
|
|
||
|
sampler2D gSlopeFoamSampler = sampler_state {
|
||
|
Texture = (slopeFoamMap);
|
||
|
MipFilter = LINEAR;
|
||
|
MinFilter = LINEAR;
|
||
|
MagFilter = LINEAR;
|
||
|
AddressU = WRAP;
|
||
|
AddressV = WRAP;
|
||
|
};
|
||
|
|
||
|
#else
|
||
|
|
||
|
struct VSOutput {
|
||
|
float4 position :
|
||
|
SV_Position;
|
||
|
float3 intensity :
|
||
|
TEXCOORD0;
|
||
|
float3 view :
|
||
|
TEXCOORD1;
|
||
|
};
|
||
|
|
||
|
struct PSSceneIn {
|
||
|
float4 pos :
|
||
|
SV_Position;
|
||
|
float3 intensity :
|
||
|
TEXCOORD0;
|
||
|
float3 view :
|
||
|
TEXCOORD1;
|
||
|
};
|
||
|
|
||
|
struct PSSceneOut {
|
||
|
float4 color :
|
||
|
SV_Target;
|
||
|
};
|
||
|
|
||
|
Texture2D displacementMap;
|
||
|
Texture2D slopeFoamMap;
|
||
|
|
||
|
SamplerState gTriLinearSamWrap {
|
||
|
Filter = MIN_MAG_MIP_LINEAR;
|
||
|
AddressU = WRAP;
|
||
|
AddressV = WRAP;
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
float3 CalculateWaterNormal(inout float3 v)
|
||
|
{
|
||
|
float3 localV = mul(v, basis);
|
||
|
float2 texCoords = localV.xy / textureSize;
|
||
|
|
||
|
#ifdef DX9
|
||
|
float4 tc4 = float4(texCoords.x, texCoords.y, 0.0f, 0.0f);
|
||
|
float3 slopesAndFoam = tex2Dlod(gSlopeFoamSampler, tc4).xyz;
|
||
|
float3 displacement = tex2Dlod(gDisplacementSampler, tc4).xyz;
|
||
|
#else
|
||
|
float3 slopesAndFoam = slopeFoamMap.SampleLevel(gTriLinearSamWrap, texCoords, 0).xyz;
|
||
|
float3 displacement = displacementMap.SampleLevel(gTriLinearSamWrap, texCoords, 0).xyz;
|
||
|
#endif
|
||
|
|
||
|
localV += displacement;
|
||
|
|
||
|
v = mul(localV, invBasis);
|
||
|
|
||
|
float3 sx = float3(1.0, 0.0, slopesAndFoam.x);
|
||
|
float3 sy = float3(0.0, 1.0, slopesAndFoam.y);
|
||
|
|
||
|
float3 nNorm = mul(normalize(cross(sx, sy)), invBasis);
|
||
|
|
||
|
return nNorm;
|
||
|
}
|
||
|
|
||
|
float FastFresnel(float3 I, float3 N)
|
||
|
{
|
||
|
const float R0 = 0.0204;
|
||
|
return R0 + (1.0 - R0) * pow(1 - dot(I, N), 5.0);
|
||
|
}
|
||
|
|
||
|
VSOutput VS(VSInput Input)
|
||
|
{
|
||
|
VSOutput Out;
|
||
|
|
||
|
float4 position = Input.position;
|
||
|
|
||
|
float3 worldPos = position.xyz * float3(spacing, 1, spacing);
|
||
|
worldPos += origin;
|
||
|
|
||
|
float3 normal = CalculateWaterNormal(worldPos);
|
||
|
float vertDist = length(worldPos - viewer);
|
||
|
float totalDist = position.w + vertDist;
|
||
|
|
||
|
if (position.w > 0) {
|
||
|
float3 refr = refract(-sunDir, normal, 1.0 / 1.333);
|
||
|
worldPos += refr * position.w;
|
||
|
Out.intensity = float3(0, 0, 0);
|
||
|
} else {
|
||
|
float tr = 1.0 - FastFresnel(sunDir, normal);
|
||
|
Out.intensity = exp(-totalDist * extinction) * tr * fade;
|
||
|
}
|
||
|
|
||
|
Out.view = worldPos - viewer;
|
||
|
|
||
|
float4 clipPos = mul(float4(worldPos, 1.0), mvProj);
|
||
|
clipPos.z = 0.01;
|
||
|
|
||
|
Out.position = clipPos;
|
||
|
|
||
|
return Out;
|
||
|
}
|
||
|
|
||
|
float ComputeMieScattering(in float3 V, in float3 sunDir)
|
||
|
{
|
||
|
const float g = 0.924;
|
||
|
// const float g = 0.7;
|
||
|
|
||
|
float cosTheta = dot(normalize(V), normalize(sunDir));
|
||
|
|
||
|
float num = 1.0 - g * g;
|
||
|
float den = (1.0 + g * g - 2.0 * g * cosTheta);
|
||
|
|
||
|
den = sqrt(den);
|
||
|
den = den * den * den;
|
||
|
|
||
|
float phase = (1.0 / (4.0 * 3.14159)) * (num / den);
|
||
|
|
||
|
return phase;
|
||
|
}
|
||
|
|
||
|
#ifdef DX9
|
||
|
PSSceneOut PS(float4 pos : VPOS, float3 pIntensity : TEXCOORD0, float3 pView : TEXCOORD1)
|
||
|
{
|
||
|
#else
|
||
|
PSSceneOut PS(PSSceneIn input)
|
||
|
{
|
||
|
float3 pView = input.view;
|
||
|
float3 pIntensity = input.intensity;
|
||
|
#endif
|
||
|
float3 up = mul(float3(0, 0, 1), invBasis);
|
||
|
float3 refractedLight = refract(-sunDir, up, 1.0 / 1.333);
|
||
|
|
||
|
float phase = ComputeMieScattering(-normalize(pView), refractedLight);
|
||
|
|
||
|
float3 finalIntensity = pIntensity * float3(phase, phase, phase);
|
||
|
finalIntensity *= exp(-length(pView) * (3.912 / visibility) * 8.0);
|
||
|
|
||
|
finalIntensity *= sunColor;
|
||
|
|
||
|
float4 color = float4(finalIntensity, 1.0);
|
||
|
|
||
|
color = clamp(color, 0.0, 1.0);
|
||
|
|
||
|
PSSceneOut output;
|
||
|
output.color = color;
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
#ifdef DX11
|
||
|
technique11 ColorTech {
|
||
|
pass P0
|
||
|
{
|
||
|
SetVertexShader(CompileShader(vs_5_0, VS()));
|
||
|
SetGeometryShader(NULL);
|
||
|
SetPixelShader(CompileShader(ps_5_0, PS()));
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef DX10
|
||
|
technique10 ColorTech {
|
||
|
pass P0
|
||
|
{
|
||
|
SetVertexShader(CompileShader(vs_4_0, VS()));
|
||
|
SetGeometryShader(NULL);
|
||
|
SetPixelShader(CompileShader(ps_4_0, PS()));
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef DX10LEVEL9
|
||
|
technique10 ColorTech {
|
||
|
pass P0
|
||
|
{
|
||
|
SetVertexShader(CompileShader(vs_4_0_level_9_1, VS()));
|
||
|
SetGeometryShader(NULL);
|
||
|
SetPixelShader(CompileShader(ps_4_0_level_9_1, PS()));
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef DX9
|
||
|
technique {
|
||
|
pass P0
|
||
|
{
|
||
|
SetVertexShader(CompileShader(vs_3_0, VS()));
|
||
|
#ifdef PS30
|
||
|
SetPixelShader(CompileShader(ps_3_0, PS()));
|
||
|
#else
|
||
|
SetPixelShader(CompileShader(ps_2_0, PS()));
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
#endif
|