|
|
- Shader "Hidden/FXAA" {
- Properties {
- _MainTex ("Texture", 2D) = "white" {}
- }
-
- CGINCLUDE
- #include "UnityCG.cginc"
-
- sampler2D _MainTex;
- half4 _MainTex_TexelSize;
-
- half _ContrastThreshold, _RelativeThreshold;
- half _SubpixelBlending;
-
- struct VertexData {
- half4 vertex : POSITION;
- half2 uv : TEXCOORD0;
- };
-
- struct Interpolators {
- half4 pos : SV_POSITION;
- half2 uv : TEXCOORD0;
- };
-
- Interpolators VertexProgram (VertexData v) {
- Interpolators i;
- i.pos = UnityObjectToClipPos(v.vertex);
- i.uv = v.uv;
- return i;
- }
-
- half4 Sample (half2 uv) {
- return tex2Dlod(_MainTex, half4(uv, 0, 0));
- }
-
- half SampleLuminance (half2 uv) {
- return Sample(uv).g;
- // #if defined(LUMINANCE_GREEN)
- // return Sample(uv).g;
- // #else
- // return Sample(uv).a;
- // #endif
- }
-
- half SampleLuminance (half2 uv, half uOffset, half vOffset) {
- uv += _MainTex_TexelSize * half2(uOffset, vOffset);
- return SampleLuminance(uv);
- }
-
- struct LuminanceData {
- half m, n, e, s, w;
- half ne, nw, se, sw;
- half highest, lowest, contrast;
- };
-
- LuminanceData SampleLuminanceNeighborhood (half2 uv) {
- LuminanceData l;
- l.m = SampleLuminance(uv);
- l.n = SampleLuminance(uv, 0, 1);
- l.e = SampleLuminance(uv, 1, 0);
- l.s = SampleLuminance(uv, 0, -1);
- l.w = SampleLuminance(uv, -1, 0);
-
- l.ne = SampleLuminance(uv, 1, 1);
- l.nw = SampleLuminance(uv, -1, 1);
- l.se = SampleLuminance(uv, 1, -1);
- l.sw = SampleLuminance(uv, -1, -1);
-
- l.highest = max(max(max(max(l.n, l.e), l.s), l.w), l.m);
- l.lowest = min(min(min(min(l.n, l.e), l.s), l.w), l.m);
- l.contrast = l.highest - l.lowest;
- return l;
- }
-
- bool ShouldSkipPixel (LuminanceData l) {
- half threshold =
- max(_ContrastThreshold, _RelativeThreshold * l.highest);
- return l.contrast < threshold;
- }
-
- half DeterminePixelBlendFactor (LuminanceData l) {
- half filter = 2 * (l.n + l.e + l.s + l.w);
- filter += l.ne + l.nw + l.se + l.sw;
- filter *= 1.0 / 12.0;
- filter = abs(filter - l.m);
- filter = saturate(filter / l.contrast);
-
- half blendFactor = smoothstep(0, 1, filter);
- return blendFactor * blendFactor * _SubpixelBlending;
- }
-
- struct EdgeData {
- bool isHorizontal;
- half pixelStep;
- half oppositeLuminance, gradient;
- };
-
- EdgeData DetermineEdge (LuminanceData l) {
- EdgeData e;
- half horizontal =
- abs(l.n + l.s - 2 * l.m) * 2 +
- abs(l.ne + l.se - 2 * l.e) +
- abs(l.nw + l.sw - 2 * l.w);
- half vertical =
- abs(l.e + l.w - 2 * l.m) * 2 +
- abs(l.ne + l.nw - 2 * l.n) +
- abs(l.se + l.sw - 2 * l.s);
- e.isHorizontal = horizontal >= vertical;
-
- half pLuminance = e.isHorizontal ? l.n : l.e;
- half nLuminance = e.isHorizontal ? l.s : l.w;
- half pGradient = abs(pLuminance - l.m);
- half nGradient = abs(nLuminance - l.m);
-
- e.pixelStep =
- e.isHorizontal ? _MainTex_TexelSize.y : _MainTex_TexelSize.x;
-
- if (pGradient < nGradient) {
- e.pixelStep = -e.pixelStep;
- e.oppositeLuminance = nLuminance;
- e.gradient = nGradient;
- }
- else {
- e.oppositeLuminance = pLuminance;
- e.gradient = pGradient;
- }
-
- return e;
- }
-
- #if defined(LOW_QUALITY)
- #define EDGE_STEP_COUNT 4
- #define EDGE_STEPS 1, 1.5, 2, 4
- #define EDGE_GUESS 12
- #else
- #define EDGE_STEP_COUNT 10
- #define EDGE_STEPS 1, 1.5, 2, 2, 2, 2, 2, 2, 2, 4
- #define EDGE_GUESS 8
- #endif
-
- static const half edgeSteps[EDGE_STEP_COUNT] = { EDGE_STEPS };
-
- half DetermineEdgeBlendFactor (LuminanceData l, EdgeData e, half2 uv) {
- half2 uvEdge = uv;
- half2 edgeStep;
- if (e.isHorizontal) {
- uvEdge.y += e.pixelStep * 0.5;
- edgeStep = half2(_MainTex_TexelSize.x, 0);
- }
- else {
- uvEdge.x += e.pixelStep * 0.5;
- edgeStep = half2(0, _MainTex_TexelSize.y);
- }
-
- half edgeLuminance = (l.m + e.oppositeLuminance) * 0.5;
- half gradientThreshold = e.gradient * 0.25;
-
- half2 puv = uvEdge + edgeStep * edgeSteps[0];
- half pLuminanceDelta = SampleLuminance(puv) - edgeLuminance;
- bool pAtEnd = abs(pLuminanceDelta) >= gradientThreshold;
-
- UNITY_UNROLL
- for (int i = 1; i < EDGE_STEP_COUNT && !pAtEnd; i++) {
- puv += edgeStep * edgeSteps[i];
- pLuminanceDelta = SampleLuminance(puv) - edgeLuminance;
- pAtEnd = abs(pLuminanceDelta) >= gradientThreshold;
- }
- if (!pAtEnd) {
- puv += edgeStep * EDGE_GUESS;
- }
-
- half2 nuv = uvEdge - edgeStep * edgeSteps[0];
- half nLuminanceDelta = SampleLuminance(nuv) - edgeLuminance;
- bool nAtEnd = abs(nLuminanceDelta) >= gradientThreshold;
-
- UNITY_UNROLL
- for (int i = 1; i < EDGE_STEP_COUNT && !nAtEnd; i++) {
- nuv -= edgeStep * edgeSteps[i];
- nLuminanceDelta = SampleLuminance(nuv) - edgeLuminance;
- nAtEnd = abs(nLuminanceDelta) >= gradientThreshold;
- }
- if (!nAtEnd) {
- nuv -= edgeStep * EDGE_GUESS;
- }
-
- half pDistance, nDistance;
- if (e.isHorizontal) {
- pDistance = puv.x - uv.x;
- nDistance = uv.x - nuv.x;
- }
- else {
- pDistance = puv.y - uv.y;
- nDistance = uv.y - nuv.y;
- }
-
- half shortestDistance;
- bool deltaSign;
- if (pDistance <= nDistance) {
- shortestDistance = pDistance;
- deltaSign = pLuminanceDelta >= 0;
- }
- else {
- shortestDistance = nDistance;
- deltaSign = nLuminanceDelta >= 0;
- }
-
- if (deltaSign == (l.m - edgeLuminance >= 0)) {
- return 0;
- }
- return 0.5 - shortestDistance / (pDistance + nDistance);
- }
-
- half4 ApplyFXAA (half2 uv) {
- LuminanceData l = SampleLuminanceNeighborhood(uv);
- if (ShouldSkipPixel(l)) {
- return Sample(uv);
- }
-
- half pixelBlend = DeterminePixelBlendFactor(l);
- EdgeData e = DetermineEdge(l);
- half edgeBlend = DetermineEdgeBlendFactor(l, e, uv);
- half finalBlend = max(pixelBlend, edgeBlend);
-
- if (e.isHorizontal) {
- uv.y += e.pixelStep * finalBlend;
- }
- else {
- uv.x += e.pixelStep * finalBlend;
- }
- return half4(Sample(uv).rgb, l.m);
- }
- ENDCG
-
- SubShader {
- Cull Off
- ZTest Always
- ZWrite Off
-
- Pass { // 0 luminancePass
- CGPROGRAM
- #pragma vertex VertexProgram
- #pragma fragment FragmentProgram
- // #pragma enable_d3d11_debug_symbols
- #pragma multi_compile _ GAMMA_BLENDING
-
- half4 FragmentProgram (Interpolators i) : SV_Target {
- half4 sample = tex2D(_MainTex, i.uv);
- sample.rgb = saturate(sample.rgb);
- sample.a = LinearRgbToLuminance(sample.rgb);
- #if defined(GAMMA_BLENDING)
- sample.rgb = LinearToGammaSpace(sample.rgb);
- #endif
- return sample;
- }
- ENDCG
- }
-
- Pass { // 1 fxaaPass
- CGPROGRAM
- #pragma vertex VertexProgram
- #pragma fragment FragmentProgram
- // #pragma enable_d3d11_debug_symbols
- // #pragma multi_compile _ LUMINANCE_GREEN
- #pragma multi_compile _ LOW_QUALITY
- #pragma multi_compile _ GAMMA_BLENDING
-
- half4 FragmentProgram (Interpolators i) : SV_Target {
- half4 sample = ApplyFXAA(i.uv);
- #if defined(GAMMA_BLENDING)
- sample.rgb = GammaToLinearSpace(sample.rgb);
- #endif
- return sample;
- }
- ENDCG
- }
- }
- }
|