<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

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

      【從UnityURP開始探索游戲渲染】專欄-直達

      歷史發展節點

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

      抗鋸齒技術實現原理

      快速近似抗鋸齒(FXAA)

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

      ?實現原理?:

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

      核心流程?:

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

      • 邊緣檢測:對比3x3區域內像素亮度差,超過閾值則標記為邊緣

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

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

      • 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)

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

      核心原理流程

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

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

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

      • 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)

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

      實現原理?:

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

      核心原理流程

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

      • ?樣本合并階段?:通過加權平均子樣本顏色值生成最終像素輸出,平滑幾何邊緣鋸齒

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

      • 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%帶寬)
      • 對著色器鋸齒無效(如紋理過濾)?

      限制?:

      • 需關閉URP的延遲渲染功能?

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

      時間抗鋸齒(TAA)

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

      ?實現原理?:

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

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

      核心原理流程

      • ?幀間抖動采樣?:通過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項目需保持60FPS時,其性能消耗僅為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計算


      【從UnityURP開始探索游戲渲染】專欄-直達
      (歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,??)

      posted @ 2025-10-30 08:26  SmalBox  閱讀(82)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 鄂州市| 亚洲永久一区二区三区在线| 欧美视频专区一二在线观看| 四虎在线永久免费看精品| 亚洲中文字幕日产无码成人片| 成人午夜av在线播放| 国产精品一区中文字幕| 人人做人人妻人人精| 玛沁县| 影音先锋啪啪av资源网站| 久久精品夜夜夜夜夜久久| 狠狠噜天天噜日日噜视频麻豆 | 青草热在线观看精品视频| 成人AV专区精品无码国产| 亚洲日产韩国一二三四区| 国产成人无码综合亚洲日韩| 女同在线观看亚洲国产精品| 亚洲AV国产福利精品在现观看| 人妻少妇无码精品专区| 亚洲色大成网站www永久男同 | 国产日韩av二区三区| 久热伊人精品国产中文| 色综合久久久久综合体桃花网| 乱女乱妇熟女熟妇综合网| 色午夜一av男人的天堂| 开心五月深深爱天天天操| 中文有无人妻vs无码人妻激烈| 99RE8这里有精品热视频| 成人毛片100免费观看| 国产日韩精品视频无码| 熟妇人妻中文a∨无码| 中文字幕有码日韩精品| 国产日韩精品中文字幕| 在线免费播放av观看| 国产精品乱码人妻一区二区三区| 精品乱人伦一区二区三区| 拜城县| 亚洲精品日韩在线观看| 国产精品久久久久久久久久直播| 久久精品人人做人人爽97| 亚洲男人在线天堂|