I made a custom Unity shader for the Universal Render Pipeline (URP). That script is working well inside the scene view, but strangely not game view, and neither in build.
That script uses the depth buffer of the camera to blend between two colors. The depth field is enabled on the camera.
You can find previews below (taken from same position) :
I got this result anywhere in the scene. When mouse is over the material component, it flickers strangely...
Did I do something weird, or is there a legit bug?
Here is my code for the shader :
Shader "DepthWater"
{
Properties
{
// Color of the shader at the shallowest parts, close to the shore
_ShallowWaterColor("Shallow Water Color", Color) = (0.3, 0.8, 0.98, 1.0)
// Color of the shader at the deepest part, at the center of the sea
_DeepWaterColor("Deep Water Color", Color) = (0.1, 0.4, 0.98, 1.0)
// The distance at which the water is considerer deep and will use the deep water color. More than that value won't make any blending.
_DeepWaterDistance("Depth Maximum Distance", Float) = 2
}
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Pass
{
HLSLPROGRAM
#pragma vertex UnlitPassVertex
#pragma fragment UnlitPassFragment
// The Core.hlsl file contains definitions of frequently used HLSL
// macros and functions, and also contains #include references to other
// HLSL files (for example, Common.hlsl, SpaceTransforms.hlsl, etc.).
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera depth texture.
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
struct Attributes
{
// The positionOS variable contains the vertex positions in object space.
float4 positionOS : POSITION;
};
struct Varyings
{
// The positions in this struct must have the SV_POSITION semantic.
float4 positionCS : SV_POSITION;
};
CBUFFER_START(UnityPerMaterial)
half4 _ShallowWaterColor;
half4 _DeepWaterColor;
half _DeepWaterDistance;
CBUFFER_END
float RawToLinearDepth(float rawSceneDepth)
{
return LinearEyeDepth(rawSceneDepth, _ZBufferParams);
}
Varyings UnlitPassVertex(Attributes IN)
{
Varyings OUT;
// calculate position on screen
VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
OUT.positionCS = positionInputs.positionCS; // ClipSpace
return OUT;
}
half4 UnlitPassFragment(Varyings input) : SV_Target
{
// To calculate the UV coordinates for sampling the depth buffer,
// divide the pixel location by the render target resolution
// _ScaledScreenParams.
float2 UV = input.positionCS.xy / _ScaledScreenParams.xy;
// Sample the depth from the Camera depth texture.
float rawSceneDepth = SampleSceneDepth(UV);
float waterDepth = RawToLinearDepth(rawSceneDepth) - input.positionCS.w;
float waterDepthNormalized = saturate(waterDepth / _DeepWaterDistance);
// float depthDifference = existingDepthLinear - IN.screenPosition.w;
half4 newColor = lerp(_ShallowWaterColor, _DeepWaterColor, waterDepthNormalized);
// Returning the _WaterColor value.
return newColor;
}
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}
Just found the answer : I indeed enabled the Depth Texture on the camera. However, it seems there is also a settings in URP for DepthPriming, inside the ForwardRenderer
settings. It is Disabled
by default, meaning that no depth priming is done by unity. Setting it to Auto
doesn't solve the problem strangely, but setting it to Forced
solves my problem.