中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

【URP】Unity[抗鋸齒]原理實現(xian)與對比(bi)

專欄-直達

歷史發展節點

  • ?2001年?:MSAA成為DirectX 8標準配置,通過硬件多采樣解決幾何鋸齒
  • ?2009年?:NVIDIA推出FXAA,開創后處理抗鋸齒時代
  • ?2011年?:SMAA 1.0發布,平衡性能與畫質
  • ?2014年?:TAA開始普及,解決動態場景抗鋸齒問題
  • ?2017年?:Unity URP集成全系列抗鋸齒方案

抗鋸齒技術實現原理

快速近似抗鋸齒(FXAA)

通過全(quan)屏后處理(li)檢測邊緣像素并(bing)進行顏(yan)色混合,采(cai)用(yong)亮度對(dui)比度閾值(zhi)識別鋸齒區域,使用(yong)低通濾(lv)波器平滑(hua)邊緣。其核心是(shi)犧牲少量銳度換(huan)取性能優勢(shi),處理(li)過程(cheng)完全(quan)在像素空間(jian)進行,不依賴(lai)幾何信息。

?實現原理?:

通過全(quan)屏后處理檢測像(xiang)素間亮度(du)差異(如RGB通道(dao)對比度(du)),對超(chao)過閾值的(de)邊緣(yuan)區(qu)域進行低通濾波混合。例如,當檢測到斜線邊緣(yuan)時,會模糊相鄰像(xiang)素以消(xiao)除階梯狀鋸(ju)齒(chi)?。

