问题描述
在明度较暗的场景中,常会遇到明显的色彩断层问题,即在本应平滑过渡的灰度渐变中出现了明显的色阶分层。这种现象严重影响了美术效果,尤其是在VR显示中尤为显著。
解决思路
为了解决这个问题,我们主要采用使用噪点(noise)来打破平直的边界的方法。在屏幕空间中增加不易察觉的噪点,可以有效干扰原本平直的渐变边界,从而使难看的渐变越阶变得更加光滑。
如上图所示,这是为了便于观察而夸张处理的情况。实际应用中,可以通过调整噪点强度以达到不影响画面的效果。该方法源自平面设计,但其原理相同,只需在引擎中用shader实现即可。
最终与原像素混合的方式需要根据具体情况决定,同时也要限制好受影响的范围,以确保整体视觉效果的优化。
ASE截图
HLSL范例代码
Shader "Unlit/PixelNoise"
{
Properties
{
[SingleLineTexture]
_BaseColor ("BaceColro", 2D) = "white" {}
[SingleLineTexture]
_PixelNoise ("PixelNoise", 2D) = "white" {}
_NoiseInt ("NoiseInt" , range(0.0,1.0)) = 0.2
_PixelNoiseTilingSpeed ("PixelNoiseTiling&Speed", Vector) = ( 10, 10, 10, 10)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct appdata
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0 ;
float4 clipPosV : TEXCOORD1 ;
};
sampler2D _PixelNoise;
sampler2D _BaseColor;
uniform float4 _PixelNoiseTilingSpeed;
uniform float _NoiseInt;
v2f vert (appdata v)
{
v2f o;
VertexPositionInputs vertexInput = GetVertexPositionInputs( v.positionOS.xyz );
o.positionCS = vertexInput.positionCS;
o.clipPosV = vertexInput.positionCS;
o.uv = v.uv;
return o;
}
float4 frag (v2f i ) : SV_Target
{
float4 ScreenPos = ComputeScreenPos(i.clipPosV);
float4 screenPosUV = ScreenPos / ScreenPos.w;
float2 PixelNoiseUVSpeed = frac(_TimeParameters.x * _PixelNoiseTilingSpeed.zw);
float2 PixelNoiseUV = screenPosUV * _PixelNoiseTilingSpeed.xy + PixelNoiseUVSpeed;
float PixelNoise = (tex2D(_PixelNoise, PixelNoiseUV.xy ).r * _NoiseInt);
float3 baseColor = tex2D(_BaseColor, i.uv + PixelNoise);
return float4(baseColor,1);
}
ENDHLSL
}
}
}
Noise贴图