Created
September 16, 2025 19:02
-
-
Save unvestigate/0d82591956c2573f1a42f4a6ad25fc8e to your computer and use it in GitHub Desktop.
Water surface shader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "hlsl_include/basis_shader.h" | |
| #include "hlsl_include/lighting_scene.h" | |
| #include "hlsl_include/pixel_data.h" | |
| #include "hlsl_include/water.h" | |
| #autobind Texture2D gWaterDUDVMap; | |
| //#autobind Texture2D gWaterNormalMap; | |
| struct VertexIn | |
| { | |
| float3 position : POSITION; | |
| float3 normal : NORMAL; | |
| float2 texCoord : TEXCOORD0; | |
| }; | |
| struct VertexOut | |
| { | |
| float3 positionWS : POSITION; // World space position. | |
| float2 texCoord : TEXCOORD0; // Texture coordinate. | |
| float4 position : SV_POSITION; // Clip space position. | |
| float4 positionClip : POSITION2; | |
| /*#ifdef BASIS_ENABLE_CUSTOM_CLIPPING_PLANES | |
| float customClipDistance : SV_ClipDistance0; | |
| #endif*/ | |
| }; | |
| VertexOut VS(VertexIn vin) | |
| { | |
| VertexOut vout; | |
| /* | |
| #if BASIS_SPIRV == 1 | |
| vin.world = transpose(vin.world); | |
| #endif | |
| */ | |
| float4x4 world = gWaterWorld; | |
| float4x4 worldview = mul(gCameraView, world); | |
| float4x4 wvp = mul(gCameraProjection, worldview); | |
| vout.position = mul(wvp, float4(vin.position, 1.0f)); | |
| vout.positionWS = mul(world, float4(vin.position, 1.0f)).xyz; | |
| vout.positionClip = vout.position; | |
| vout.texCoord = vin.texCoord; | |
| /*#ifdef BASIS_ENABLE_CUSTOM_CLIPPING_PLANES | |
| vout.customClipDistance = dot(float4(vout.positionWS, 1.0f), gCustomClippingPlane); | |
| #endif*/ | |
| return vout; | |
| } | |
| PixelData PS(VertexOut pin) | |
| { | |
| float3 pixelToCamera = gCameraPosition - pin.positionWS; | |
| float2 texCoords = pin.texCoord * float2(gWaterTexScaleX, gWaterTexScaleY); | |
| // Calculate the projected texture coordinates, for sampling from the relf/refr textures. | |
| float2 ndc = ((pin.positionClip.xy / pin.positionClip.w) * 0.5f) + 0.5f; | |
| float2 reflectionCoords = float2(ndc.x, ndc.y); | |
| float2 refractionCoords = float2(ndc.x, -ndc.y); | |
| // Sample the refraction pass depth buffer and compare the value to the value of the current pixel | |
| // to get the water depth along the view vector, for this surface pixel. | |
| float rawDepth = __BasisWaterRefrDepthMap.Sample(__BasisSampler_PointWrap, refractionCoords).x; | |
| float bottomToCameraDistance = getLinearDepthBufferValue_BrokenFixMe(rawDepth); | |
| float surfaceToCameraDistance = getLinearDepthBufferValue_BrokenFixMe(pin.position.z); | |
| float waterDepth = bottomToCameraDistance - surfaceToCameraDistance; | |
| // Calculate the texture coordinates for distortion on the water surface. | |
| float distortionTime = gWorldTime * gWaterWaveAnimationSpeed; | |
| float2 distortedTexCoords = gWaterDUDVMap.Sample(__BasisSampler_LinearWrap, float2(texCoords.x + distortionTime, texCoords.y)).xy * gWaterWaveScale; | |
| distortedTexCoords = texCoords + float2(distortedTexCoords.x, distortedTexCoords.y + distortionTime); | |
| // The total distortion is multiplied by the wave strength as well as the water depth. | |
| // This makes the distrortion smaller when the water is shallower, helping eliminate | |
| // artifacts caused by the distortion. | |
| float2 totalDistortion = (gWaterDUDVMap.Sample(__BasisSampler_LinearWrap, distortedTexCoords).xy * 2.0f - 1.0f) * gWaterWaveStrength * saturate(waterDepth); | |
| // Apply the distortion to the texture coords for the relf/refr textures. | |
| reflectionCoords += totalDistortion; | |
| reflectionCoords.x = clamp(reflectionCoords.x, 0.001, 0.999); | |
| refractionCoords += totalDistortion; | |
| refractionCoords.x = clamp(refractionCoords.x, 0.001, 0.999); | |
| refractionCoords.y = clamp(refractionCoords.y, -0.999, -0.001); | |
| float4 reflColor = __BasisWaterReflMap.Sample(__BasisSampler_LinearWrap, reflectionCoords); | |
| float4 refrColor = __BasisWaterRefrMap.Sample(__BasisSampler_LinearWrap, refractionCoords); | |
| // Apply the "deep" water color to the refractionColor. | |
| float depthColorFactor = remapFloat(waterDepth, gDeepWaterFadeStart, gDeepWaterFadeEnd, 0.0f, 1.0f); | |
| refrColor = lerp(refrColor, gDeepWaterColor, depthColorFactor); | |
| float3 normal = float3(0.0f, 1.0f, 0.0f); | |
| // Calculate the fresnel value, to determine how much reflection vs refraction. | |
| float3 viewVector = normalize(pixelToCamera); | |
| float reflectionFactor = saturate(dot(viewVector, normal)); | |
| reflectionFactor = pow(reflectionFactor, gWaterReflectionStrength); | |
| // Apply the fresnel. | |
| float4 litColor = lerp(reflColor, refrColor, saturate(reflectionFactor)); | |
| // Apply color tinting. | |
| litColor = lerp(litColor, gWaterColorTint, gWaterColorTintAmount); | |
| // Apply fog. | |
| litColor = applyFogToPixel(pin.positionWS, gCameraPosition.xyz, litColor); | |
| // Fade out the water in shallow areas. | |
| litColor.a = saturate(waterDepth / gWaterFullOpacityDepth); | |
| return getPixelData(litColor, float4(0.0f, 0.0f, 0.0f, 0.0f)); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment