Initial
This commit is contained in:
commit
36a53f343e
58 changed files with 300431 additions and 0 deletions
1333
UnityProject/Assets/!ext/PostProcessing/Resources/Shaders/ACES.cginc
Normal file
1333
UnityProject/Assets/!ext/PostProcessing/Resources/Shaders/ACES.cginc
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b8d56fc3449f426408c23c723b58d7b5
|
||||
timeCreated: 1460363486
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,500 @@
|
|||
// Upgrade NOTE: commented out 'float4x4 _WorldToCamera', a built-in variable
|
||||
// Upgrade NOTE: replaced '_WorldToCamera' with 'unity_WorldToCamera'
|
||||
|
||||
#ifndef __AMBIENT_OCCLUSION__
|
||||
#define __AMBIENT_OCCLUSION__
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "Common.cginc"
|
||||
|
||||
// --------
|
||||
// Options for further customization
|
||||
// --------
|
||||
|
||||
// By default, a 5-tap Gaussian with the linear sampling technique is used
|
||||
// in the bilateral noise filter. It can be replaced with a 7-tap Gaussian
|
||||
// with adaptive sampling by enabling the macro below. Although the
|
||||
// differences are not noticeable in most cases, it may provide preferable
|
||||
// results with some special usage (e.g. NPR without textureing).
|
||||
// #define BLUR_HIGH_QUALITY
|
||||
|
||||
// By default, a fixed sampling pattern is used in the AO estimator. Although
|
||||
// this gives preferable results in most cases, a completely random sampling
|
||||
// pattern could give aesthetically better results. Disable the macro below
|
||||
// to use such a random pattern instead of the fixed one.
|
||||
#define FIX_SAMPLING_PATTERN
|
||||
|
||||
// The SampleNormal function normalizes samples from G-buffer because
|
||||
// they're possibly unnormalized. We can eliminate this if it can be said
|
||||
// that there is no wrong shader that outputs unnormalized normals.
|
||||
// #define VALIDATE_NORMALS
|
||||
|
||||
// The constant below determines the contrast of occlusion. This allows
|
||||
// users to control over/under occlusion. At the moment, this is not exposed
|
||||
// to the editor because it<69>s rarely useful.
|
||||
static const float kContrast = 0.6;
|
||||
|
||||
// The constant below controls the geometry-awareness of the bilateral
|
||||
// filter. The higher value, the more sensitive it is.
|
||||
static const float kGeometryCoeff = 0.8;
|
||||
|
||||
// The constants below are used in the AO estimator. Beta is mainly used
|
||||
// for suppressing self-shadowing noise, and Epsilon is used to prevent
|
||||
// calculation underflow. See the paper (Morgan 2011 http://goo.gl/2iz3P)
|
||||
// for further details of these constants.
|
||||
static const float kBeta = 0.002;
|
||||
|
||||
// --------
|
||||
|
||||
// System built-in variables
|
||||
sampler2D _CameraGBufferTexture2;
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
sampler2D _CameraDepthNormalsTexture;
|
||||
|
||||
float4 _CameraDepthTexture_ST;
|
||||
|
||||
// Sample count
|
||||
#if !defined(SHADER_API_GLES)
|
||||
int _SampleCount;
|
||||
#else
|
||||
// GLES2: In many cases, dynamic looping is not supported.
|
||||
static const int _SampleCount = 3;
|
||||
#endif
|
||||
|
||||
// Source texture properties
|
||||
sampler2D _OcclusionTexture;
|
||||
float4 _OcclusionTexture_TexelSize;
|
||||
|
||||
// Other parameters
|
||||
half _Intensity;
|
||||
float _Radius;
|
||||
float _Downsample;
|
||||
float3 _FogParams; // x: density, y: start, z: end
|
||||
|
||||
// Accessors for packed AO/normal buffer
|
||||
fixed4 PackAONormal(fixed ao, fixed3 n)
|
||||
{
|
||||
return fixed4(ao, n * 0.5 + 0.5);
|
||||
}
|
||||
|
||||
fixed GetPackedAO(fixed4 p)
|
||||
{
|
||||
return p.r;
|
||||
}
|
||||
|
||||
fixed3 GetPackedNormal(fixed4 p)
|
||||
{
|
||||
return p.gba * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
// Boundary check for depth sampler
|
||||
// (returns a very large value if it lies out of bounds)
|
||||
float CheckBounds(float2 uv, float d)
|
||||
{
|
||||
float ob = any(uv < 0) + any(uv > 1);
|
||||
#if defined(UNITY_REVERSED_Z)
|
||||
ob += (d <= 0.00001);
|
||||
#else
|
||||
ob += (d >= 0.99999);
|
||||
#endif
|
||||
return ob * 1e8;
|
||||
}
|
||||
|
||||
// Depth/normal sampling functions
|
||||
float SampleDepth(float2 uv)
|
||||
{
|
||||
#if defined(SOURCE_GBUFFER) || defined(SOURCE_DEPTH)
|
||||
float d = LinearizeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv));
|
||||
#else
|
||||
float4 cdn = tex2D(_CameraDepthNormalsTexture, uv);
|
||||
float d = DecodeFloatRG(cdn.zw);
|
||||
#endif
|
||||
return d * _ProjectionParams.z + CheckBounds(uv, d);
|
||||
}
|
||||
|
||||
float3 SampleNormal(float2 uv)
|
||||
{
|
||||
#if defined(SOURCE_GBUFFER)
|
||||
float3 norm = tex2D(_CameraGBufferTexture2, uv).xyz;
|
||||
norm = norm * 2 - any(norm); // gets (0,0,0) when norm == 0
|
||||
norm = mul((float3x3)unity_WorldToCamera, norm);
|
||||
#if defined(VALIDATE_NORMALS)
|
||||
norm = normalize(norm);
|
||||
#endif
|
||||
return norm;
|
||||
#else
|
||||
float4 cdn = tex2D(_CameraDepthNormalsTexture, uv);
|
||||
return DecodeViewNormalStereo(cdn) * float3(1.0, 1.0, -1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
float SampleDepthNormal(float2 uv, out float3 normal)
|
||||
{
|
||||
#if defined(SOURCE_GBUFFER) || defined(SOURCE_DEPTH)
|
||||
normal = SampleNormal(uv);
|
||||
return SampleDepth(uv);
|
||||
#else
|
||||
float4 cdn = tex2D(_CameraDepthNormalsTexture, uv);
|
||||
normal = DecodeViewNormalStereo(cdn) * float3(1.0, 1.0, -1.0);
|
||||
float d = DecodeFloatRG(cdn.zw);
|
||||
return d * _ProjectionParams.z + CheckBounds(uv, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Normal vector comparer (for geometry-aware weighting)
|
||||
half CompareNormal(half3 d1, half3 d2)
|
||||
{
|
||||
return smoothstep(kGeometryCoeff, 1.0, dot(d1, d2));
|
||||
}
|
||||
|
||||
// Common vertex shader
|
||||
struct VaryingsMultitex
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
half2 uv : TEXCOORD0; // Original UV
|
||||
half2 uv01 : TEXCOORD1; // Alternative UV (supports v-flip case)
|
||||
half2 uvSPR : TEXCOORD2; // Single pass stereo rendering UV
|
||||
};
|
||||
|
||||
VaryingsMultitex VertMultitex(AttributesDefault v)
|
||||
{
|
||||
half2 uvAlt = v.texcoord.xy;
|
||||
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
if (_MainTex_TexelSize.y < 0.0) uvAlt.y = 1.0 - uvAlt.y;
|
||||
#endif
|
||||
|
||||
VaryingsMultitex o;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.uv01 = uvAlt;
|
||||
o.uvSPR = UnityStereoTransformScreenSpaceTex(uvAlt);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
// Trigonometric function utility
|
||||
float2 CosSin(float theta)
|
||||
{
|
||||
float sn, cs;
|
||||
sincos(theta, sn, cs);
|
||||
return float2(cs, sn);
|
||||
}
|
||||
|
||||
// Pseudo random number generator with 2D coordinates
|
||||
float UVRandom(float u, float v)
|
||||
{
|
||||
float f = dot(float2(12.9898, 78.233), float2(u, v));
|
||||
return frac(43758.5453 * sin(f));
|
||||
}
|
||||
|
||||
// Check if the camera is perspective.
|
||||
// (returns 1.0 when orthographic)
|
||||
float CheckPerspective(float x)
|
||||
{
|
||||
return lerp(x, 1.0, unity_OrthoParams.w);
|
||||
}
|
||||
|
||||
// Reconstruct view-space position from UV and depth.
|
||||
// p11_22 = (unity_CameraProjection._11, unity_CameraProjection._22)
|
||||
// p13_31 = (unity_CameraProjection._13, unity_CameraProjection._23)
|
||||
float3 ReconstructViewPos(float2 uv, float depth, float2 p11_22, float2 p13_31)
|
||||
{
|
||||
return float3((uv * 2.0 - 1.0 - p13_31) / p11_22 * CheckPerspective(depth), depth);
|
||||
}
|
||||
|
||||
// Sample point picker
|
||||
float3 PickSamplePoint(float2 uv, float index)
|
||||
{
|
||||
// Uniformaly distributed points on a unit sphere http://goo.gl/X2F1Ho
|
||||
#if defined(FIX_SAMPLING_PATTERN)
|
||||
float gn = GradientNoise(uv * _Downsample);
|
||||
// FIXME: This was added to avoid a NVIDIA driver issue.
|
||||
// vvvvvvvvvvvv
|
||||
float u = frac(UVRandom(0.0, index + uv.x * 1e-10) + gn) * 2.0 - 1.0;
|
||||
float theta = (UVRandom(1.0, index + uv.x * 1e-10) + gn) * UNITY_PI_2;
|
||||
#else
|
||||
float u = UVRandom(uv.x + _Time.x, uv.y + index) * 2.0 - 1.0;
|
||||
float theta = UVRandom(-uv.x - _Time.x, uv.y + index) * UNITY_PI_2;
|
||||
#endif
|
||||
float3 v = float3(CosSin(theta) * sqrt(1.0 - u * u), u);
|
||||
// Make them distributed between [0, _Radius]
|
||||
float l = sqrt((index + 1.0) / _SampleCount) * _Radius;
|
||||
return v * l;
|
||||
}
|
||||
|
||||
// Fog handling in forward
|
||||
half ComputeFog(float z)
|
||||
{
|
||||
half fog = 0.0;
|
||||
#if FOG_LINEAR
|
||||
fog = (_FogParams.z - z) / (_FogParams.z - _FogParams.y);
|
||||
#elif FOG_EXP
|
||||
fog = exp2(-_FogParams.x * z);
|
||||
#else // FOG_EXP2
|
||||
fog = _FogParams.x * z;
|
||||
fog = exp2(-fog * fog);
|
||||
#endif
|
||||
return saturate(fog);
|
||||
}
|
||||
|
||||
float ComputeDistance(float depth)
|
||||
{
|
||||
float dist = depth * _ProjectionParams.z;
|
||||
dist -= _ProjectionParams.y;
|
||||
return dist;
|
||||
}
|
||||
|
||||
//
|
||||
// Distance-based AO estimator based on Morgan 2011 http://goo.gl/2iz3P
|
||||
//
|
||||
half4 FragAO(VaryingsMultitex i) : SV_Target
|
||||
{
|
||||
float2 uv = i.uv;
|
||||
|
||||
// Parameters used in coordinate conversion
|
||||
float3x3 proj = (float3x3)unity_CameraProjection;
|
||||
float2 p11_22 = float2(unity_CameraProjection._11, unity_CameraProjection._22);
|
||||
float2 p13_31 = float2(unity_CameraProjection._13, unity_CameraProjection._23);
|
||||
|
||||
// View space normal and depth
|
||||
float3 norm_o;
|
||||
float depth_o = SampleDepthNormal(UnityStereoScreenSpaceUVAdjust(uv, _CameraDepthTexture_ST), norm_o);
|
||||
|
||||
#if defined(SOURCE_DEPTHNORMALS)
|
||||
// Offset the depth value to avoid precision error.
|
||||
// (depth in the DepthNormals mode has only 16-bit precision)
|
||||
depth_o -= _ProjectionParams.z / 65536;
|
||||
#endif
|
||||
|
||||
// Reconstruct the view-space position.
|
||||
float3 vpos_o = ReconstructViewPos(i.uv01, depth_o, p11_22, p13_31);
|
||||
|
||||
float ao = 0.0;
|
||||
|
||||
for (int s = 0; s < _SampleCount; s++)
|
||||
{
|
||||
// Sample point
|
||||
#if defined(SHADER_API_D3D11)
|
||||
// This 'floor(1.0001 * s)' operation is needed to avoid a NVidia
|
||||
// shader issue. This issue is only observed on DX11.
|
||||
float3 v_s1 = PickSamplePoint(uv, floor(1.0001 * s));
|
||||
#else
|
||||
float3 v_s1 = PickSamplePoint(uv, s);
|
||||
#endif
|
||||
v_s1 = faceforward(v_s1, -norm_o, v_s1);
|
||||
float3 vpos_s1 = vpos_o + v_s1;
|
||||
|
||||
// Reproject the sample point
|
||||
float3 spos_s1 = mul(proj, vpos_s1);
|
||||
float2 uv_s1_01 = (spos_s1.xy / CheckPerspective(vpos_s1.z) + 1.0) * 0.5;
|
||||
|
||||
// Depth at the sample point
|
||||
float depth_s1 = SampleDepth(UnityStereoScreenSpaceUVAdjust(uv_s1_01, _CameraDepthTexture_ST));
|
||||
|
||||
// Relative position of the sample point
|
||||
float3 vpos_s2 = ReconstructViewPos(uv_s1_01, depth_s1, p11_22, p13_31);
|
||||
float3 v_s2 = vpos_s2 - vpos_o;
|
||||
|
||||
// Estimate the obscurance value
|
||||
float a1 = max(dot(v_s2, norm_o) - kBeta * depth_o, 0.0);
|
||||
float a2 = dot(v_s2, v_s2) + EPSILON;
|
||||
ao += a1 / a2;
|
||||
}
|
||||
|
||||
ao *= _Radius; // intensity normalization
|
||||
|
||||
// Apply other parameters.
|
||||
ao = pow(ao * _Intensity / _SampleCount, kContrast);
|
||||
|
||||
// Apply fog when enabled (forward-only)
|
||||
#if !FOG_OFF
|
||||
float d = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv));
|
||||
d = ComputeDistance(d);
|
||||
ao *= ComputeFog(d);
|
||||
#endif
|
||||
|
||||
return PackAONormal(ao, norm_o);
|
||||
}
|
||||
|
||||
// Geometry-aware separable bilateral filter
|
||||
half4 FragBlur(VaryingsMultitex i) : SV_Target
|
||||
{
|
||||
#if defined(BLUR_HORIZONTAL)
|
||||
// Horizontal pass: Always use 2 texels interval to match to
|
||||
// the dither pattern.
|
||||
float2 delta = float2(_MainTex_TexelSize.x * 2.0, 0.0);
|
||||
#else
|
||||
// Vertical pass: Apply _Downsample to match to the dither
|
||||
// pattern in the original occlusion buffer.
|
||||
float2 delta = float2(0.0, _MainTex_TexelSize.y / _Downsample * 2.0);
|
||||
#endif
|
||||
|
||||
#if defined(BLUR_HIGH_QUALITY)
|
||||
|
||||
// High quality 7-tap Gaussian with adaptive sampling
|
||||
|
||||
fixed4 p0 = tex2D(_MainTex, i.uvSPR);
|
||||
fixed4 p1a = tex2D(_MainTex, i.uvSPR - delta);
|
||||
fixed4 p1b = tex2D(_MainTex, i.uvSPR + delta);
|
||||
fixed4 p2a = tex2D(_MainTex, i.uvSPR - delta * 2.0);
|
||||
fixed4 p2b = tex2D(_MainTex, i.uvSPR + delta * 2.0);
|
||||
fixed4 p3a = tex2D(_MainTex, i.uvSPR - delta * 3.2307692308);
|
||||
fixed4 p3b = tex2D(_MainTex, i.uvSPR + delta * 3.2307692308);
|
||||
|
||||
#if defined(BLUR_SAMPLE_CENTER_NORMAL)
|
||||
fixed3 n0 = SampleNormal(i.uvSPR);
|
||||
#else
|
||||
fixed3 n0 = GetPackedNormal(p0);
|
||||
#endif
|
||||
|
||||
half w0 = 0.37004405286;
|
||||
half w1a = CompareNormal(n0, GetPackedNormal(p1a)) * 0.31718061674;
|
||||
half w1b = CompareNormal(n0, GetPackedNormal(p1b)) * 0.31718061674;
|
||||
half w2a = CompareNormal(n0, GetPackedNormal(p2a)) * 0.19823788546;
|
||||
half w2b = CompareNormal(n0, GetPackedNormal(p2b)) * 0.19823788546;
|
||||
half w3a = CompareNormal(n0, GetPackedNormal(p3a)) * 0.11453744493;
|
||||
half w3b = CompareNormal(n0, GetPackedNormal(p3b)) * 0.11453744493;
|
||||
|
||||
half s;
|
||||
s = GetPackedAO(p0) * w0;
|
||||
s += GetPackedAO(p1a) * w1a;
|
||||
s += GetPackedAO(p1b) * w1b;
|
||||
s += GetPackedAO(p2a) * w2a;
|
||||
s += GetPackedAO(p2b) * w2b;
|
||||
s += GetPackedAO(p3a) * w3a;
|
||||
s += GetPackedAO(p3b) * w3b;
|
||||
|
||||
s /= w0 + w1a + w1b + w2a + w2b + w3a + w3b;
|
||||
|
||||
#else
|
||||
|
||||
// Fater 5-tap Gaussian with linear sampling
|
||||
fixed4 p0 = tex2D(_MainTex, i.uvSPR);
|
||||
fixed4 p1a = tex2D(_MainTex, i.uvSPR - delta * 1.3846153846);
|
||||
fixed4 p1b = tex2D(_MainTex, i.uvSPR + delta * 1.3846153846);
|
||||
fixed4 p2a = tex2D(_MainTex, i.uvSPR - delta * 3.2307692308);
|
||||
fixed4 p2b = tex2D(_MainTex, i.uvSPR + delta * 3.2307692308);
|
||||
|
||||
#if defined(BLUR_SAMPLE_CENTER_NORMAL)
|
||||
fixed3 n0 = SampleNormal(i.uvSPR);
|
||||
#else
|
||||
fixed3 n0 = GetPackedNormal(p0);
|
||||
#endif
|
||||
|
||||
half w0 = 0.2270270270;
|
||||
half w1a = CompareNormal(n0, GetPackedNormal(p1a)) * 0.3162162162;
|
||||
half w1b = CompareNormal(n0, GetPackedNormal(p1b)) * 0.3162162162;
|
||||
half w2a = CompareNormal(n0, GetPackedNormal(p2a)) * 0.0702702703;
|
||||
half w2b = CompareNormal(n0, GetPackedNormal(p2b)) * 0.0702702703;
|
||||
|
||||
half s;
|
||||
s = GetPackedAO(p0) * w0;
|
||||
s += GetPackedAO(p1a) * w1a;
|
||||
s += GetPackedAO(p1b) * w1b;
|
||||
s += GetPackedAO(p2a) * w2a;
|
||||
s += GetPackedAO(p2b) * w2b;
|
||||
|
||||
s /= w0 + w1a + w1b + w2a + w2b;
|
||||
|
||||
#endif
|
||||
|
||||
return PackAONormal(s, n0);
|
||||
}
|
||||
|
||||
// Gamma encoding (only needed in gamma lighting mode)
|
||||
half EncodeAO(half x)
|
||||
{
|
||||
half x_g = 1.0 - max(1.055 * pow(1.0 - x, 0.416666667) - 0.055, 0.0);
|
||||
// ColorSpaceLuminance.w == 0 (gamma) or 1 (linear)
|
||||
return lerp(x_g, x, unity_ColorSpaceLuminance.w);
|
||||
}
|
||||
|
||||
// Geometry-aware bilateral filter (single pass/small kernel)
|
||||
half BlurSmall(sampler2D tex, float2 uv, float2 delta)
|
||||
{
|
||||
fixed4 p0 = tex2D(tex, uv);
|
||||
fixed4 p1 = tex2D(tex, uv + float2(-delta.x, -delta.y));
|
||||
fixed4 p2 = tex2D(tex, uv + float2(+delta.x, -delta.y));
|
||||
fixed4 p3 = tex2D(tex, uv + float2(-delta.x, +delta.y));
|
||||
fixed4 p4 = tex2D(tex, uv + float2(+delta.x, +delta.y));
|
||||
|
||||
fixed3 n0 = GetPackedNormal(p0);
|
||||
|
||||
half w0 = 1.0;
|
||||
half w1 = CompareNormal(n0, GetPackedNormal(p1));
|
||||
half w2 = CompareNormal(n0, GetPackedNormal(p2));
|
||||
half w3 = CompareNormal(n0, GetPackedNormal(p3));
|
||||
half w4 = CompareNormal(n0, GetPackedNormal(p4));
|
||||
|
||||
half s;
|
||||
s = GetPackedAO(p0) * w0;
|
||||
s += GetPackedAO(p1) * w1;
|
||||
s += GetPackedAO(p2) * w2;
|
||||
s += GetPackedAO(p3) * w3;
|
||||
s += GetPackedAO(p4) * w4;
|
||||
|
||||
return s / (w0 + w1 + w2 + w3 + w4);
|
||||
}
|
||||
|
||||
// Final composition shader
|
||||
half4 FragComposition(VaryingsMultitex i) : SV_Target
|
||||
{
|
||||
float2 delta = _MainTex_TexelSize.xy / _Downsample;
|
||||
half ao = BlurSmall(_OcclusionTexture, i.uvSPR, delta);
|
||||
half4 color = tex2D(_MainTex, i.uvSPR);
|
||||
|
||||
#if !defined(DEBUG_COMPOSITION)
|
||||
color.rgb *= 1.0 - EncodeAO(ao);
|
||||
#else
|
||||
color.rgb = 1.0 - EncodeAO(ao);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Final composition shader (ambient-only mode)
|
||||
VaryingsDefault VertCompositionGBuffer(AttributesDefault v)
|
||||
{
|
||||
VaryingsDefault o;
|
||||
o.pos = v.vertex;
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
o.uv = v.texcoord.xy * float2(1.0, -1.0) + float2(0.0, 1.0);
|
||||
#else
|
||||
o.uv = v.texcoord.xy;
|
||||
#endif
|
||||
o.uvSPR = UnityStereoTransformScreenSpaceTex(o.uv);
|
||||
return o;
|
||||
}
|
||||
|
||||
#if !SHADER_API_GLES // excluding the MRT pass under GLES2
|
||||
|
||||
struct CompositionOutput
|
||||
{
|
||||
half4 gbuffer0 : SV_Target0;
|
||||
half4 gbuffer3 : SV_Target1;
|
||||
};
|
||||
|
||||
CompositionOutput FragCompositionGBuffer(VaryingsDefault i)
|
||||
{
|
||||
// Workaround: _OcclusionTexture_Texelsize hasn't been set properly
|
||||
// for some reasons. Use _ScreenParams instead.
|
||||
float2 delta = (_ScreenParams.zw - 1.0) / _Downsample;
|
||||
half ao = BlurSmall(_OcclusionTexture, i.uvSPR, delta);
|
||||
|
||||
CompositionOutput o;
|
||||
o.gbuffer0 = half4(0.0, 0.0, 0.0, ao);
|
||||
o.gbuffer3 = half4((half3)EncodeAO(ao), 0.0);
|
||||
return o;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
fixed4 FragCompositionGBuffer(VaryingsDefault i) : SV_Target0
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // __AMBIENT_OCCLUSION__
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 447591ee3d9d4204899be5fe25968ea0
|
||||
timeCreated: 1473323470
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
Shader "Hidden/Post FX/Ambient Occlusion"
|
||||
{
|
||||
CGINCLUDE
|
||||
|
||||
#pragma target 3.0
|
||||
|
||||
ENDCG
|
||||
|
||||
SubShader
|
||||
{
|
||||
ZTest Always Cull Off ZWrite Off
|
||||
|
||||
// 0: Occlusion estimation with CameraDepthTexture
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragAO
|
||||
#pragma multi_compile FOG_OFF FOG_LINEAR FOG_EXP FOG_EXP2
|
||||
#define SOURCE_DEPTH
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// 1: Occlusion estimation with CameraDepthNormalsTexture
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragAO
|
||||
#pragma multi_compile FOG_OFF FOG_LINEAR FOG_EXP FOG_EXP2
|
||||
#define SOURCE_DEPTHNORMALS
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// 2: Occlusion estimation with G-Buffer
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragAO
|
||||
#pragma multi_compile FOG_OFF FOG_LINEAR FOG_EXP FOG_EXP2
|
||||
#define SOURCE_GBUFFER
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// 3: Separable blur (horizontal pass) with CameraDepthNormalsTexture
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragBlur
|
||||
#define SOURCE_DEPTHNORMALS
|
||||
#define BLUR_HORIZONTAL
|
||||
#define BLUR_SAMPLE_CENTER_NORMAL
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// 4: Separable blur (horizontal pass) with G-Buffer
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragBlur
|
||||
#define SOURCE_GBUFFER
|
||||
#define BLUR_HORIZONTAL
|
||||
#define BLUR_SAMPLE_CENTER_NORMAL
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// 5: Separable blur (vertical pass)
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragBlur
|
||||
#define BLUR_VERTICAL
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// 6: Final composition
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragComposition
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// 7: Final composition (ambient only mode)
|
||||
Pass
|
||||
{
|
||||
Blend Zero OneMinusSrcColor, Zero OneMinusSrcAlpha
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex VertCompositionGBuffer
|
||||
#pragma fragment FragCompositionGBuffer
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// 8: Debug visualization
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragComposition
|
||||
#define DEBUG_COMPOSITION
|
||||
#include "AmbientOcclusion.cginc"
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e881ae5627d1cc84395303acfbca6fb2
|
||||
timeCreated: 1462280790
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
Shader "Hidden/Post FX/Blit"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex("Main Texture", 2D) = "white" {}
|
||||
}
|
||||
|
||||
CGINCLUDE
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "Common.cginc"
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 vertex : SV_POSITION;
|
||||
};
|
||||
|
||||
Varyings VertBlit(AttributesDefault v)
|
||||
{
|
||||
Varyings o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST);
|
||||
return o;
|
||||
}
|
||||
|
||||
half4 FragBlit(Varyings i) : SV_Target
|
||||
{
|
||||
half4 col = tex2D(_MainTex, i.uv);
|
||||
return col;
|
||||
}
|
||||
|
||||
ENDCG
|
||||
|
||||
SubShader
|
||||
{
|
||||
Cull Off ZWrite Off ZTest Always
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
|
||||
#pragma vertex VertBlit
|
||||
#pragma fragment FragBlit
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7d89469544dfa214eabdbf37fca76f40
|
||||
timeCreated: 1474297975
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#ifndef __BLOOM__
|
||||
#define __BLOOM__
|
||||
|
||||
#include "Common.cginc"
|
||||
|
||||
// Brightness function
|
||||
half Brightness(half3 c)
|
||||
{
|
||||
return Max3(c);
|
||||
}
|
||||
|
||||
// 3-tap median filter
|
||||
half3 Median(half3 a, half3 b, half3 c)
|
||||
{
|
||||
return a + b + c - min(min(a, b), c) - max(max(a, b), c);
|
||||
}
|
||||
|
||||
// Downsample with a 4x4 box filter
|
||||
half3 DownsampleFilter(sampler2D tex, float2 uv, float2 texelSize)
|
||||
{
|
||||
float4 d = texelSize.xyxy * float4(-1.0, -1.0, 1.0, 1.0);
|
||||
|
||||
half3 s;
|
||||
s = DecodeHDR(tex2D(tex, uv + d.xy));
|
||||
s += DecodeHDR(tex2D(tex, uv + d.zy));
|
||||
s += DecodeHDR(tex2D(tex, uv + d.xw));
|
||||
s += DecodeHDR(tex2D(tex, uv + d.zw));
|
||||
|
||||
return s * (1.0 / 4.0);
|
||||
}
|
||||
|
||||
// Downsample with a 4x4 box filter + anti-flicker filter
|
||||
half3 DownsampleAntiFlickerFilter(sampler2D tex, float2 uv, float2 texelSize)
|
||||
{
|
||||
float4 d = texelSize.xyxy * float4(-1.0, -1.0, 1.0, 1.0);
|
||||
|
||||
half3 s1 = DecodeHDR(tex2D(tex, uv + d.xy));
|
||||
half3 s2 = DecodeHDR(tex2D(tex, uv + d.zy));
|
||||
half3 s3 = DecodeHDR(tex2D(tex, uv + d.xw));
|
||||
half3 s4 = DecodeHDR(tex2D(tex, uv + d.zw));
|
||||
|
||||
// Karis's luma weighted average (using brightness instead of luma)
|
||||
half s1w = 1.0 / (Brightness(s1) + 1.0);
|
||||
half s2w = 1.0 / (Brightness(s2) + 1.0);
|
||||
half s3w = 1.0 / (Brightness(s3) + 1.0);
|
||||
half s4w = 1.0 / (Brightness(s4) + 1.0);
|
||||
half one_div_wsum = 1.0 / (s1w + s2w + s3w + s4w);
|
||||
|
||||
return (s1 * s1w + s2 * s2w + s3 * s3w + s4 * s4w) * one_div_wsum;
|
||||
}
|
||||
|
||||
half3 UpsampleFilter(sampler2D tex, float2 uv, float2 texelSize, float sampleScale)
|
||||
{
|
||||
#if MOBILE_OR_CONSOLE
|
||||
// 4-tap bilinear upsampler
|
||||
float4 d = texelSize.xyxy * float4(-1.0, -1.0, 1.0, 1.0) * (sampleScale * 0.5);
|
||||
|
||||
half3 s;
|
||||
s = DecodeHDR(tex2D(tex, uv + d.xy));
|
||||
s += DecodeHDR(tex2D(tex, uv + d.zy));
|
||||
s += DecodeHDR(tex2D(tex, uv + d.xw));
|
||||
s += DecodeHDR(tex2D(tex, uv + d.zw));
|
||||
|
||||
return s * (1.0 / 4.0);
|
||||
#else
|
||||
// 9-tap bilinear upsampler (tent filter)
|
||||
float4 d = texelSize.xyxy * float4(1.0, 1.0, -1.0, 0.0) * sampleScale;
|
||||
|
||||
half3 s;
|
||||
s = DecodeHDR(tex2D(tex, uv - d.xy));
|
||||
s += DecodeHDR(tex2D(tex, uv - d.wy)) * 2.0;
|
||||
s += DecodeHDR(tex2D(tex, uv - d.zy));
|
||||
|
||||
s += DecodeHDR(tex2D(tex, uv + d.zw)) * 2.0;
|
||||
s += DecodeHDR(tex2D(tex, uv)) * 4.0;
|
||||
s += DecodeHDR(tex2D(tex, uv + d.xw)) * 2.0;
|
||||
|
||||
s += DecodeHDR(tex2D(tex, uv + d.zy));
|
||||
s += DecodeHDR(tex2D(tex, uv + d.wy)) * 2.0;
|
||||
s += DecodeHDR(tex2D(tex, uv + d.xy));
|
||||
|
||||
return s * (1.0 / 16.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // __BLOOM__
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7d1f4dd94c8e6e940b0730076ea7d6d9
|
||||
timeCreated: 1462980395
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
//
|
||||
// Kino/Bloom v2 - Bloom filter for Unity
|
||||
//
|
||||
// Copyright (C) 2015, 2016 Keijiro Takahashi
|
||||
//
|
||||
// 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/Post FX/Bloom"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("", 2D) = "" {}
|
||||
_BaseTex ("", 2D) = "" {}
|
||||
_AutoExposure ("", 2D) = "" {}
|
||||
}
|
||||
|
||||
CGINCLUDE
|
||||
|
||||
#pragma target 3.0
|
||||
#include "UnityCG.cginc"
|
||||
#include "Bloom.cginc"
|
||||
#include "Common.cginc"
|
||||
|
||||
sampler2D _BaseTex;
|
||||
float2 _BaseTex_TexelSize;
|
||||
|
||||
sampler2D _AutoExposure;
|
||||
|
||||
float _PrefilterOffs;
|
||||
float _Threshold;
|
||||
float3 _Curve;
|
||||
float _SampleScale;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Vertex shaders
|
||||
|
||||
struct VaryingsMultitex
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uvMain : TEXCOORD0;
|
||||
float2 uvBase : TEXCOORD1;
|
||||
};
|
||||
|
||||
VaryingsMultitex VertMultitex(AttributesDefault v)
|
||||
{
|
||||
VaryingsMultitex o;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uvMain = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy, _MainTex_ST);
|
||||
o.uvBase = o.uvMain;
|
||||
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
if (_BaseTex_TexelSize.y < 0.0)
|
||||
o.uvBase.y = 1.0 - o.uvBase.y;
|
||||
#endif
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Fragment shaders
|
||||
|
||||
half4 FetchAutoExposed(sampler2D tex, float2 uv)
|
||||
{
|
||||
float autoExposure = 1.0;
|
||||
uv = UnityStereoScreenSpaceUVAdjust(uv, _MainTex_ST);
|
||||
autoExposure = tex2D(_AutoExposure, uv).r;
|
||||
return tex2D(tex, uv) * autoExposure;
|
||||
}
|
||||
|
||||
half4 FragPrefilter(VaryingsDefault i) : SV_Target
|
||||
{
|
||||
float2 uv = i.uv + _MainTex_TexelSize.xy * _PrefilterOffs;
|
||||
|
||||
#if ANTI_FLICKER
|
||||
float3 d = _MainTex_TexelSize.xyx * float3(1.0, 1.0, 0.0);
|
||||
half4 s0 = SafeHDR(FetchAutoExposed(_MainTex, uv));
|
||||
half3 s1 = SafeHDR(FetchAutoExposed(_MainTex, uv - d.xz).rgb);
|
||||
half3 s2 = SafeHDR(FetchAutoExposed(_MainTex, uv + d.xz).rgb);
|
||||
half3 s3 = SafeHDR(FetchAutoExposed(_MainTex, uv - d.zy).rgb);
|
||||
half3 s4 = SafeHDR(FetchAutoExposed(_MainTex, uv + d.zy).rgb);
|
||||
half3 m = Median(Median(s0.rgb, s1, s2), s3, s4);
|
||||
#else
|
||||
half4 s0 = SafeHDR(FetchAutoExposed(_MainTex, uv));
|
||||
half3 m = s0.rgb;
|
||||
#endif
|
||||
|
||||
#if UNITY_COLORSPACE_GAMMA
|
||||
m = GammaToLinearSpace(m);
|
||||
#endif
|
||||
|
||||
// Pixel brightness
|
||||
half br = Brightness(m);
|
||||
|
||||
// Under-threshold part: quadratic curve
|
||||
half rq = clamp(br - _Curve.x, 0.0, _Curve.y);
|
||||
rq = _Curve.z * rq * rq;
|
||||
|
||||
// Combine and apply the brightness response curve.
|
||||
m *= max(rq, br - _Threshold) / max(br, 1e-5);
|
||||
|
||||
return EncodeHDR(m);
|
||||
}
|
||||
|
||||
half4 FragDownsample1(VaryingsDefault i) : SV_Target
|
||||
{
|
||||
#if ANTI_FLICKER
|
||||
return EncodeHDR(DownsampleAntiFlickerFilter(_MainTex, i.uvSPR, _MainTex_TexelSize.xy));
|
||||
#else
|
||||
return EncodeHDR(DownsampleFilter(_MainTex, i.uvSPR, _MainTex_TexelSize.xy));
|
||||
#endif
|
||||
}
|
||||
|
||||
half4 FragDownsample2(VaryingsDefault i) : SV_Target
|
||||
{
|
||||
return EncodeHDR(DownsampleFilter(_MainTex, i.uvSPR, _MainTex_TexelSize.xy));
|
||||
}
|
||||
|
||||
half4 FragUpsample(VaryingsMultitex i) : SV_Target
|
||||
{
|
||||
half3 base = DecodeHDR(tex2D(_BaseTex, i.uvBase));
|
||||
half3 blur = UpsampleFilter(_MainTex, i.uvMain, _MainTex_TexelSize.xy, _SampleScale);
|
||||
return EncodeHDR(base + blur);
|
||||
}
|
||||
|
||||
ENDCG
|
||||
|
||||
SubShader
|
||||
{
|
||||
ZTest Always Cull Off ZWrite Off
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma multi_compile __ ANTI_FLICKER
|
||||
#pragma multi_compile __ UNITY_COLORSPACE_GAMMA
|
||||
#pragma vertex VertDefault
|
||||
#pragma fragment FragPrefilter
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma multi_compile __ ANTI_FLICKER
|
||||
#pragma vertex VertDefault
|
||||
#pragma fragment FragDownsample1
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertDefault
|
||||
#pragma fragment FragDownsample2
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex VertMultitex
|
||||
#pragma fragment FragUpsample
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4ceb73bc148699b469361531d6062548
|
||||
timeCreated: 1462953634
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
Shader "Hidden/Post FX/Builtin Debug Views"
|
||||
{
|
||||
CGINCLUDE
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "Common.cginc"
|
||||
|
||||
#pragma exclude_renderers d3d11_9x
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
sampler2D_float _CameraDepthNormalsTexture;
|
||||
sampler2D_float _CameraMotionVectorsTexture;
|
||||
|
||||
float4 _CameraDepthTexture_ST;
|
||||
float4 _CameraDepthNormalsTexture_ST;
|
||||
float4 _CameraMotionVectorsTexture_ST;
|
||||
|
||||
#if SOURCE_GBUFFER
|
||||
sampler2D _CameraGBufferTexture2;
|
||||
float4 _CameraGBufferTexture2_ST;
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Depth
|
||||
|
||||
float _DepthScale;
|
||||
|
||||
float4 FragDepth(VaryingsDefault i) : SV_Target
|
||||
{
|
||||
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.uv, _CameraDepthTexture_ST));
|
||||
depth = Linear01Depth(depth) * _DepthScale;
|
||||
float3 d = depth.xxx;
|
||||
|
||||
#if !UNITY_COLORSPACE_GAMMA
|
||||
d = GammaToLinearSpace(d);
|
||||
#endif
|
||||
|
||||
return float4(d, 1.0);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Normals
|
||||
|
||||
float3 SampleNormal(float2 uv)
|
||||
{
|
||||
#if SOURCE_GBUFFER
|
||||
float3 norm = tex2D(_CameraGBufferTexture2, uv).xyz * 2.0 - 1.0;
|
||||
return mul((float3x3)unity_WorldToCamera, norm);
|
||||
#else
|
||||
float4 cdn = tex2D(_CameraDepthNormalsTexture, uv);
|
||||
return DecodeViewNormalStereo(cdn) * float3(1.0, 1.0, -1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
float4 FragNormals(VaryingsDefault i) : SV_Target
|
||||
{
|
||||
float3 n = SampleNormal(UnityStereoScreenSpaceUVAdjust(i.uv, _CameraDepthNormalsTexture_ST));
|
||||
|
||||
#if UNITY_COLORSPACE_GAMMA
|
||||
n = LinearToGammaSpace(n);
|
||||
#endif
|
||||
|
||||
return float4(n, 1.0);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Motion vectors
|
||||
|
||||
float _Opacity;
|
||||
float _Amplitude;
|
||||
float4 _Scale;
|
||||
|
||||
float4 FragMovecsOpacity(VaryingsDefault i) : SV_Target
|
||||
{
|
||||
float4 src = tex2D(_MainTex, i.uv);
|
||||
return float4(src.rgb * _Opacity, src.a);
|
||||
}
|
||||
|
||||
// Convert a motion vector into RGBA color.
|
||||
float4 VectorToColor(float2 mv)
|
||||
{
|
||||
float phi = atan2(mv.x, mv.y);
|
||||
float hue = (phi / UNITY_PI + 1.0) * 0.5;
|
||||
|
||||
float r = abs(hue * 6.0 - 3.0) - 1.0;
|
||||
float g = 2.0 - abs(hue * 6.0 - 2.0);
|
||||
float b = 2.0 - abs(hue * 6.0 - 4.0);
|
||||
float a = length(mv);
|
||||
|
||||
return saturate(float4(r, g, b, a));
|
||||
}
|
||||
|
||||
float4 FragMovecsImaging(VaryingsDefault i) : SV_Target
|
||||
{
|
||||
float4 src = tex2D(_MainTex, i.uv);
|
||||
|
||||
float2 mv = tex2D(_CameraMotionVectorsTexture, i.uv).rg * _Amplitude;
|
||||
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
mv.y *= -1.0;
|
||||
#endif
|
||||
|
||||
float4 mc = VectorToColor(mv);
|
||||
|
||||
float3 rgb = src.rgb;
|
||||
|
||||
#if !UNITY_COLORSPACE_GAMMA
|
||||
rgb = LinearToGammaSpace(rgb);
|
||||
#endif
|
||||
|
||||
rgb = lerp(rgb, mc.rgb, mc.a * _Opacity);
|
||||
|
||||
#if !UNITY_COLORSPACE_GAMMA
|
||||
rgb = GammaToLinearSpace(rgb);
|
||||
#endif
|
||||
|
||||
return float4(rgb, src.a);
|
||||
}
|
||||
|
||||
struct VaryingsArrows
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
float2 scoord : TEXCOORD;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
VaryingsArrows VertArrows(AttributesDefault v)
|
||||
{
|
||||
// Retrieve the motion vector.
|
||||
float4 uv = float4(v.texcoord.xy, 0.0, 0.0);
|
||||
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
uv.y = 1.0 - uv.y;
|
||||
#endif
|
||||
|
||||
float2 mv = tex2Dlod(_CameraMotionVectorsTexture, uv).rg * _Amplitude;
|
||||
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
mv.y *= -1.0;
|
||||
#endif
|
||||
|
||||
// Arrow color
|
||||
float4 color = VectorToColor(mv);
|
||||
|
||||
// Make a rotation matrix based on the motion vector.
|
||||
float2x2 rot = float2x2(mv.y, mv.x, -mv.x, mv.y);
|
||||
|
||||
// Rotate and scale the body of the arrow.
|
||||
float2 pos = mul(rot, v.vertex.zy) * _Scale.xy;
|
||||
|
||||
// Normalized variant of the motion vector and the rotation matrix.
|
||||
float2 mv_n = normalize(mv);
|
||||
float2x2 rot_n = float2x2(mv_n.y, mv_n.x, -mv_n.x, mv_n.y);
|
||||
|
||||
// Rotate and scale the head of the arrow.
|
||||
float2 head = float2(v.vertex.x, -abs(v.vertex.x)) * 0.3;
|
||||
head *= saturate(color.a);
|
||||
pos += mul(rot_n, head) * _Scale.xy;
|
||||
|
||||
// Offset the arrow position.
|
||||
pos += v.texcoord.xy * 2.0 - 1.0;
|
||||
|
||||
// Convert to the screen coordinates.
|
||||
float2 scoord = (pos + 1.0) * 0.5 * _ScreenParams.xy;
|
||||
|
||||
// Snap to a pixel-perfect position.
|
||||
scoord = round(scoord);
|
||||
|
||||
// Bring back to the normalized screen space.
|
||||
pos = (scoord + 0.5) * (_ScreenParams.zw - 1.0) * 2.0 - 1.0;
|
||||
|
||||
// Color tweaks
|
||||
color.rgb = GammaToLinearSpace(lerp(color.rgb, 1.0, 0.5));
|
||||
color.a *= _Opacity;
|
||||
|
||||
// Output
|
||||
VaryingsArrows o;
|
||||
o.vertex = float4(pos, 0.0, 1.0);
|
||||
o.scoord = scoord;
|
||||
o.color = saturate(color);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 FragMovecsArrows(VaryingsArrows i) : SV_Target
|
||||
{
|
||||
// Pseudo anti-aliasing.
|
||||
float aa = length(frac(i.scoord) - 0.5) / 0.707;
|
||||
aa *= (aa * (aa * 0.305306011 + 0.682171111) + 0.012522878); // gamma
|
||||
return float4(i.color.rgb, i.color.a * aa);
|
||||
}
|
||||
|
||||
ENDCG
|
||||
|
||||
SubShader
|
||||
{
|
||||
Cull Off ZWrite Off ZTest Always
|
||||
|
||||
// (0) - Depth
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
|
||||
#pragma vertex VertDefault
|
||||
#pragma fragment FragDepth
|
||||
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// (1) - Normals
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
|
||||
#pragma vertex VertDefault
|
||||
#pragma fragment FragNormals
|
||||
#pragma multi_compile __ SOURCE_GBUFFER
|
||||
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// (2) - Motion vectors - Opacity
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
|
||||
#pragma vertex VertDefault
|
||||
#pragma fragment FragMovecsOpacity
|
||||
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// (3) - Motion vectors - Imaging
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
|
||||
#pragma vertex VertDefault
|
||||
#pragma fragment FragMovecsImaging
|
||||
#pragma multi_compile __ UNITY_COLORSPACE_GAMMA
|
||||
|
||||
ENDCG
|
||||
}
|
||||
|
||||
// (4) - Motion vectors - Arrows
|
||||
Pass
|
||||
{
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
CGPROGRAM
|
||||
|
||||
#pragma vertex VertArrows
|
||||
#pragma fragment FragMovecsArrows
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 72127ba7dd8c6b04bb3f29c7ee669813
|
||||
timeCreated: 1468224802
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
#ifndef __COLOR_GRADING__
|
||||
#define __COLOR_GRADING__
|
||||
|
||||
#include "ACES.cginc"
|
||||
#include "Common.cginc"
|
||||
|
||||
// Set to 1 to use more precise but more expensive log/linear conversions. I haven't found a proper
|
||||
// use case for the high precision version yet so I'm leaving this to 0.
|
||||
#define COLOR_GRADING_PRECISE_LOG 0
|
||||
|
||||
//
|
||||
// Alexa LogC converters (El 1000)
|
||||
// See http://www.vocas.nl/webfm_send/964
|
||||
// It's a good fit to store HDR values in log as the range is pretty wide (1 maps to ~58.85666) and
|
||||
// is quick enough to compute.
|
||||
//
|
||||
struct ParamsLogC
|
||||
{
|
||||
half cut;
|
||||
half a, b, c, d, e, f;
|
||||
};
|
||||
|
||||
static const ParamsLogC LogC =
|
||||
{
|
||||
0.011361, // cut
|
||||
5.555556, // a
|
||||
0.047996, // b
|
||||
0.244161, // c
|
||||
0.386036, // d
|
||||
5.301883, // e
|
||||
0.092819 // f
|
||||
};
|
||||
|
||||
half LinearToLogC_Precise(half x)
|
||||
{
|
||||
half o;
|
||||
if (x > LogC.cut)
|
||||
o = LogC.c * log10(LogC.a * x + LogC.b) + LogC.d;
|
||||
else
|
||||
o = LogC.e * x + LogC.f;
|
||||
return o;
|
||||
}
|
||||
|
||||
half3 LinearToLogC(half3 x)
|
||||
{
|
||||
#if COLOR_GRADING_PRECISE_LOG
|
||||
return half3(
|
||||
LinearToLogC_Precise(x.x),
|
||||
LinearToLogC_Precise(x.y),
|
||||
LinearToLogC_Precise(x.z)
|
||||
);
|
||||
#else
|
||||
return LogC.c * log10(LogC.a * x + LogC.b) + LogC.d;
|
||||
#endif
|
||||
}
|
||||
|
||||
half LogCToLinear_Precise(half x)
|
||||
{
|
||||
half o;
|
||||
if (x > LogC.e * LogC.cut + LogC.f)
|
||||
o = (pow(10.0, (x - LogC.d) / LogC.c) - LogC.b) / LogC.a;
|
||||
else
|
||||
o = (x - LogC.f) / LogC.e;
|
||||
return o;
|
||||
}
|
||||
|
||||
half3 LogCToLinear(half3 x)
|
||||
{
|
||||
#if COLOR_GRADING_PRECISE_LOG
|
||||
return half3(
|
||||
LogCToLinear_Precise(x.x),
|
||||
LogCToLinear_Precise(x.y),
|
||||
LogCToLinear_Precise(x.z)
|
||||
);
|
||||
#else
|
||||
return (pow(10.0, (x - LogC.d) / LogC.c) - LogC.b) / LogC.a;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// White balance
|
||||
// Recommended workspace: ACEScg (linear)
|
||||
//
|
||||
static const half3x3 LIN_2_LMS_MAT = {
|
||||
3.90405e-1, 5.49941e-1, 8.92632e-3,
|
||||
7.08416e-2, 9.63172e-1, 1.35775e-3,
|
||||
2.31082e-2, 1.28021e-1, 9.36245e-1
|
||||
};
|
||||
|
||||
static const half3x3 LMS_2_LIN_MAT = {
|
||||
2.85847e+0, -1.62879e+0, -2.48910e-2,
|
||||
-2.10182e-1, 1.15820e+0, 3.24281e-4,
|
||||
-4.18120e-2, -1.18169e-1, 1.06867e+0
|
||||
};
|
||||
|
||||
half3 WhiteBalance(half3 c, half3 balance)
|
||||
{
|
||||
half3 lms = mul(LIN_2_LMS_MAT, c);
|
||||
lms *= balance;
|
||||
return mul(LMS_2_LIN_MAT, lms);
|
||||
}
|
||||
|
||||
//
|
||||
// Luminance (Rec.709 primaries according to ACES specs)
|
||||
//
|
||||
half AcesLuminance(half3 c)
|
||||
{
|
||||
return dot(c, half3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
//
|
||||
// Offset, Power, Slope (ASC-CDL)
|
||||
// Works in Log & Linear. Results will be different but still correct.
|
||||
//
|
||||
half3 OffsetPowerSlope(half3 c, half3 offset, half3 power, half3 slope)
|
||||
{
|
||||
half3 so = c * slope + offset;
|
||||
so = so > (0.0).xxx ? pow(so, power) : so;
|
||||
return so;
|
||||
}
|
||||
|
||||
//
|
||||
// Lift, Gamma (pre-inverted), Gain
|
||||
// Recommended workspace: ACEScg (linear)
|
||||
//
|
||||
half3 LiftGammaGain(half3 c, half3 lift, half3 invgamma, half3 gain)
|
||||
{
|
||||
//return gain * (lift * (1.0 - c) + pow(max(c, kEpsilon), invgamma));
|
||||
//return pow(gain * (c + lift * (1.0 - c)), invgamma);
|
||||
|
||||
half3 power = invgamma;
|
||||
half3 offset = lift * gain;
|
||||
half3 slope = ((1.0).xxx - lift) * gain;
|
||||
return OffsetPowerSlope(c, offset, power, slope);
|
||||
}
|
||||
|
||||
//
|
||||
// Saturation (should be used after offset/power/slope)
|
||||
// Recommended workspace: ACEScc (log)
|
||||
// Optimal range: [0.0, 2.0]
|
||||
//
|
||||
half3 Saturation(half3 c, half sat)
|
||||
{
|
||||
half luma = AcesLuminance(c);
|
||||
return luma.xxx + sat * (c - luma.xxx);
|
||||
}
|
||||
|
||||
//
|
||||
// Basic contrast curve
|
||||
// Recommended workspace: ACEScc (log)
|
||||
// Optimal range: [0.0, 2.0]
|
||||
//
|
||||
half3 ContrastLog(half3 c, half con)
|
||||
{
|
||||
return (c - ACEScc_MIDGRAY) * con + ACEScc_MIDGRAY;
|
||||
}
|
||||
|
||||
//
|
||||
// Hue, Saturation, Value
|
||||
// Ranges:
|
||||
// Hue [0.0, 1.0]
|
||||
// Sat [0.0, 1.0]
|
||||
// Lum [0.0, HALF_MAX]
|
||||
//
|
||||
half3 RgbToHsv(half3 c)
|
||||
{
|
||||
half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
half4 p = lerp(half4(c.bg, K.wz), half4(c.gb, K.xy), step(c.b, c.g));
|
||||
half4 q = lerp(half4(p.xyw, c.r), half4(c.r, p.yzx), step(p.x, c.r));
|
||||
half d = q.x - min(q.w, q.y);
|
||||
half e = EPSILON;
|
||||
return half3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
|
||||
half3 HsvToRgb(half3 c)
|
||||
{
|
||||
half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
half3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y);
|
||||
}
|
||||
|
||||
half RotateHue(half value, half low, half hi)
|
||||
{
|
||||
return (value < low)
|
||||
? value + hi
|
||||
: (value > hi)
|
||||
? value - hi
|
||||
: value;
|
||||
}
|
||||
|
||||
//
|
||||
// Remaps Y/R/G/B values
|
||||
//
|
||||
half3 YrgbCurve(half3 c, sampler2D curveTex)
|
||||
{
|
||||
const float kHalfPixel = (1.0 / 128.0) / 2.0;
|
||||
|
||||
// Y
|
||||
c += kHalfPixel.xxx;
|
||||
float mr = tex2D(curveTex, float2(c.r, 0.75)).a;
|
||||
float mg = tex2D(curveTex, float2(c.g, 0.75)).a;
|
||||
float mb = tex2D(curveTex, float2(c.b, 0.75)).a;
|
||||
c = saturate(float3(mr, mg, mb));
|
||||
|
||||
// RGB
|
||||
c += kHalfPixel.xxx;
|
||||
float r = tex2D(curveTex, float2(c.r, 0.75)).r;
|
||||
float g = tex2D(curveTex, float2(c.g, 0.75)).g;
|
||||
float b = tex2D(curveTex, float2(c.b, 0.75)).b;
|
||||
return saturate(half3(r, g, b));
|
||||
}
|
||||
|
||||
//
|
||||
// (X) Hue VS Hue - Remaps hue on a curve according to the current hue
|
||||
// Input is Hue [0.0, 1.0]
|
||||
// Output is Hue [0.0, 1.0]
|
||||
//
|
||||
half SecondaryHueHue(half hue, sampler2D curveTex)
|
||||
{
|
||||
half offset = saturate(tex2D(curveTex, half2(hue, 0.25)).x) - 0.5;
|
||||
hue += offset;
|
||||
hue = RotateHue(hue, 0.0, 1.0);
|
||||
return hue;
|
||||
}
|
||||
|
||||
//
|
||||
// (Y) Hue VS Saturation - Remaps saturation on a curve according to the current hue
|
||||
// Input is Hue [0.0, 1.0]
|
||||
// Output is Saturation multiplier [0.0, 2.0]
|
||||
//
|
||||
half SecondaryHueSat(half hue, sampler2D curveTex)
|
||||
{
|
||||
return saturate(tex2D(curveTex, half2(hue, 0.25)).y) * 2.0;
|
||||
}
|
||||
|
||||
//
|
||||
// (Z) Saturation VS Saturation - Remaps saturation on a curve according to the current saturation
|
||||
// Input is Saturation [0.0, 1.0]
|
||||
// Output is Saturation multiplier [0.0, 2.0]
|
||||
//
|
||||
half SecondarySatSat(half sat, sampler2D curveTex)
|
||||
{
|
||||
return saturate(tex2D(curveTex, half2(sat, 0.25)).z) * 2.0;
|
||||
}
|
||||
|
||||
//
|
||||
// (W) Luminance VS Saturation - Remaps saturation on a curve according to the current luminance
|
||||
// Input is Luminance [0.0, 1.0]
|
||||
// Output is Saturation multiplier [0.0, 2.0]
|
||||
//
|
||||
half SecondaryLumSat(half lum, sampler2D curveTex)
|
||||
{
|
||||
return saturate(tex2D(curveTex, half2(lum, 0.25)).w) * 2.0;
|
||||
}
|
||||
|
||||
//
|
||||
// Channel mixing (same as Photoshop's and DaVinci's Resolve)
|
||||
// Recommended workspace: ACEScg (linear)
|
||||
// Input mixers should be in range [-2.0;2.0]
|
||||
//
|
||||
half3 ChannelMixer(half3 c, half3 red, half3 green, half3 blue)
|
||||
{
|
||||
return half3(
|
||||
dot(c, red),
|
||||
dot(c, green),
|
||||
dot(c, blue)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// LUT grading
|
||||
// scaleOffset = (1 / lut_width, 1 / lut_height, lut_height - 1)
|
||||
//
|
||||
half3 ApplyLut2d(sampler2D tex, half3 uvw, half3 scaleOffset)
|
||||
{
|
||||
// Strip format where `height = sqrt(width)`
|
||||
uvw.z *= scaleOffset.z;
|
||||
half shift = floor(uvw.z);
|
||||
uvw.xy = uvw.xy * scaleOffset.z * scaleOffset.xy + scaleOffset.xy * 0.5;
|
||||
uvw.x += shift * scaleOffset.y;
|
||||
uvw.xyz = lerp(tex2D(tex, uvw.xy).rgb, tex2D(tex, uvw.xy + half2(scaleOffset.y, 0)).rgb, uvw.z - shift);
|
||||
return uvw;
|
||||
}
|
||||
|
||||
half3 ApplyLut3d(sampler3D tex, half3 uvw)
|
||||
{
|
||||
return tex3D(tex, uvw).rgb;
|
||||
}
|
||||
|
||||
#endif // __COLOR_GRADING__
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 26a62c2e30be83547bdfa9fe837165e3
|
||||
timeCreated: 1460363486
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
#ifndef __COMMON__
|
||||
#define __COMMON__
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
// Mobile: use RGBM instead of float/half RGB
|
||||
#define USE_RGBM defined(SHADER_API_MOBILE)
|
||||
|
||||
#define MOBILE_OR_CONSOLE (defined(SHADER_API_MOBILE) || defined(SHADER_API_PSSL) || defined(SHADER_API_XBOXONE) || defined(SHADER_API_WIIU))
|
||||
|
||||
#if defined(SHADER_API_PSSL)
|
||||
// No support for sampler2D_half on PS4 in 5.4
|
||||
#define sampler2D_half sampler2D_float
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Uniforms
|
||||
|
||||
#if defined(SEPARATE_TEXTURE_SAMPLER)
|
||||
Texture2D _MainTex;
|
||||
SamplerState sampler_MainTex;
|
||||
#else
|
||||
sampler2D _MainTex;
|
||||
#endif
|
||||
float4 _MainTex_TexelSize;
|
||||
float4 _MainTex_ST;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Vertex shaders
|
||||
|
||||
struct AttributesDefault
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct VaryingsDefault
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float2 uvSPR : TEXCOORD1; // Single Pass Stereo UVs
|
||||
};
|
||||
|
||||
VaryingsDefault VertDefault(AttributesDefault v)
|
||||
{
|
||||
VaryingsDefault o;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.uvSPR = UnityStereoScreenSpaceUVAdjust(v.texcoord.xy, _MainTex_ST);
|
||||
return o;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Maths stuff
|
||||
|
||||
#define HALF_MAX 65504.0
|
||||
#define EPSILON 1.0e-4
|
||||
#define UNITY_PI_2 (UNITY_PI * 2.0)
|
||||
|
||||
inline half Min3(half3 x) { return min(x.x, min(x.y, x.z)); }
|
||||
inline half Min3(half x, half y, half z) { return min(x, min(y, z)); }
|
||||
|
||||
inline half Max3(half3 x) { return max(x.x, max(x.y, x.z)); }
|
||||
inline half Max3(half x, half y, half z) { return max(x, max(y, z)); }
|
||||
|
||||
inline half Min4(half4 x) { return min(x.x, min(x.y, min(x.z, x.w))); }
|
||||
inline half Min4(half x, half y, half z, half w) { return min(x, min(y, min(z, w))); }
|
||||
|
||||
inline half Max4(half4 x) { return max(x.x, max(x.y, max(x.z, x.w))); }
|
||||
inline half Max4(half x, half y, half z, half w) { return max(x, max(y, min(z, w))); }
|
||||
|
||||
inline half Pow2(half x) { return x * x; }
|
||||
inline half2 Pow2(half2 x) { return x * x; }
|
||||
inline half3 Pow2(half3 x) { return x * x; }
|
||||
inline half4 Pow2(half4 x) { return x * x; }
|
||||
|
||||
inline half Pow3(half x) { return x * x * x; }
|
||||
inline half2 Pow3(half2 x) { return x * x * x; }
|
||||
inline half3 Pow3(half3 x) { return x * x * x; }
|
||||
inline half4 Pow3(half4 x) { return x * x * x; }
|
||||
|
||||
#ifndef UNITY_STANDARD_BRDF_INCLUDED
|
||||
inline half Pow4(half x) { return x * x * x * x; }
|
||||
inline half2 Pow4(half2 x) { return x * x * x * x; }
|
||||
inline half3 Pow4(half3 x) { return x * x * x * x; }
|
||||
inline half4 Pow4(half4 x) { return x * x * x * x; }
|
||||
#endif
|
||||
|
||||
// Returns the largest vector of v1 and v2
|
||||
inline half2 MaxV(half2 v1, half2 v2) { return dot(v1, v1) < dot(v2, v2) ? v2 : v1; }
|
||||
inline half3 MaxV(half3 v1, half3 v2) { return dot(v1, v1) < dot(v2, v2) ? v2 : v1; }
|
||||
inline half4 MaxV(half4 v1, half4 v2) { return dot(v1, v1) < dot(v2, v2) ? v2 : v1; }
|
||||
|
||||
// Clamp HDR value within a safe range
|
||||
inline half SafeHDR(half c) { return min(c, HALF_MAX); }
|
||||
inline half2 SafeHDR(half2 c) { return min(c, HALF_MAX); }
|
||||
inline half3 SafeHDR(half3 c) { return min(c, HALF_MAX); }
|
||||
inline half4 SafeHDR(half4 c) { return min(c, HALF_MAX); }
|
||||
|
||||
// Compatibility function
|
||||
#if (SHADER_TARGET < 50 && !defined(SHADER_API_PSSL))
|
||||
float rcp(float value)
|
||||
{
|
||||
return 1.0 / value;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Tonemapper from http://gpuopen.com/optimized-reversible-tonemapper-for-resolve/
|
||||
float4 FastToneMap(in float4 color)
|
||||
{
|
||||
return float4(color.rgb * rcp(Max3(color.rgb) + 1.), color.a);
|
||||
}
|
||||
|
||||
float4 FastToneMap(in float4 color, in float weight)
|
||||
{
|
||||
return float4(color.rgb * rcp(weight * Max3(color.rgb) + 1.), color.a);
|
||||
}
|
||||
|
||||
float4 FastToneUnmap(in float4 color)
|
||||
{
|
||||
return float4(color.rgb * rcp(1. - Max3(color.rgb)), color.a);
|
||||
}
|
||||
|
||||
// Interleaved gradient function from Jimenez 2014 http://goo.gl/eomGso
|
||||
float GradientNoise(float2 uv)
|
||||
{
|
||||
uv = floor(uv * _ScreenParams.xy);
|
||||
float f = dot(float2(0.06711056, 0.00583715), uv);
|
||||
return frac(52.9829189 * frac(f));
|
||||
}
|
||||
|
||||
// Z buffer depth to linear 0-1 depth
|
||||
// Handles orthographic projection correctly
|
||||
float LinearizeDepth(float z)
|
||||
{
|
||||
float isOrtho = unity_OrthoParams.w;
|
||||
float isPers = 1.0 - unity_OrthoParams.w;
|
||||
z *= _ZBufferParams.x;
|
||||
return (1.0 - isOrtho * z) / (isPers * z + _ZBufferParams.y);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RGBM encoding/decoding
|
||||
|
||||
half4 EncodeHDR(float3 rgb)
|
||||
{
|
||||
#if USE_RGBM
|
||||
rgb *= 1.0 / 8.0;
|
||||
float m = max(max(rgb.r, rgb.g), max(rgb.b, 1e-6));
|
||||
m = ceil(m * 255.0) / 255.0;
|
||||
return half4(rgb / m, m);
|
||||
#else
|
||||
return half4(rgb, 0.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
float3 DecodeHDR(half4 rgba)
|
||||
{
|
||||
#if USE_RGBM
|
||||
return rgba.rgb * rgba.a * 8.0;
|
||||
#else
|
||||
return rgba.rgb;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // __COMMON__
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eb88496804341c648b32a75843d92ccb
|
||||
timeCreated: 1465205118
|
||||
licenseType: Store
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
#ifndef __DEPTH_OF_FIELD__
|
||||
#define __DEPTH_OF_FIELD__
|
||||
|
||||
#if SHADER_TARGET >= 50
|
||||
// Use separate texture/sampler objects on Shader Model 5.0
|
||||
#define SEPARATE_TEXTURE_SAMPLER
|
||||
#define DOF_DECL_TEX2D(tex) Texture2D tex; SamplerState sampler##tex
|
||||
#define DOF_TEX2D(tex, coord) tex.Sample(sampler##tex, coord)
|
||||
#else
|
||||
#define DOF_DECL_TEX2D(tex) sampler2D tex
|
||||
#define DOF_TEX2D(tex, coord) tex2D(tex, coord)
|
||||
#endif
|
||||
|
||||
#include "Common.cginc"
|
||||
#include "DiskKernels.cginc"
|
||||
|
||||
DOF_DECL_TEX2D(_CameraDepthTexture);
|
||||
DOF_DECL_TEX2D(_CameraMotionVectorsTexture);
|
||||
DOF_DECL_TEX2D(_CoCTex);
|
||||
|
||||
// Camera parameters
|
||||
float _Distance;
|
||||
float _LensCoeff; // f^2 / (N * (S1 - f) * film_width * 2)
|
||||
float _MaxCoC;
|
||||
float _RcpMaxCoC;
|
||||
float _RcpAspect;
|
||||
half3 _TaaParams; // Jitter.x, Jitter.y, Blending
|
||||
|
||||
struct VaryingsDOF
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
half2 uv : TEXCOORD0;
|
||||
half2 uvAlt : TEXCOORD1;
|
||||
};
|
||||
|
||||
// Common vertex shader with single pass stereo rendering support
|
||||
VaryingsDOF VertDOF(AttributesDefault v)
|
||||
{
|
||||
half2 uvAlt = v.texcoord;
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
if (_MainTex_TexelSize.y < 0.0) uvAlt.y = 1.0 - uvAlt.y;
|
||||
#endif
|
||||
|
||||
VaryingsDOF o;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
|
||||
#if defined(UNITY_SINGLE_PASS_STEREO)
|
||||
o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST);
|
||||
o.uvAlt = UnityStereoScreenSpaceUVAdjust(uvAlt, _MainTex_ST);
|
||||
#else
|
||||
o.uv = v.texcoord;
|
||||
o.uvAlt = uvAlt;
|
||||
#endif
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
// CoC calculation
|
||||
half4 FragCoC(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
float depth = LinearEyeDepth(DOF_TEX2D(_CameraDepthTexture, i.uv));
|
||||
half coc = (depth - _Distance) * _LensCoeff / max(depth, 1e-5);
|
||||
return saturate(coc * 0.5 * _RcpMaxCoC + 0.5);
|
||||
}
|
||||
|
||||
// Temporal filter
|
||||
half4 FragTempFilter(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
float3 uvOffs = _MainTex_TexelSize.xyy * float3(1, 1, 0);
|
||||
|
||||
#if defined(SEPARATE_TEXTURE_SAMPLER)
|
||||
|
||||
half4 cocTL = _CoCTex.GatherRed(sampler_CoCTex, i.uv - uvOffs.xy * 0.5); // top-left
|
||||
half4 cocBR = _CoCTex.GatherRed(sampler_CoCTex, i.uv + uvOffs.xy * 0.5); // bottom-right
|
||||
half coc1 = cocTL.x; // top
|
||||
half coc2 = cocTL.z; // left
|
||||
half coc3 = cocBR.x; // bottom
|
||||
half coc4 = cocBR.z; // right
|
||||
|
||||
#else
|
||||
|
||||
half coc1 = DOF_TEX2D(_CoCTex, i.uv - uvOffs.xz).r; // top
|
||||
half coc2 = DOF_TEX2D(_CoCTex, i.uv - uvOffs.zy).r; // left
|
||||
half coc3 = DOF_TEX2D(_CoCTex, i.uv + uvOffs.zy).r; // bottom
|
||||
half coc4 = DOF_TEX2D(_CoCTex, i.uv + uvOffs.xz).r; // right
|
||||
|
||||
#endif
|
||||
|
||||
// Dejittered center sample.
|
||||
half coc0 = DOF_TEX2D(_CoCTex, i.uv - _TaaParams.xy).r;
|
||||
|
||||
// CoC dilation: determine the closest point in the four neighbors.
|
||||
float3 closest = float3(0, 0, coc0);
|
||||
closest = coc1 < closest.z ? float3(-uvOffs.xz, coc1) : closest;
|
||||
closest = coc2 < closest.z ? float3(-uvOffs.zy, coc2) : closest;
|
||||
closest = coc3 < closest.z ? float3(+uvOffs.zy, coc3) : closest;
|
||||
closest = coc4 < closest.z ? float3(+uvOffs.xz, coc4) : closest;
|
||||
|
||||
// Sample the history buffer with the motion vector at the closest point.
|
||||
float2 motion = DOF_TEX2D(_CameraMotionVectorsTexture, i.uv + closest.xy).xy;
|
||||
half cocHis = DOF_TEX2D(_MainTex, i.uv - motion).r;
|
||||
|
||||
// Neighborhood clamping.
|
||||
half cocMin = closest.z;
|
||||
half cocMax = max(max(max(max(coc0, coc1), coc2), coc3), coc4);
|
||||
cocHis = clamp(cocHis, cocMin, cocMax);
|
||||
|
||||
// Blend with the history.
|
||||
return lerp(coc0, cocHis, _TaaParams.z);
|
||||
}
|
||||
|
||||
// Prefilter: downsampling and premultiplying.
|
||||
half4 FragPrefilter(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
#if defined(SEPARATE_TEXTURE_SAMPLER)
|
||||
|
||||
// Sample source colors.
|
||||
half4 c_r = _MainTex.GatherRed (sampler_MainTex, i.uv);
|
||||
half4 c_g = _MainTex.GatherGreen(sampler_MainTex, i.uv);
|
||||
half4 c_b = _MainTex.GatherBlue (sampler_MainTex, i.uv);
|
||||
|
||||
half3 c0 = half3(c_r.x, c_g.x, c_b.x);
|
||||
half3 c1 = half3(c_r.y, c_g.y, c_b.y);
|
||||
half3 c2 = half3(c_r.z, c_g.z, c_b.z);
|
||||
half3 c3 = half3(c_r.w, c_g.w, c_b.w);
|
||||
|
||||
// Sample CoCs.
|
||||
half4 cocs = _CoCTex.Gather(sampler_CoCTex, i.uvAlt) * 2.0 - 1.0;
|
||||
half coc0 = cocs.x;
|
||||
half coc1 = cocs.y;
|
||||
half coc2 = cocs.z;
|
||||
half coc3 = cocs.w;
|
||||
|
||||
#else
|
||||
|
||||
float3 duv = _MainTex_TexelSize.xyx * float3(0.5, 0.5, -0.5);
|
||||
|
||||
// Sample source colors.
|
||||
half3 c0 = DOF_TEX2D(_MainTex, i.uv - duv.xy).rgb;
|
||||
half3 c1 = DOF_TEX2D(_MainTex, i.uv - duv.zy).rgb;
|
||||
half3 c2 = DOF_TEX2D(_MainTex, i.uv + duv.zy).rgb;
|
||||
half3 c3 = DOF_TEX2D(_MainTex, i.uv + duv.xy).rgb;
|
||||
|
||||
// Sample CoCs.
|
||||
half coc0 = DOF_TEX2D(_CoCTex, i.uvAlt - duv.xy).r * 2.0 - 1.0;
|
||||
half coc1 = DOF_TEX2D(_CoCTex, i.uvAlt - duv.zy).r * 2.0 - 1.0;
|
||||
half coc2 = DOF_TEX2D(_CoCTex, i.uvAlt + duv.zy).r * 2.0 - 1.0;
|
||||
half coc3 = DOF_TEX2D(_CoCTex, i.uvAlt + duv.xy).r * 2.0 - 1.0;
|
||||
|
||||
#endif
|
||||
|
||||
// Apply CoC and luma weights to reduce bleeding and flickering.
|
||||
float w0 = abs(coc0) / (Max3(c0) + 1.0);
|
||||
float w1 = abs(coc1) / (Max3(c1) + 1.0);
|
||||
float w2 = abs(coc2) / (Max3(c2) + 1.0);
|
||||
float w3 = abs(coc3) / (Max3(c3) + 1.0);
|
||||
|
||||
// Weighted average of the color samples
|
||||
half3 avg = c0 * w0 + c1 * w1 + c2 * w2 + c3 * w3;
|
||||
avg /= max(w0 + w1 + w2 + w3, 1e-5);
|
||||
|
||||
// Select the largest CoC value.
|
||||
half coc_min = Min4(coc0, coc1, coc2, coc3);
|
||||
half coc_max = Max4(coc0, coc1, coc2, coc3);
|
||||
half coc = (-coc_min > coc_max ? coc_min : coc_max) * _MaxCoC;
|
||||
|
||||
// Premultiply CoC again.
|
||||
avg *= smoothstep(0, _MainTex_TexelSize.y * 2, abs(coc));
|
||||
|
||||
#if defined(UNITY_COLORSPACE_GAMMA)
|
||||
avg = GammaToLinearSpace(avg);
|
||||
#endif
|
||||
|
||||
return half4(avg, coc);
|
||||
}
|
||||
|
||||
// Bokeh filter with disk-shaped kernels
|
||||
half4 FragBlur(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
half4 samp0 = DOF_TEX2D(_MainTex, i.uv);
|
||||
|
||||
half4 bgAcc = 0.0; // Background: far field bokeh
|
||||
half4 fgAcc = 0.0; // Foreground: near field bokeh
|
||||
|
||||
UNITY_LOOP for (int si = 0; si < kSampleCount; si++)
|
||||
{
|
||||
float2 disp = kDiskKernel[si] * _MaxCoC;
|
||||
float dist = length(disp);
|
||||
|
||||
float2 duv = float2(disp.x * _RcpAspect, disp.y);
|
||||
half4 samp = DOF_TEX2D(_MainTex, i.uv + duv);
|
||||
|
||||
// BG: Compare CoC of the current sample and the center sample
|
||||
// and select smaller one.
|
||||
half bgCoC = max(min(samp0.a, samp.a), 0.0);
|
||||
|
||||
// Compare the CoC to the sample distance.
|
||||
// Add a small margin to smooth out.
|
||||
const half margin = _MainTex_TexelSize.y * 2;
|
||||
half bgWeight = saturate((bgCoC - dist + margin) / margin);
|
||||
half fgWeight = saturate((-samp.a - dist + margin) / margin);
|
||||
|
||||
// Cut influence from focused areas because they're darkened by CoC
|
||||
// premultiplying. This is only needed for near field.
|
||||
fgWeight *= step(_MainTex_TexelSize.y, -samp.a);
|
||||
|
||||
// Accumulation
|
||||
bgAcc += half4(samp.rgb, 1.0) * bgWeight;
|
||||
fgAcc += half4(samp.rgb, 1.0) * fgWeight;
|
||||
}
|
||||
|
||||
// Get the weighted average.
|
||||
bgAcc.rgb /= bgAcc.a + (bgAcc.a == 0.0); // zero-div guard
|
||||
fgAcc.rgb /= fgAcc.a + (fgAcc.a == 0.0);
|
||||
|
||||
// BG: Calculate the alpha value only based on the center CoC.
|
||||
// This is a rather aggressive approximation but provides stable results.
|
||||
bgAcc.a = smoothstep(_MainTex_TexelSize.y, _MainTex_TexelSize.y * 2.0, samp0.a);
|
||||
|
||||
// FG: Normalize the total of the weights.
|
||||
fgAcc.a *= UNITY_PI / kSampleCount;
|
||||
|
||||
// Alpha premultiplying
|
||||
half alpha = saturate(fgAcc.a);
|
||||
half3 rgb = lerp(bgAcc.rgb, fgAcc.rgb, alpha);
|
||||
|
||||
return half4(rgb, alpha);
|
||||
}
|
||||
|
||||
// Postfilter blur
|
||||
half4 FragPostBlur(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
// 9 tap tent filter with 4 bilinear samples
|
||||
const float4 duv = _MainTex_TexelSize.xyxy * float4(0.5, 0.5, -0.5, 0);
|
||||
half4 acc;
|
||||
acc = DOF_TEX2D(_MainTex, i.uv - duv.xy);
|
||||
acc += DOF_TEX2D(_MainTex, i.uv - duv.zy);
|
||||
acc += DOF_TEX2D(_MainTex, i.uv + duv.zy);
|
||||
acc += DOF_TEX2D(_MainTex, i.uv + duv.xy);
|
||||
return acc / 4.0;
|
||||
}
|
||||
|
||||
#endif // __DEPTH_OF_FIELD__
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
#ifndef __DEPTH_OF_FIELD__
|
||||
#define __DEPTH_OF_FIELD__
|
||||
|
||||
#if SHADER_TARGET >= 50
|
||||
// Use separate texture/sampler objects on Shader Model 5.0
|
||||
#define SEPARATE_TEXTURE_SAMPLER
|
||||
#define DOF_DECL_TEX2D(tex) Texture2D tex; SamplerState sampler##tex
|
||||
#define DOF_TEX2D(tex, coord) tex.Sample(sampler##tex, coord)
|
||||
#else
|
||||
#define DOF_DECL_TEX2D(tex) sampler2D tex
|
||||
#define DOF_TEX2D(tex, coord) tex2D(tex, coord)
|
||||
#endif
|
||||
|
||||
#include "Common.cginc"
|
||||
#include "DiskKernels.cginc"
|
||||
|
||||
DOF_DECL_TEX2D(_CameraDepthTexture);
|
||||
DOF_DECL_TEX2D(_CameraMotionVectorsTexture);
|
||||
DOF_DECL_TEX2D(_CoCTex);
|
||||
|
||||
// Camera parameters
|
||||
float _Distance;
|
||||
float _LensCoeff; // f^2 / (N * (S1 - f) * film_width * 2)
|
||||
float _MaxCoC;
|
||||
float _RcpMaxCoC;
|
||||
float _RcpAspect;
|
||||
half3 _TaaParams; // Jitter.x, Jitter.y, Blending
|
||||
|
||||
struct VaryingsDOF
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
half2 uv : TEXCOORD0;
|
||||
half2 uvAlt : TEXCOORD1;
|
||||
};
|
||||
|
||||
// Common vertex shader with single pass stereo rendering support
|
||||
VaryingsDOF VertDOF(AttributesDefault v)
|
||||
{
|
||||
half2 uvAlt = v.texcoord;
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
if (_MainTex_TexelSize.y < 0.0) uvAlt.y = 1.0 - uvAlt.y;
|
||||
#endif
|
||||
|
||||
VaryingsDOF o;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
|
||||
#if defined(UNITY_SINGLE_PASS_STEREO)
|
||||
o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST);
|
||||
o.uvAlt = UnityStereoScreenSpaceUVAdjust(uvAlt, _MainTex_ST);
|
||||
#else
|
||||
o.uv = v.texcoord;
|
||||
o.uvAlt = uvAlt;
|
||||
#endif
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
// CoC calculation
|
||||
half4 FragCoC(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
float depth = LinearEyeDepth(DOF_TEX2D(_CameraDepthTexture, i.uv));
|
||||
half coc = (depth - _Distance) * _LensCoeff / max(depth, 1e-5);
|
||||
return saturate(coc * 0.5 * _RcpMaxCoC + 0.5);
|
||||
}
|
||||
|
||||
// Temporal filter
|
||||
half4 FragTempFilter(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
float3 uvOffs = _MainTex_TexelSize.xyy * float3(1, 1, 0);
|
||||
|
||||
#if defined(SEPARATE_TEXTURE_SAMPLER)
|
||||
|
||||
half4 cocTL = _CoCTex.GatherRed(sampler_CoCTex, i.uv - uvOffs.xy * 0.5); // top-left
|
||||
half4 cocBR = _CoCTex.GatherRed(sampler_CoCTex, i.uv + uvOffs.xy * 0.5); // bottom-right
|
||||
half coc1 = cocTL.x; // top
|
||||
half coc2 = cocTL.z; // left
|
||||
half coc3 = cocBR.x; // bottom
|
||||
half coc4 = cocBR.z; // right
|
||||
|
||||
#else
|
||||
|
||||
half coc1 = DOF_TEX2D(_CoCTex, i.uv - uvOffs.xz).r; // top
|
||||
half coc2 = DOF_TEX2D(_CoCTex, i.uv - uvOffs.zy).r; // left
|
||||
half coc3 = DOF_TEX2D(_CoCTex, i.uv + uvOffs.zy).r; // bottom
|
||||
half coc4 = DOF_TEX2D(_CoCTex, i.uv + uvOffs.xz).r; // right
|
||||
|
||||
#endif
|
||||
|
||||
// Dejittered center sample.
|
||||
half coc0 = DOF_TEX2D(_CoCTex, i.uv - _TaaParams.xy).r;
|
||||
|
||||
// CoC dilation: determine the closest point in the four neighbors.
|
||||
float3 closest = float3(0, 0, coc0);
|
||||
closest = coc1 < closest.z ? float3(-uvOffs.xz, coc1) : closest;
|
||||
closest = coc2 < closest.z ? float3(-uvOffs.zy, coc2) : closest;
|
||||
closest = coc3 < closest.z ? float3(+uvOffs.zy, coc3) : closest;
|
||||
closest = coc4 < closest.z ? float3(+uvOffs.xz, coc4) : closest;
|
||||
|
||||
// Sample the history buffer with the motion vector at the closest point.
|
||||
float2 motion = DOF_TEX2D(_CameraMotionVectorsTexture, i.uv + closest.xy).xy;
|
||||
half cocHis = DOF_TEX2D(_MainTex, i.uv - motion).r;
|
||||
|
||||
// Neighborhood clamping.
|
||||
half cocMin = closest.z;
|
||||
half cocMax = max(max(max(max(coc0, coc1), coc2), coc3), coc4);
|
||||
cocHis = clamp(cocHis, cocMin, cocMax);
|
||||
|
||||
// Blend with the history.
|
||||
return lerp(coc0, cocHis, _TaaParams.z);
|
||||
}
|
||||
|
||||
// Prefilter: downsampling and premultiplying.
|
||||
half4 FragPrefilter(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
#if defined(SEPARATE_TEXTURE_SAMPLER)
|
||||
|
||||
// Sample source colors.
|
||||
half4 c_r = _MainTex.GatherRed (sampler_MainTex, i.uv);
|
||||
half4 c_g = _MainTex.GatherGreen(sampler_MainTex, i.uv);
|
||||
half4 c_b = _MainTex.GatherBlue (sampler_MainTex, i.uv);
|
||||
|
||||
half3 c0 = half3(c_r.x, c_g.x, c_b.x);
|
||||
half3 c1 = half3(c_r.y, c_g.y, c_b.y);
|
||||
half3 c2 = half3(c_r.z, c_g.z, c_b.z);
|
||||
half3 c3 = half3(c_r.w, c_g.w, c_b.w);
|
||||
|
||||
// Sample CoCs.
|
||||
half4 cocs = _CoCTex.Gather(sampler_CoCTex, i.uvAlt) * 2.0 - 1.0;
|
||||
half coc0 = cocs.x;
|
||||
half coc1 = cocs.y;
|
||||
half coc2 = cocs.z;
|
||||
half coc3 = cocs.w;
|
||||
|
||||
#else
|
||||
|
||||
float3 duv = _MainTex_TexelSize.xyx * float3(0.5, 0.5, -0.5);
|
||||
|
||||
// Sample source colors.
|
||||
half3 c0 = DOF_TEX2D(_MainTex, i.uv - duv.xy).rgb;
|
||||
half3 c1 = DOF_TEX2D(_MainTex, i.uv - duv.zy).rgb;
|
||||
half3 c2 = DOF_TEX2D(_MainTex, i.uv + duv.zy).rgb;
|
||||
half3 c3 = DOF_TEX2D(_MainTex, i.uv + duv.xy).rgb;
|
||||
|
||||
// Sample CoCs.
|
||||
half coc0 = DOF_TEX2D(_CoCTex, i.uvAlt - duv.xy).r * 2.0 - 1.0;
|
||||
half coc1 = DOF_TEX2D(_CoCTex, i.uvAlt - duv.zy).r * 2.0 - 1.0;
|
||||
half coc2 = DOF_TEX2D(_CoCTex, i.uvAlt + duv.zy).r * 2.0 - 1.0;
|
||||
half coc3 = DOF_TEX2D(_CoCTex, i.uvAlt + duv.xy).r * 2.0 - 1.0;
|
||||
|
||||
#endif
|
||||
|
||||
// Apply CoC and luma weights to reduce bleeding and flickering.
|
||||
float w0 = abs(coc0) / (Max3(c0) + 1.0);
|
||||
float w1 = abs(coc1) / (Max3(c1) + 1.0);
|
||||
float w2 = abs(coc2) / (Max3(c2) + 1.0);
|
||||
float w3 = abs(coc3) / (Max3(c3) + 1.0);
|
||||
|
||||
// Weighted average of the color samples
|
||||
half3 avg = c0 * w0 + c1 * w1 + c2 * w2 + c3 * w3;
|
||||
avg /= max(w0 + w1 + w2 + w3, 1e-5);
|
||||
|
||||
// Select the largest CoC value.
|
||||
half coc_min = Min4(coc0, coc1, coc2, coc3);
|
||||
half coc_max = Max4(coc0, coc1, coc2, coc3);
|
||||
half coc = (-coc_min > coc_max ? coc_min : coc_max) * _MaxCoC;
|
||||
|
||||
// Premultiply CoC again.
|
||||
avg *= smoothstep(0, _MainTex_TexelSize.y * 2, abs(coc));
|
||||
|
||||
#if defined(UNITY_COLORSPACE_GAMMA)
|
||||
avg = GammaToLinearSpace(avg);
|
||||
#endif
|
||||
|
||||
return half4(avg, coc);
|
||||
}
|
||||
|
||||
// Bokeh filter with disk-shaped kernels
|
||||
half4 FragBlur(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
half4 samp0 = DOF_TEX2D(_MainTex, i.uv);
|
||||
|
||||
half4 bgAcc = 0.0; // Background: far field bokeh
|
||||
half4 fgAcc = 0.0; // Foreground: near field bokeh
|
||||
|
||||
UNITY_LOOP for (int si = 0; si < kSampleCount; si++)
|
||||
{
|
||||
float2 disp = kDiskKernel[si] * _MaxCoC;
|
||||
float dist = length(disp);
|
||||
|
||||
float2 duv = float2(disp.x * _RcpAspect, disp.y);
|
||||
half4 samp = DOF_TEX2D(_MainTex, i.uv + duv);
|
||||
|
||||
// BG: Compare CoC of the current sample and the center sample
|
||||
// and select smaller one.
|
||||
half bgCoC = max(min(samp0.a, samp.a), 0.0);
|
||||
|
||||
// Compare the CoC to the sample distance.
|
||||
// Add a small margin to smooth out.
|
||||
const half margin = _MainTex_TexelSize.y * 2;
|
||||
half bgWeight = saturate((bgCoC - dist + margin) / margin);
|
||||
half fgWeight = saturate((-samp.a - dist + margin) / margin);
|
||||
|
||||
// Cut influence from focused areas because they're darkened by CoC
|
||||
// premultiplying. This is only needed for near field.
|
||||
fgWeight *= step(_MainTex_TexelSize.y, -samp.a);
|
||||
|
||||
// Accumulation
|
||||
bgAcc += half4(samp.rgb, 1.0) * bgWeight;
|
||||
fgAcc += half4(samp.rgb, 1.0) * fgWeight;
|
||||
}
|
||||
|
||||
// Get the weighted average.
|
||||
bgAcc.rgb /= bgAcc.a + (bgAcc.a == 0.0); // zero-div guard
|
||||
fgAcc.rgb /= fgAcc.a + (fgAcc.a == 0.0);
|
||||
|
||||
// BG: Calculate the alpha value only based on the center CoC.
|
||||
// This is a rather aggressive approximation but provides stable results.
|
||||
bgAcc.a = smoothstep(_MainTex_TexelSize.y, _MainTex_TexelSize.y * 2.0, samp0.a);
|
||||
|
||||
// FG: Normalize the total of the weights.
|
||||
fgAcc.a *= UNITY_PI / kSampleCount;
|
||||
|
||||
// Alpha premultiplying
|
||||
half alpha = saturate(fgAcc.a);
|
||||
half3 rgb = lerp(bgAcc.rgb, fgAcc.rgb, alpha);
|
||||
|
||||
return half4(rgb, alpha);
|
||||
}
|
||||
|
||||
// Postfilter blur
|
||||
half4 FragPostBlur(VaryingsDOF i) : SV_Target
|
||||
{
|
||||
// 9 tap tent filter with 4 bilinear samples
|
||||
const float4 duv = _MainTex_TexelSize.xyxy * float4(0.5, 0.5, -0.5, 0);
|
||||
half4 acc;
|
||||
acc = DOF_TEX2D(_MainTex, i.uv - duv.xy);
|
||||
acc += DOF_TEX2D(_MainTex, i.uv - duv.zy);
|
||||
acc += DOF_TEX2D(_MainTex, i.uv + duv.zy);
|
||||
acc += DOF_TEX2D(_MainTex, i.uv + duv.xy);
|
||||
return acc / 4.0;
|
||||
}
|
||||
|
||||
#endif // __DEPTH_OF_FIELD__
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue