415 lines
14 KiB
GLSL
415 lines
14 KiB
GLSL
/*
|
|
MIT License
|
|
|
|
Copyright (c) 2022 Pascal Zwick
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
Shader "Hidden/TemporalAAShader"
|
|
{
|
|
Properties
|
|
{
|
|
_MainTex ("Main Texture", 2D) = "white" {}
|
|
_TemporalFade("Temporal Fade", Range(0, 1)) = 0.0
|
|
}
|
|
SubShader
|
|
{
|
|
// No culling or depth
|
|
Cull Back ZWrite Off ZTest Always
|
|
|
|
Pass //0
|
|
{
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
|
|
#include "UnityCG.cginc"
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float2 uv : TEXCOORD0;
|
|
float4 vertex : SV_POSITION;
|
|
};
|
|
|
|
v2f vert (appdata v)
|
|
{
|
|
v2f o;
|
|
o.vertex = UnityObjectToClipPos(v.vertex);
|
|
o.uv = v.uv;
|
|
return o;
|
|
}
|
|
|
|
sampler2D _MainTex;
|
|
|
|
//sampler2D _MotionVectorTexture;
|
|
sampler2D _CameraDepthTexture;
|
|
|
|
sampler2D _TemporalAATexture;
|
|
|
|
float _TemporalFade;
|
|
float _MovementBlending;
|
|
bool _UseFlipUV;
|
|
|
|
float4x4 _invP;
|
|
float4x4 _FrameMatrix;
|
|
|
|
|
|
float sampleDepth(float2 uv) {
|
|
//float rd = _CameraDepthTexture.Load(int3(pix, 0)).x;
|
|
float rd = tex2D(_CameraDepthTexture, uv).x;
|
|
return Linear01Depth(rd);
|
|
}
|
|
|
|
/*
|
|
Box intersection by IQ, modified for neighbourhood clamping
|
|
https://www.iquilezles.org/www/articles/boxfunctions/boxfunctions.htm
|
|
*/
|
|
float2 boxIntersection(in float3 ro, in float3 rd, in float3 rad)
|
|
{
|
|
float3 m = 1.0 / rd;
|
|
float3 n = m * ro;
|
|
float3 k = abs(m) * rad;
|
|
float3 t1 = -n - k;
|
|
float3 t2 = -n + k;
|
|
|
|
float tN = max(max(t1.x, t1.y), t1.z);
|
|
float tF = min(min(t2.x, t2.y), t2.z);
|
|
|
|
return float2(tN, tF);
|
|
}
|
|
|
|
/*
|
|
* GLSL Color Spaces by tobspr
|
|
* https://github.com/tobspr/GLSL-Color-Spaces
|
|
*/
|
|
// RGB to YCbCr, ranges [0, 1]
|
|
float3 rgb_to_ycbcr(float3 rgb) {
|
|
float y = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b;
|
|
float cb = (rgb.b - y) * 0.565;
|
|
float cr = (rgb.r - y) * 0.713;
|
|
|
|
return float3(y, cb, cr);
|
|
}
|
|
|
|
// YCbCr to RGB
|
|
float3 ycbcr_to_rgb(float3 yuv) {
|
|
return float3(
|
|
yuv.x + 1.403 * yuv.z,
|
|
yuv.x - 0.344 * yuv.y - 0.714 * yuv.z,
|
|
yuv.x + 1.770 * yuv.y
|
|
);
|
|
}
|
|
//###
|
|
|
|
float3 clipLuminance(float3 col, float3 minCol, float3 maxCol){
|
|
float3 c0 = rgb_to_ycbcr(col);
|
|
//float3 c1 = rgb_to_ycbcr(minCol);
|
|
//float3 c2 = rgb_to_ycbcr(maxCol);
|
|
|
|
//c0 = clamp(c0, c1, c2);
|
|
c0 = clamp(c0, minCol, maxCol);
|
|
|
|
return ycbcr_to_rgb(c0);
|
|
}
|
|
|
|
float4 frag(v2f i) : SV_Target
|
|
{
|
|
|
|
float2 baseUV = i.uv;
|
|
if (_UseFlipUV)
|
|
i.uv.y = 1 - i.uv.y;
|
|
|
|
float4 curCol = tex2D(_MainTex, i.uv);
|
|
|
|
//temporal reprojection
|
|
float d0 = sampleDepth(i.uv);
|
|
float d01 = (d0 * (_ProjectionParams.z - _ProjectionParams.y) + _ProjectionParams.y) / _ProjectionParams.z;
|
|
float3 pos = float3(baseUV * 2.0 - 1.0, 1.0);
|
|
float4 rd = mul(_invP, float4(pos, 1));
|
|
rd.xyz /= rd.w;
|
|
|
|
float4 temporalUV = mul(_FrameMatrix, float4(rd.xyz * d01, 1));
|
|
temporalUV /= temporalUV.w;
|
|
|
|
//float2 temporalUV = i.uv - tex2D(_MotionVectorTexture, i.uv).xy;
|
|
float3 lastCol = tex2D(_TemporalAATexture, temporalUV*0.5+0.5).xyz;
|
|
if (abs(temporalUV.x) > 1 || abs(temporalUV.y) > 1)
|
|
lastCol = curCol;
|
|
//
|
|
|
|
// Neighbourhood clipping
|
|
//float3 ya = rgb_to_ycbcr(curCol);
|
|
float3 ya = curCol;
|
|
float3 minCol = ya;
|
|
float3 maxCol = ya;
|
|
|
|
for (int x = -1; x <= 1; ++x) {
|
|
for (int y = -1; y <= 1; ++y) {
|
|
float2 duv = float2(x, y) / _ScreenParams.xy;
|
|
//float3 s = rgb_to_ycbcr(tex2D(_MainTex, i.uv + duv).xyz);
|
|
float3 s = tex2D(_MainTex, i.uv + duv).xyz;
|
|
|
|
minCol = min(minCol, s);
|
|
maxCol = max(maxCol, s);
|
|
}
|
|
}
|
|
//lastCol = mul(YCoCgToRGBMatrix, clamp(mul(RGBToYCoCgMatrix, lastCol), minCol, maxCol));
|
|
lastCol = clamp(lastCol, minCol, maxCol);
|
|
//lastCol = clipLuminance(lastCol, minCol, maxCol);
|
|
//
|
|
|
|
float temporalMultiplier = exp(-_MovementBlending * length(pos.xy - temporalUV));
|
|
float3 finalCol = lerp(curCol, lastCol, _TemporalFade * temporalMultiplier);
|
|
//finalCol = length(minCol - maxCol).xxx;
|
|
|
|
return float4(finalCol, 1);
|
|
}
|
|
ENDCG
|
|
}
|
|
|
|
|
|
//// GRAPH
|
|
Pass //1 BLIT
|
|
{
|
|
Name "ColorBlitPass"
|
|
HLSLPROGRAM
|
|
// Core.hlsl includes URP basic variables needed for any shader. The Blit.hlsl provides a
|
|
//Vert and Fragment function that abstracts platform differences when handling a full screen shader pass.
|
|
//It also declares a _BlitTex texture that is bound by the Blitter API.
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
//#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
|
// This is a simple read shader so we use the default provided Vert and FragNearest
|
|
//functions. If you would like to do a bilinear sample you could use the FragBilinear functions instead.
|
|
#include "BlitTAA.hlsl"//v0.2
|
|
|
|
#pragma vertex Vert
|
|
#pragma fragment FragNearest
|
|
ENDHLSL
|
|
}
|
|
Pass //2 BLIT BACKGROUND
|
|
{
|
|
Name "ColorBlitPasss"
|
|
HLSLPROGRAM
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
//#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
|
#include "BlitTAA.hlsl"//v0.2
|
|
#pragma vertex Vert
|
|
#pragma fragment Frag
|
|
//
|
|
float4 Frag(VaryingsB input) : SV_Target0
|
|
{
|
|
// this is needed so we account XR platform differences in how they handle texture arrays
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
// sample the texture using the SAMPLE_TEXTURE2D_X_LOD
|
|
float2 uv = input.texcoord.xy;
|
|
half4 color = SAMPLE_TEXTURE2D_X_LOD(_BlitTexture, sampler_LinearRepeat, uv, _BlitMipLevel);
|
|
// Inverts the sampled color
|
|
//return half4(1, 1, 1, 1) - color;
|
|
return color;
|
|
}
|
|
ENDHLSL
|
|
}
|
|
|
|
Pass //3
|
|
{
|
|
HLSLPROGRAM//CGPROGRAM
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include "BlitTAA.hlsl"//v0.2
|
|
#pragma vertex Vert
|
|
|
|
//#pragma vertex vert
|
|
#pragma fragment frag
|
|
|
|
|
|
/// #include "UnityCG.cginc"
|
|
float4 UnityObjectToClipPos( in float3 pos )
|
|
{
|
|
#if defined(UNITY_SINGLE_PASS_STEREO) || defined(UNITY_USE_CONCATENATED_MATRICES)
|
|
// More efficient than computing M*VP matrix product
|
|
return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0)));
|
|
#else
|
|
return mul(UNITY_MATRIX_MVP, float4(pos, 1.0));
|
|
#endif
|
|
}
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float2 texcoord : TEXCOORD0;
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float2 texcoord : TEXCOORD0;
|
|
float4 vertex : SV_POSITION;
|
|
};
|
|
|
|
v2f vert (appdata v)
|
|
{
|
|
v2f o;
|
|
o.vertex = UnityObjectToClipPos(v.vertex);
|
|
o.texcoord = v.texcoord;
|
|
return o;//
|
|
}
|
|
|
|
sampler2D _MainTex;
|
|
|
|
//sampler2D _MotionVectorTexture;
|
|
sampler2D _CameraDepthTexture;
|
|
|
|
sampler2D _TemporalAATexture;
|
|
|
|
float _TemporalFade;
|
|
float _MovementBlending;
|
|
bool _UseFlipUV;
|
|
|
|
float4x4 _invP;
|
|
float4x4 _FrameMatrix;
|
|
|
|
|
|
float sampleDepth(float2 uv) {
|
|
//float rd = _CameraDepthTexture.Load(int3(pix, 0)).x;
|
|
float rd = tex2D(_CameraDepthTexture, uv).x;
|
|
return Linear01Depth(rd, _ZBufferParams);///v0.1
|
|
}
|
|
|
|
/*
|
|
Box intersection by IQ, modified for neighbourhood clamping
|
|
https://www.iquilezles.org/www/articles/boxfunctions/boxfunctions.htm
|
|
*/
|
|
float2 boxIntersection(in float3 ro, in float3 rd, in float3 rad)
|
|
{
|
|
float3 m = 1.0 / rd;
|
|
float3 n = m * ro;
|
|
float3 k = abs(m) * rad;
|
|
float3 t1 = -n - k;
|
|
float3 t2 = -n + k;
|
|
|
|
float tN = max(max(t1.x, t1.y), t1.z);
|
|
float tF = min(min(t2.x, t2.y), t2.z);
|
|
|
|
return float2(tN, tF);
|
|
}
|
|
|
|
/*
|
|
* GLSL Color Spaces by tobspr
|
|
* https://github.com/tobspr/GLSL-Color-Spaces
|
|
*/
|
|
// RGB to YCbCr, ranges [0, 1]
|
|
float3 rgb_to_ycbcr(float3 rgb) {
|
|
float y = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b;
|
|
float cb = (rgb.b - y) * 0.565;
|
|
float cr = (rgb.r - y) * 0.713;
|
|
|
|
return float3(y, cb, cr);
|
|
}
|
|
|
|
// YCbCr to RGB
|
|
float3 ycbcr_to_rgb(float3 yuv) {
|
|
return float3(
|
|
yuv.x + 1.403 * yuv.z,
|
|
yuv.x - 0.344 * yuv.y - 0.714 * yuv.z,
|
|
yuv.x + 1.770 * yuv.y
|
|
);
|
|
}
|
|
//###
|
|
|
|
float3 clipLuminance(float3 col, float3 minCol, float3 maxCol){
|
|
float3 c0 = rgb_to_ycbcr(col);
|
|
//float3 c1 = rgb_to_ycbcr(minCol);
|
|
//float3 c2 = rgb_to_ycbcr(maxCol);
|
|
|
|
//c0 = clamp(c0, c1, c2);
|
|
c0 = clamp(c0, minCol, maxCol);
|
|
|
|
return ycbcr_to_rgb(c0);
|
|
}
|
|
|
|
float4 frag(VaryingsB i) : SV_Target ///////////// BASIC must become VaryingsB!!!!!!!!!!!!1
|
|
{
|
|
|
|
float2 baseUV = i.texcoord;
|
|
if (_UseFlipUV)
|
|
i.texcoord.y = 1 - i.texcoord.y;
|
|
|
|
float4 curCol = tex2D(_MainTex, i.texcoord);
|
|
|
|
//temporal reprojection
|
|
float d0 = sampleDepth(i.texcoord);
|
|
float d01 = (d0 * (_ProjectionParams.z - _ProjectionParams.y) + _ProjectionParams.y) / _ProjectionParams.z;
|
|
float3 pos = float3(baseUV * 2.0 - 1.0, 1.0);
|
|
float4 rd = mul(_invP, float4(pos, 1));
|
|
rd.xyz /= rd.w;
|
|
|
|
float4 temporalUV = mul(_FrameMatrix, float4(rd.xyz * d01, 1));
|
|
temporalUV /= temporalUV.w;
|
|
|
|
//float2 temporalUV = i.uv - tex2D(_MotionVectorTexture, i.uv).xy;
|
|
float3 lastCol = tex2D(_TemporalAATexture, temporalUV*0.5+0.5).xyz;
|
|
if (abs(temporalUV.x) > 1 || abs(temporalUV.y) > 1)
|
|
lastCol = curCol;
|
|
//
|
|
|
|
// Neighbourhood clipping
|
|
//float3 ya = rgb_to_ycbcr(curCol);
|
|
float3 ya = curCol;
|
|
float3 minCol = ya;
|
|
float3 maxCol = ya;
|
|
|
|
for (int x = -1; x <= 1; ++x) {
|
|
for (int y = -1; y <= 1; ++y) {
|
|
float2 duv = float2(x, y) / _ScreenParams.xy;
|
|
//float3 s = rgb_to_ycbcr(tex2D(_MainTex, i.uv + duv).xyz);
|
|
float3 s = tex2D(_MainTex, i.texcoord + duv).xyz;
|
|
|
|
minCol = min(minCol, s);
|
|
maxCol = max(maxCol, s);
|
|
}
|
|
}
|
|
//lastCol = mul(YCoCgToRGBMatrix, clamp(mul(RGBToYCoCgMatrix, lastCol), minCol, maxCol));
|
|
lastCol = clamp(lastCol, minCol, maxCol);
|
|
//lastCol = clipLuminance(lastCol, minCol, maxCol);
|
|
//
|
|
|
|
float temporalMultiplier = exp(-_MovementBlending * length(pos.xy - temporalUV));
|
|
float3 finalCol = lerp(curCol, lastCol, _TemporalFade * temporalMultiplier);
|
|
//finalCol = length(minCol - maxCol).xxx;
|
|
|
|
//return float4(i.texcoord.x,0.5,0, 1);
|
|
|
|
//float2 uv = i.texcoord.xy;
|
|
//half4 color = SAMPLE_TEXTURE2D_X_LOD(_BlitTexture, sampler_LinearRepeat, uv, _BlitMipLevel)*2;
|
|
//color = tex2D(_MainTex, uv)*2;
|
|
//return color;
|
|
return float4(finalCol, 1);
|
|
}
|
|
ENDHLSL//ENDCG
|
|
}
|
|
//// END GRAPH
|
|
|
|
}
|
|
}
|