核心流程?:

  • 亮度計算:使用RGB轉亮度公式luma = dot(rgb, float3(0.299, 0.587, 0.114)) 采用(yong)ITU-R BT.709標(biao)準權重(zhong).

  • 邊緣(yuan)檢測:對比3x3區(qu)域內像素亮(liang)度差(cha),超過閾值(zhi)則(ze)標記為邊緣(yuan)

  • 方向(xiang)判定:計算水平/垂直亮度梯(ti)度,確(que)定邊緣走向(xiang)(NW-SE或NE-SW)

  • 混合執行:沿邊(bian)緣方向進行5-tap濾(lv)波,加權平均相(xiang)鄰像素顏色

  • FXAA.shader

    • 關鍵參數說明
      • ?亮度計算?:采用0.2126729, 0.7151522, 0.0721750權重符合sRGB標準
      • ?邊緣閾值?:edgeThresholdMin防止過度處理平滑區域,edgeThreshold動態適應高亮度區域
      • ?方向判定?:通過水平和垂直方向的二階差分確定主邊緣方向
      • ?子像素混合?:subpixelBlend控制亞像素級混合強度,改善細線表現
    • URP集成要點
      • 通過RenderFeature添加到URP渲染管線
      • 需在相機設置中禁用MSAA/TAA等沖突抗鋸齒
      • 紋理采樣使用URP標準的SAMPLE_TEXTURE2D
    Shader "Hidden/Universal Render Pipeline/FXAA"
    {
        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    
        TEXTURE2D(_MainTex);
        SAMPLER(sampler_MainTex);
        float4 _MainTex_TexelSize;
    
        // ITU-R BT.709亮度系數
        float Luminance(float3 rgb)
        {
            return dot(rgb, float3(0.2126729, 0.7151522, 0.0721750));
        }
    
        // 邊緣檢測結構體
        struct EdgeData {
            float m, n, e, s, w;
            float highest, lowest, contrast;
        };
    
        EdgeData SampleLumaNeighborhood(float2 uv)
        {
            EdgeData ed;
            float2 offset = _MainTex_TexelSize.xy;
    
            ed.m = Luminance(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv).rgb);
            ed.n = Luminance(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2(0,  offset.y)).rgb);
            ed.e = Luminance(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2(offset.x, 0)).rgb);
            ed.s = Luminance(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv - float2(0,  offset.y)).rgb);
            ed.w = Luminance(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv - float2(offset.x, 0)).rgb);
    
            ed.highest = max(max(max(max(ed.n, ed.e), ed.s), ed.w), ed.m);
            ed.lowest = min(min(min(min(ed.n, ed.e), ed.s), ed.w), ed.m);
            ed.contrast = ed.highest - ed.lowest;
            return ed;
        }
    
        float4 FXAA_Pass(float2 uv)
        {
            // 參數配置
            float edgeThresholdMin = 0.03125;
            float edgeThreshold = 0.125;
            float subpixelBlend = 0.75;
    
            EdgeData ed = SampleLumaNeighborhood(uv);
    
            // 邊緣檢測條件
            if(ed.contrast < max(edgeThresholdMin, ed.highest * edgeThreshold))
                return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
    
            // 計算混合方向
            float horizontal = abs(ed.n + ed.s - 2.0 * ed.m) * 2.0 + 
                              abs(ed.e + ed.w - 2.0 * ed.m);
            float vertical = abs(ed.e + ed.w - 2.0 * ed.m) * 2.0 + 
                            abs(ed.n + ed.s - 2.0 * ed.m);
    
            bool isHorizontal = horizontal >= vertical;
    
            // 邊緣端點檢測
            float2 edgeDir = isHorizontal ? 
                float2(0, _MainTex_TexelSize.y) : 
                float2(_MainTex_TexelSize.x, 0);
    
            // 5-tap混合
            float3 rgbA = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv - edgeDir * 0.5).rgb;
            float3 rgbB = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + edgeDir * 0.5).rgb;
            float3 rgbC = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv - edgeDir).rgb;
            float3 rgbD = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + edgeDir).rgb;
    
            // 加權混合
            float blendFactor = 0.5 * (Luminance(rgbA) + Luminance(rgbB)) - Luminance(ed.m);
            blendFactor = saturate(blendFactor / ed.contrast) * subpixelBlend;
    
            float3 finalColor = lerp(
                lerp(rgbC, rgbD, 0.5),
                lerp(rgbA, rgbB, 0.5),
                blendFactor
            );
    
            return float4(finalColor, 1.0);
        }
    
        ENDHLSL
    
        SubShader
        {
            Pass
            {
                Name "FXAA"
                HLSLPROGRAM
                #pragma vertex Vert
                #pragma fragment Frag
    
                struct Attributes {
                    float4 positionOS : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct Varyings {
                    float4 positionCS : SV_POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                Varyings Vert(Attributes input)
                {
                    Varyings output;
                    output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                    output.uv = input.uv;
                    return output;
                }
    
                float4 Frag(Varyings input) : SV_Target
                {
                    return FXAA_Pass(input.uv);
                }
                ENDHLSL
            }
        }
    }
    

?優勢?:

  • 性能消耗最低(僅需1次全屏采樣)
  • 兼容所有GPU架構?

劣勢?:

  • 導致畫面整體模糊(尤其影響高光區域)
  • 無法處理時間性鋸齒(如動態物體)?

限制?:

  • 不適用于HDRP的延遲渲染管線?

子像素形態抗鋸齒(SMAA)

分三(san)階段實現:邊(bian)(bian)緣(yuan)(yuan)檢(jian)測(基(ji)于顏色/深度差)、權(quan)重(zhong)計(ji)算(分析(xi)邊(bian)(bian)緣(yuan)(yuan)模式)、混合執行(沿邊(bian)(bian)緣(yuan)(yuan)方向(xiang)(xiang)插值)。相比FXAA能保留更(geng)多高頻細節,通過(guo)形態學處理(li)識別像素級邊(bian)(bian)緣(yuan)(yuan)走向(xiang)(xiang)。

核心原理流程

  • ?邊緣檢測階段?:使(shi)用Sobel算子分析像素亮度(du)梯度(du),生成(cheng)邊(bian)(bian)緣(yuan)紋理(分為水平和(he)垂直邊(bian)(bian)緣(yuan))

  • ?權重計算階段?:通過AreaTex和SearchTex分(fen)析邊緣形(xing)態(L形(xing)/T形(xing)/對(dui)角線),計算混合權重

  • ?混合執行階段?:根據權(quan)重對邊緣像素進(jin)行雙線性插值混合,保(bao)留高頻細節

  • SMAA.hlsl

    • 關鍵實現解析
      • ?三階段架構?:需創建三個獨立Pass分別對應邊緣檢測、權重計算和混合階段
      • ?紋理資源?:依賴預計算的AreaTex(存儲混合模式)和SearchTex(存儲搜索方向),需導入為Texture2D資源
      • ?動態閾值?:采用相對亮度差(0.1閾值)檢測邊緣,避免固定閾值導致的過檢測
    • URP集成要點
      • ?RenderPass配置?:在URP Renderer中按順序添加三個RenderFeature
      • ?紋理綁定?:通過_AreaTex_SearchTex參數傳遞預計算紋理
      • ?性能優化?:使用linear_clamp_sampler減少紋理采樣開銷
    // 邊緣檢測階段
    Texture2D _MainTex;
    Texture2D _BlendTex;
    SamplerState linear_clamp_sampler;
    
    // 預計算紋理
    Texture2D _AreaTex; // 存儲混合模式(512x512)
    Texture2D _SearchTex; // 存儲搜索方向(64x16)
    
    struct EdgeData {
        float2 uv;
        float4 offsets[3];
    };
    
    EdgeData SMAAEdgeDetectionVS(float4 position : POSITION, float2 uv : TEXCOORD0) {
        EdgeData output;
        output.uv = uv;
        float4 texelSize = _MainTex_TexelSize.xyxy * float4(1.0, 1.0, -1.0, -1.0);
        output.offsets[0] = uv.xyxy + texelSize.xyxy * float4(-1.0, 0.0, 0.0, -1.0);
        output.offsets[1] = uv.xyxy + texelSize.xyxy * float4(1.0, 0.0, 0.0, 1.0);
        output.offsets[2] = uv.xyxy + texelSize.xyxy * float4(-2.0, 0.0, 0.0, -2.0);
        return output;
    }
    
    float4 SMAAColorEdgeDetectionPS(EdgeData input) : SV_Target {
        float L = Luminance(_MainTex.Sample(linear_clamp_sampler, input.uv).rgb);
        float delta1 = Luminance(_MainTex.Sample(linear_clamp_sampler, input.offsets[0].xy).rgb) - L;
        float delta2 = L - Luminance(_MainTex.Sample(linear_clamp_sampler, input.offsets[0].zw).rgb);
        float2 edges = step(float2(0.1, 0.1), abs(float2(delta1, delta2)));
        return float4(edges, 0.0, 1.0);
    }
    
    // 權重計算階段
    float4 SMAABlendingWeightCalculationPS(EdgeData input) : SV_Target {
        float2 area = _AreaTex.Sample(linear_clamp_sampler, input.uv).rg;
        float2 search = _SearchTex.Sample(linear_clamp_sampler, input.uv).rg;
        float4 weights = float4(area.r, area.g, search.r, search.g);
        return weights;
    }
    
    // 混合階段
    float4 SMAANeighborhoodBlendingPS(EdgeData input) : SV_Target {
        float4 weights = _BlendTex.Sample(linear_clamp_sampler, input.uv);
        float3 color = _MainTex.Sample(linear_clamp_sampler, input.uv).rgb;
        float3 color1 = _MainTex.Sample(linear_clamp_sampler, input.uv + float2(weights.r, 0.0)).rgb;
        float3 color2 = _MainTex.Sample(linear_clamp_sampler, input.uv + float2(0.0, weights.g)).rgb;
        return float4(lerp(color, (color1 + color2) * 0.5, weights.b), 1.0);
    }
    

?實現原理?:

分三階段處理:

  • ?邊緣檢測?:基于顏色/深度梯度識別鋸齒邊緣
  • ?模式分析?:通過形態學算法(如腐蝕/膨脹)確定邊緣走向
  • ?像素混合?:沿檢測到的邊緣方向插值(如斜線邊緣按45°方向混合)?

優勢?:

  • 保留更多高頻細節(如UI文字銳度)
  • 性能消耗僅為MSAA的1/3?

劣勢?:

  • 對復雜光照鋸齒(如SSR反射)效果有限?

限制?:

  • 需URP 12.0+版本支持?

多重采樣抗鋸齒(MSAA)

在(zai)光柵化階段對(dui)(dui)每個(ge)像素(su)進(jin)行多重采樣(yang)(2x/4x/8x),計算(suan)覆蓋(gai)率和深度(du)值后合并樣(yang)本。僅對(dui)(dui)幾何邊緣有效,通(tong)過硬件加(jia)速實現物理(li)級抗鋸(ju)齒(chi),但對(dui)(dui)著色鋸(ju)齒(chi)無效且消耗(hao)顯存帶寬。

實現原理?:

在(zai)光柵化(hua)階段對每個像(xiang)素進行多重采樣(yang)(如4x MSAA采樣(yang)4個深度/顏色值),合(he)并時通過(guo)權重計算平滑邊緣。例如,三角形邊緣像(xiang)素會混合(he)部分覆蓋的樣(yang)本?。

核心原理流程

  • ?多重采樣階段?:硬件在光(guang)柵化時對每個(ge)像素生(sheng)成多(duo)個(ge)子樣(yang)本(2x/4x/8x),分別計算深度(du)和模板值

  • ?樣本合并階段?:通過加(jia)權平(ping)均子樣(yang)本(ben)顏(yan)色值生成最終像素輸(shu)出,平(ping)滑幾何(he)邊緣鋸齒

  • ?深度一致性檢測?:自(zi)動處(chu)理(li)子樣本間的深度差異,保留銳利(li)幾何(he)輪(lun)廓

  • MSAA_URP.shader

    • 實現解析
      • ?硬件級集成?:MSAA通過#pragma multi_compile指令激活GPU硬件支持,無需手動實現采樣邏輯
      • ?深度處理優化?:自動處理子樣本間的深度差異,保留幾何邊緣銳度
      • ?光照兼容性?:演示與URP光照系統的無縫集成,陰影計算同樣受益于MSAA
    • URP配置要點
      • ?質量設置?:在URP Asset中啟用MSAA(2x/4x/8x)
      • ?渲染目標?:需使用支持MSAA的RenderTexture格式(如RenderTextureFormat.DefaultHDR
      • ?性能考量?:4x MSAA在移動端TBR架構上性能損耗較低,適合高端移動設備
    Shader "Universal Render Pipeline/MSAA"
    {
        Properties
        {
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
    
        SubShader
        {
            Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }
    
            Pass
            {
                Name "MSAA_Pass"
                HLSLPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
                #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
                #pragma multi_compile _ _ADDITIONAL_LIGHTS
                #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
                #pragma multi_compile _ _SHADOWS_SOFT
    
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    
                struct Attributes
                {
                    float4 positionOS : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct Varyings
                {
                    float4 positionCS : SV_POSITION;
                    float2 uv : TEXCOORD0;
                    float3 positionWS : TEXCOORD1;
                };
    
                TEXTURE2D(_MainTex);
                SAMPLER(sampler_MainTex);
    
                Varyings vert(Attributes input)
                {
                    Varyings output;
                    VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
                    output.positionCS = vertexInput.positionCS;
                    output.uv = input.uv;
                    output.positionWS = vertexInput.positionWS;
                    return output;
                }
    
                half4 frag(Varyings input) : SV_Target
                {
                    // 硬件自動處理MSAA采樣
                    half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
    
                    // 光照計算(演示MSAA與光照的兼容性)
                    Light mainLight = GetMainLight();
                    float3 N = normalize(cross(ddy(input.positionWS), ddx(input.positionWS)));
                    float diffuse = saturate(dot(N, mainLight.direction));
                    return color * (diffuse * mainLight.color + mainLight.shadowAttenuation);
                }
                ENDHLSL
            }
        }
    }
    

?優勢?:

  • 物理級抗鋸齒(對幾何邊緣效果最佳)
  • 支持硬件加速(如DX12的MSAA優化)?

劣勢?:

  • 顯存帶寬消耗高(8x MSAA增加50%帶寬)
  • 對著色器鋸齒無效(如紋理過濾)?

限制?:

  • 需關閉(bi)URP的延遲渲染(ran)功能?

    | 特性 | MSAA | FXAA/SMAA |
    | --- | --- | --- |
    | 處理階段 | 光柵化階段 | 后處理階段 |
    | 效果范圍 | 僅幾何邊緣 | 全圖像 |
    | 性能消耗 | 中-高(取決于采樣數) | 低-中 |
    | 兼容(rong)性(xing) | 需硬件支持 | 全平臺通用 |

時間抗鋸齒(TAA)

利用歷史幀數(shu)據和運(yun)動(dong)向量,將(jiang)當前(qian)幀與前(qian)一幀抗鋸齒結果進行時域(yu)混合。通(tong)過重投影(ying)技術(shu)解決動(dong)態物(wu)體問題,需配合動(dong)態模(mo)糊抑制重影(ying)現(xian)象,對(dui)動(dong)態場景效果最佳。

?實現原理?:

利用歷史幀數據(運動向量+深度緩沖)進行時域(yu)混合:

  • ?重投影?:將當前幀與歷史幀對齊
  • ?抖動補償?:通過隨機抖動減少重影
  • ?累積濾波?:加權融合多幀結果?

核心原理流程

  • ?幀間抖動采樣?:通過Halton序列對投影矩陣施加微小偏移,使采樣點在時間維度上均勻分布
  • ?運動向量追蹤?:利用_CameraMotionVectorsTexture記錄像素位移,結合深度紋理處理邊緣運動
  • ?歷史幀混合?:通過線性插值(lerp)將當前幀與歷史緩沖數據融合,動態調整混合權重
  • TAA.shader
    • 關鍵技術解析

      • ?運動向量處理?:通過_CameraMotionVectorsTexture獲取像素位移,確保歷史幀采樣位置準確
      • ?動態混合策略?:基于運動向量長度調整混合權重,靜態區域權重低(保留更多歷史數據),動態區域權重高(減少拖影)
      • ?投影矩陣抖動?:在C#腳本中修改相機投影矩陣實現Halton序列偏移,需配合UNITY_MATRIX_PREV_VP矩陣使用
    • URP集成要點

      • ?RenderFeature配置?:需創建TAARenderFeature并設置執行時機為RenderPassEvent.BeforeRenderingPostProcessing
      • ?雙緩沖歷史紋理?:使用兩個RenderTexture交替存儲歷史幀數據,避免讀寫沖突
      • ?運動向量生成?:需為動態物體添加MotionVector Pass,靜態物體可直接使用相機運動矩陣
    • 性能優化建議

      • ?分辨率降采樣?:對歷史緩沖使用半分辨率紋理(需配合雙線性濾波)
      • ?邊緣銳化后處理?:在TAA后添加FXAA或自定義銳化Pass補償過度模糊
      • ?移動端適配?:將運動向量計算移至頂點著色器,減少Fragment計算量
      • 該方案相比SMAA能有效減少次像素閃爍,特別適合處理動態植被和細小網格的鋸齒問題。實際部署時需注意處理透明物體的運動向量生成問題
      Shader "Universal Render Pipeline/TAA"
      {
          Properties
          {
              _MainTex("Base (RGB)", 2D) = "white" {}
              _HistoryTex("History Buffer", 2D) = "black" {}
          }
      
          HLSLINCLUDE
          #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
      
          TEXTURE2D(_MainTex);
          TEXTURE2D(_HistoryTex);
          TEXTURE2D(_CameraMotionVectorsTexture);
          SAMPLER(sampler_linear_clamp);
      
          struct Varyings
          {
              float4 positionCS : SV_POSITION;
              float2 uv : TEXCOORD0;
          };
      
          // Halton序列生成抖動偏移
          float2 GetJitterOffset(uint frameIndex)
          {
              const float2 seq = float2(
                  0.5f * (frameIndex % 8 + 1) / 8.0f,
                  0.5f * (frameIndex % 16 + 1) / 16.0f
              );
              return (seq - 0.5f) * _ScreenParams.zw;
          }
      
          Varyings Vert(uint vertexID : SV_VertexID)
          {
              Varyings output;
              output.positionCS = GetFullScreenTriangleVertexPosition(vertexID);
              output.uv = GetFullScreenTriangleTexCoord(vertexID);
              return output;
          }
      
          float4 Frag(Varyings input) : SV_Target
          {
              // 獲取運動向量
              float2 motion = SAMPLE_TEXTURE2D(_CameraMotionVectorsTexture, sampler_linear_clamp, input.uv).xy;
      
              // 采樣當前幀和歷史幀
              float3 current = SAMPLE_TEXTURE2D(_MainTex, sampler_linear_clamp, input.uv).rgb;
              float3 history = SAMPLE_TEXTURE2D(_HistoryTex, sampler_linear_clamp, input.uv - motion).rgb;
      
              // 動態混合權重(基于運動向量長度)
              float blendFactor = saturate(length(motion) * 10.0f);
              return float4(lerp(history, current, blendFactor), 1.0);
          }
          ENDHLSL
      
          SubShader
          {
              Pass
              {
                  Name "TAA_Pass"
                  HLSLPROGRAM
                  #pragma vertex Vert
                  #pragma fragment Frag
                  ENDHLSL
              }
          }
      }
      

優勢?:

  • 動態場景抗鋸齒效果最佳(如快速移動的物體)
  • 支持復雜光照(如HDRP的全局光照)?

劣勢?:

  • 極端情況下出現重影(如快速切換場景)?

限制?:

  • 需啟用運動向量(Motion Vectors)
  • 不兼容動態分辨率?

URP中的選擇策略

性能優先場景

選擇FXAA:移動端或VR項目(mu)需(xu)保持60FPS時(shi),其性(xing)能消(xiao)耗(hao)僅為SMAA的60%。

畫質優先場景

  • 靜態場景:MSAA 4x/8x(需關閉延遲渲染)
  • 動態場景:TAA(需啟用運動向量)
  • 風格化渲染:SMAA(保留清晰邊緣)

特殊配置建議

  • WebGL項目:避免MSAA(內存限制),推薦SMAA
  • VR項目:FXAA+TAA組合減少動態模糊
  • HDRP管線:優先TAA解決復雜光照鋸齒

技術決策矩陣:

指標 FXAA SMAA MSAA TAA
幾何邊緣
著色鋸齒 無效
動態場景
GPU消耗 1x 1.5x 3-8x 2x
顯存占用

注:消耗基準以FXAA為1x計算


專欄-直達
(歡迎點贊留言探討,更(geng)多(duo)人加(jia)入(ru)進來能更(geng)加(jia)完善這個探索的(de)過程,??)

posted @ 2025-10-30 08:26  SmalBox  閱讀(64)  評論(0)    收藏  舉報