Files
bluflame/evoke-64k/trunk/ev10/cfg/psray.txt
2026-04-18 22:31:51 +02:00

298 lines
11 KiB
Plaintext

float3 lightDir : register(c1);
float3 viewPos : register(c2);
float3 viewDir : register(c4);
float3 passID2expIsLast : register(c23);
float4 g_fGlow : register(c61);
sampler2D colorSampler : register(s0);
sampler2D depthSampler : register(s1);
sampler2D waveSampler : register(s3);
sampler2D shadowSampler : register(s4);
// Tweakables
static float4 g_fRayColor = float4(1.75f * 0.45f, 1.75f * 0.4f, 1.75f * 0.35f, 1.0f);
static float g_fRayNearPlane = 10.0f;
static float g_fRayFarPlane = 500.0f;
static float g_fRayDensity = 0.25f;
static float g_fRayDecay = 0.9125f;
static float g_fRayAnglePersistence = 4.f;
float4 ps_ray_mask(float2 TexCoord : TEXCOORD0, float2 LightPos : TEXCOORD2) : COLOR0
{
float2 d = LightPos - TexCoord;
float r = saturate( 1.f - dot(d, d) );
r *= saturate( g_fRayAnglePersistence * dot(-lightDir, viewDir) );
float m = tex2D(depthSampler, TexCoord).x;
m = saturate( (m - g_fRayNearPlane) / (g_fRayFarPlane - g_fRayNearPlane) );
// m = saturate(1.f - m);
// float2 p = TexCoord * 2.0f - 1.0f;
// float b = saturate( 1.0f - 0.7071f * dot(p, p) );
return /* b */ m * r * g_fRayColor;
}
// Pixel shader
float4 ps_ray_extrude(float2 TexCoord : TEXCOORD0, float2 LightPos : TEXCOORD2) : COLOR0
{
float2 s = g_fRayDensity / (passID2expIsLast.y) * (LightPos - TexCoord) / 8.f;
float4 r = 0.f, ro = 0.f, rm = 0.f, rd = .125f;
float2 c = TexCoord;
for(int i = 0; i < 8; i++)
{
float4 rs = tex2D(colorSampler, c);
ro = (i == 0) ? rs : ro;
rm = max(rs, rm);
rs.xyz = rm.xyz;
r += rs * rd;
rd.xyz *= (float3)g_fRayDecay;
c += s;
}
r.xyz *= 1.0f + 0.25f * g_fGlow.z;
r.a = min(ro.a, r.a);
return r * saturate(1.f - passID2expIsLast.z * r.a);
}
float3 g_fTime : register(c3);
// Tweakables
static float g_fWaterLevel = 5.0f;
static float4 g_fLightFilterColor = float4(0.4f, 0.75f, 0.8f, 0.99f); // float4(0.8f, 0.85f, 0.9f, 0.8f);
static float g_fFilterOffset = 0.0f;
static float g_fLightFilterDensity = 0.02f;
static float g_fCausticScaling = 0.004f;
static float g_fCausticDistortion = 0.1f;
static float4 g_fCausticPatternScaling = 0.25f;
static float2 g_vCausticSpeed = float2(0.05f, 0.1f);
static float g_fCausticBrightness = 0.35f;
float4 ps_underwater_filter(float2 TexCoord : TEXCOORD0, float3 EyeDir : TEXCOORD1,
float2 LightPos : TEXCOORD2) : COLOR0
{
// Compute eye space position
float fEyeDepth = tex2D(depthSampler, TexCoord).x;
float3 vEyePoint = viewPos + fEyeDepth * EyeDir;
float3 vEyeNormal = normalize( cross( ddx(vEyePoint), ddy(vEyePoint) ) );
// Compute distance to water level
float fUnderWater = g_fWaterLevel - vEyePoint.y;
float fLightTravel = max( fUnderWater / max(-lightDir.y, 0.0001f), 0.0f );
// Intersect water plane
float3 vSubmerged = vEyePoint - viewPos;
float fSubmergedBelow = (fUnderWater >= 0.0f)
? abs(vSubmerged.y)
: (g_fWaterLevel - viewPos.y);
float fSubmerged = (viewPos.y > g_fWaterLevel)
? max(fUnderWater, 0.0f)
: fSubmergedBelow;
vSubmerged *= fSubmerged / max( abs(vSubmerged.y), 0.0001f );
// Compute submerged length
fSubmerged = length(vSubmerged);
// Compute light color
float4 fFilterDist= fLightTravel + float2(fSubmerged, 0.0f).xxxy;
float4 fLightColor = pow(g_fLightFilterColor, g_fLightFilterDensity * fFilterDist );
// Color hack
fLightColor.xyz *= pow(g_fLightFilterColor.xyz, max(fLightTravel - 30, 0) * 0.08f);
// Compute light coordinate space
float3 vLightU = normalize( cross( lightDir, float3(1.0f, 0.0f, 0.0f) ) );
float3 vLightV = normalize( cross( vLightU, lightDir ) );
// Scale time
float fTime = g_fTime.z * 0.000095f;
// Animate caustics
float2 fCausticCoord = float2( dot(vLightU, vEyePoint), dot(vLightV, vEyePoint) ) * g_fCausticScaling;
float2 fCausticCoordDelta = fTime * g_vCausticSpeed * g_fCausticScaling;
float3 bx = float3(2.0f, 1.0f, 0.0f);
// Get caustic normal
float3 vCausticNormal1 = normalize( tex2D(waveSampler, fCausticCoord - fCausticCoordDelta).xzy * bx.xyx - bx.yzy );
float3 vCausticNormal2 = normalize( tex2D(waveSampler, fCausticCoord.yx + fCausticCoordDelta).xzy * bx.xyx - bx.yzy );
float3 vCausticNormal3 = normalize( tex2D(waveSampler, 5 * (fCausticCoord - 2 * fCausticCoordDelta)).xzy * bx.xyx - bx.yzy );
float3 vCausticNormal4 = normalize( tex2D(waveSampler, 5 * (fCausticCoord.yx + 2 * fCausticCoordDelta)).xzy * bx.xyx - bx.yzy );
// Compute normals used for distortion & lighting
float3 vCausticNormalX1 = vCausticNormal1 + vCausticNormal4 / 3.0f;
float3 vCausticNormalX2 = vCausticNormal2 + vCausticNormal3 / 3.0f;
float3 vCausticNormal = vCausticNormalX1 + vCausticNormalX2;
vCausticNormal = normalize(vCausticNormal);
// Compute caustic pattern
float4 fCausticPattern = float2( dot(vEyePoint, vLightU), dot(vEyePoint, vLightV) ).xyxy;
fCausticPattern.xy += g_fCausticDistortion * vCausticNormalX1.xz * (1.0f + fEyeDepth); // + 1000 * dc.yx;
fCausticPattern.zw += g_fCausticDistortion * vCausticNormalX2.xz * (1.0f + fEyeDepth); // - 1000 * dc.xy;
fCausticPattern *= g_fCausticPatternScaling;
fCausticPattern = 2.0f * (fCausticPattern - round(fCausticPattern));
float fCaustics = dot(fCausticPattern, fCausticPattern) * g_fCausticBrightness;
// Sharpen
fCaustics *= fCaustics;
fCaustics *= fCaustics;
// Cut at surface
fCaustics *= saturate(fUnderWater);
// Remove underside lighting
fCaustics *= saturate( dot(vEyeNormal, -lightDir) ) * tex2D(shadowSampler, TexCoord).x;
float3 vSurfacePoint = vEyePoint - vSubmerged;
vSurfacePoint.y = 0.0f;
float fFadeOut = saturate( max(dot(vSurfacePoint, vSurfacePoint) - 2000000.0f, 0.0f) / 10000000.0f )
* saturate(fUnderWater);
// Filter light
return lerp(float4(fLightColor.xyz, fLightColor.w * fCaustics), float2(1, 0).xxxy, fFadeOut);
}
// Tweakables
static float4 g_fFogColor = float4(0.1f, 0.18f, 0.17f, 0.0f); // float4(0.6f, 0.7f, 0.9f, 0.25f);
static float g_fFogDensity = 0.7f;
static float g_fSceneFog = 0.6f;
static float g_fRayScaling = 0.024f;
static float2 g_vRaySpeed = float2(0.03f, 0.02f);
float4 ps_underwater(float2 TexCoord : TEXCOORD0, float3 EyeDir : TEXCOORD1,
float2 LightPos : TEXCOORD2) : COLOR0
{
// Compute eye space position
float fEyeDepth = tex2D(depthSampler, TexCoord).x;
float3 vEyePoint = viewPos + fEyeDepth * EyeDir;
// Compute distance to water level
float fUnderWater = g_fWaterLevel - vEyePoint.y;
// Intersect water plane
float3 vSubmerged = vEyePoint - viewPos;
float fSubmergedBelow = (fUnderWater >= 0.0f)
? abs(vSubmerged.y)
: (g_fWaterLevel - viewPos.y);
float fSubmerged = (viewPos.y > g_fWaterLevel)
? max(fUnderWater, 0.0f)
: fSubmergedBelow;
vSubmerged *= fSubmerged / max( abs(vSubmerged.y), 0.0001f );
// Compute submerged length & normalize
fSubmerged = length(vSubmerged);
float3 vSubmergedDir = vSubmerged / max(fSubmerged, 0.0001f);
// Pre-compute light travel quantities
float fEyeLightTravel = max( (g_fWaterLevel - viewPos.y) / max(-lightDir.y, 0.0001f), 0.0f );
float fDeltaLightTravel = vSubmergedDir.y / min(lightDir.y, -0.0001f);
float fSubmergedLightTravel = fEyeLightTravel + fDeltaLightTravel * fSubmerged;
float4 fLogLightFilterColor = log(g_fLightFilterColor);
float4 fFog = g_fFogColor / (fLogLightFilterColor * g_fLightFilterDensity * fDeltaLightTravel - g_fFogDensity);
fFog *= exp(fLogLightFilterColor * (g_fFilterOffset + g_fLightFilterDensity * fSubmergedLightTravel) - g_fFogDensity * fSubmerged)
- exp(fLogLightFilterColor * (g_fFilterOffset + g_fLightFilterDensity) * fEyeLightTravel);
// "Absorb" more scene light
fFog.w = g_fSceneFog * (1.0f - exp(-g_fFogDensity * fSubmerged));
// fFog.w = dot(fFog.xyz, 0.1f);
// fFog.w = 1.0f - fFog.w;
// fFog.w = 0;
// Compute light coordinate space
float3 vLightU = normalize( cross( lightDir, float3(1.0f, 0.0f, 0.0f) ) );
float3 vLightV = normalize( cross( vLightU, lightDir ) );
// Parallel ray direction vector
float3 vRayDir = EyeDir - lightDir * dot(lightDir, EyeDir);
vRayDir = normalize(vRayDir);
float3 vFullRayDir = EyeDir / dot(EyeDir, vRayDir);
// 1 / submerged flat
float3 vSubmergedFlatInvScale = vSubmerged - lightDir * dot(lightDir, vSubmerged);
vSubmergedFlatInvScale /= max( dot(vSubmergedFlatInvScale, vSubmergedFlatInvScale), 0.0001f );
// 4 ray Planes
float4 fPlanes = float4(5.0f, 10.0f, 20.0f, 40.0f);
float4 fPlaneIntersect = fPlanes * dot(vRayDir, vSubmergedFlatInvScale);
float4 fPlaneSubmerged = vSubmerged.y * fPlaneIntersect;
// float fWeightScaling = saturate( 1.0f - 0.1f * dot(viewDir, -lightDir) ); // polar
float4 fPlaneWeight = 1.0f - saturate( 0.5f * (fPlaneIntersect - 1.0f) );
// Compute light travel
float4 fPlanesY = g_fWaterLevel - (viewPos.y + vFullRayDir.y * fPlanes);
float4 fPlanesLightTravel = max( fPlanesY / max(-lightDir.y, 0.0001f), 0.0f );
float4 fPlanesLightInt = 1.0f / (1.0f + 0.01f * fPlanesLightTravel * fPlanesLightTravel);
// return float4(fPlanesLightInt.yyy, 1.0f);
// Snap view pos
// float3 vSnappedViewPos = vLightU * floor( dot(vLightU, viewPos) / 25.0f ) * 25.0f
// + vLightV * floor( dot(vLightV, viewPos) / 25.0f ) * 25.0f;
// fPlanes += dot(viewPos - vSnappedViewPos, vRayDir);
// Scale time
float fTime = g_fTime.z * 0.000075f;
// Animate rays
float4 fRayCoordsX = dot(vLightU, viewPos) + dot(vLightU, vRayDir) * fPlanes;
float4 fRayCoordsY = dot(vLightV, viewPos) + dot(vLightV, vRayDir) * fPlanes;
// fPlanes = dot(vLightU, vRayDir) * tx - dot(vLightV, vRayDir) * ty - 2.0f * dot(viewPos, vRayDir);
fRayCoordsX *= g_fRayScaling; fRayCoordsY *= g_fRayScaling;
float2 fRayCoordDelta = fTime * g_vRaySpeed * g_fRayScaling;
// Sample rays
float4 fRay1 = tex2D(waveSampler, float2(fRayCoordsX.x, fRayCoordsY.x) + fPlanes.x * fRayCoordDelta).xzyw;
float4 fRay2 = tex2D(waveSampler, float2(fRayCoordsX.y, fRayCoordsY.y) - fPlanes.y * fRayCoordDelta).xzyw;
float4 fRay3 = tex2D(waveSampler, float2(fRayCoordsX.z, fRayCoordsY.z) + fPlanes.z * fRayCoordDelta).xzyw;
float4 fRay4 = tex2D(waveSampler, float2(fRayCoordsX.w, fRayCoordsY.w) - fPlanes.w * fRayCoordDelta).xzyw;
// Decode Normal
float3 vRayNormal = (fRay1.xyz + fRay2.xyz + fRay3.xyz + fRay4.xyz) / 4.0f;
vRayNormal.xz = vRayNormal.xz * 2.0f - 1.0f;
vRayNormal = normalize(vRayNormal);
float4 fLight;
// Light
fLight.x = fRay1.w;
fLight.y = fRay2.w;
fLight.z = fRay3.w;
fLight.w = fRay4.w;
// fLight *= fLight * fLight;
float fLightSubmerged = 0.05f * max( fPlaneIntersect * dot(vSubmerged, lightDir), 0.0f);
// Fade rays
fLight *= fPlanesLightInt * fPlaneWeight * saturate(fSubmerged) / (1.0f + fLightSubmerged * fLightSubmerged);
fLight *= saturate(g_fWaterLevel - viewPos.y + 1.0f);
float fRayAngle = saturate( 1.0f - dot(vRayNormal, -lightDir) );
float fRayColor = 0.1f * saturate( dot(EyeDir, vRayNormal - lightDir) );
fRayAngle = frac( fRayAngle );
float3 fLightColor = 1.0f;
fLightColor.r += saturate( 1.0f - pow(3.0f * fRayAngle - 3.0f * (fRayAngle > 1.0f / 3.0f), 2) ) * fRayColor;
fLightColor.g += saturate( 1.0f - pow(3.0f * fRayAngle - 1.0f, 2) ) * fRayColor;
fLightColor.b += saturate( 1.0f - pow(3.0f * fRayAngle - 2.0f, 2) ) * fRayColor;
// God rays
fFog.xyz += dot(fLight, 0.04f) * fLightColor;
float3 vSurfacePoint = vEyePoint - vSubmerged;
vSurfacePoint.y = 0.0f;
float fFadeOut = 1.0f - saturate( max(dot(vSurfacePoint, vSurfacePoint) - 2000000.0f, 0.0f) / 10000000.0f )
* saturate(fUnderWater);
return fFog * fFadeOut;
}