Hello there,
I’m currently trying to make a outline post processing shader in HDRP.
I roughly follow the article from VertexFragment (Sobel Outline with Unity Post-Processing · Vertex Fragment) and it works (mostly), but I have this wierd issue, where the outline jumpes around all the time. Its really distracting. Additionally it only happens in game view, not in scene view.
I think it has something to do with the depth and GBuffer2 texture, since a different effect (also using the depth texture) has a similar problem.
To my testing enviroment: Sample HDRP-Scene and a simple post processing script that displays the parameters.
Perhaps someone can help me with that issue.
Shader:
/* Shader based on:
* https://www.vertexfragment.com/ramblings/unity-postprocessing-sobel-outline/
*/
Shader "Hidden/Shader/OutlineShader"
{
HLSLINCLUDE
#pragma target 4.5
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/FXAA.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/RTUpscale.hlsl"
struct Attributes
{
uint vertexID : SV_VertexID;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings Vert(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID);
return output;
}
// List of properties to control your post process effect
float _Intensity;
float _OutlineThickness;
float _OutlineDepthMultiplier;
float _OutlineDepthBias;
float _OutlineNormalMultiplier;
float _OutlineNormalBias;
float3 _OutlineColor;
TEXTURE2D_X(_InputTexture);
TEXTURE2D_X(_GBufferTexture1);
float SobelDepth(float center, float left, float right, float up, float down) {
return abs(left - center) + abs(right - center) + abs(up - center) + abs(down - center);
}
float SobelSampleDepth(float2 uv, float3 offset) {
float pixelCenter = LinearEyeDepth(LOAD_TEXTURE2D_X(_CameraDepthTexture, uv).r, _ZBufferParams);
float pixelLeft = LinearEyeDepth(LOAD_TEXTURE2D_X(_CameraDepthTexture, uv - offset.xz).r, _ZBufferParams);
float pixelRight = LinearEyeDepth(LOAD_TEXTURE2D_X(_CameraDepthTexture, uv + offset.xz).r, _ZBufferParams);
float pixelUp = LinearEyeDepth(LOAD_TEXTURE2D_X(_CameraDepthTexture, uv + offset.zy).r, _ZBufferParams);
float pixelDown = LinearEyeDepth(LOAD_TEXTURE2D_X(_CameraDepthTexture, uv - offset.zy).r, _ZBufferParams);
return SobelDepth(pixelCenter, pixelLeft, pixelRight, pixelUp, pixelDown);
}
float4 SobelNormal(float2 uv, float3 offset)
{
float4 pixelCenter = LOAD_TEXTURE2D_X(_GBufferTexture1, uv);
float4 pixelLeft = LOAD_TEXTURE2D_X(_GBufferTexture1, uv - offset.xz);
float4 pixelRight = LOAD_TEXTURE2D_X(_GBufferTexture1, uv + offset.xz);
float4 pixelUp = LOAD_TEXTURE2D_X(_GBufferTexture1, uv + offset.zy);
float4 pixelDown = LOAD_TEXTURE2D_X(_GBufferTexture1, uv - offset.zy);
return abs(pixelLeft - pixelCenter) + abs(pixelRight - pixelCenter) + abs(pixelUp - pixelCenter) + abs(pixelDown - pixelCenter);
}
float4 CustomPostProcess(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
uint2 positionSS = input.texcoord * _ScreenSize.xy;
//return float4(input.texcoord, 0, 1);
float3 outColor = LOAD_TEXTURE2D_X(_InputTexture, positionSS).xyz;
//return float4(LOAD_TEXTURE2D_X(_GBufferTexture1, positionSS).rgb, 1);
float3 offset = float3((1.0 / _ScreenParams.x), (1.0 / _ScreenParams.y), 0.0) * _OutlineThickness;
float sobelDepth = SobelSampleDepth(positionSS, offset);
sobelDepth = pow(saturate(sobelDepth) * _OutlineDepthMultiplier, _OutlineDepthBias);
float4 sobelNormalCalc = SobelNormal(positionSS, offset);
float sobelNormal = sobelNormalCalc.x + sobelNormalCalc.y + sobelNormalCalc.z;
sobelNormal = pow(sobelNormal * _OutlineNormalMultiplier, _OutlineNormalBias);
float outline = saturate(max(sobelDepth, sobelNormal));
float3 outlineColor = lerp(outColor, _OutlineColor, _Intensity);
outColor = lerp(outColor, outlineColor, outline);
return float4(outColor, 1);
}
ENDHLSL
SubShader
{
Pass
{
Name "OutlineShader"
ZWrite Off
ZTest Always
Blend Off
Cull Off
HLSLPROGRAM
#pragma fragment CustomPostProcess
#pragma vertex Vert
ENDHLSL
}
}
Fallback Off
}