{"id":266,"date":"2024-10-30T02:18:12","date_gmt":"2024-10-29T18:18:12","guid":{"rendered":"http:\/\/chenglixue.top\/?p=266"},"modified":"2024-10-30T02:19:43","modified_gmt":"2024-10-29T18:19:43","slug":"unity-stochastic-screen-space-reflections","status":"publish","type":"post","link":"http:\/\/chenglixue.top\/?p=266","title":{"rendered":"unity Stochastic Screen Space Reflections"},"content":{"rendered":"<h1>\u4e3a\u4ec0\u4e48\u9700\u8981SSSR?<\/h1>\n<p>\u5728\u5b9e\u65f6\u6e32\u67d3\u4e2d\u53cd\u5c04\u624b\u6bb5\u7ecf\u5e38\u7528\u5230\u7684\u53cd\u5c04\u63a2\u9488\uff0c\u8fd9\u79cd\u65b9\u6cd5\u975e\u5e38\u8282\u7701\u6027\u80fd\uff0c\u4f46\u5b83\u4e5f\u5b58\u5728\u4e00\u5b9a\u7684\u95ee\u9898\u2014\u2014\u5373<strong>\u4ece\u4e0d\u540c\u89c6\u89d2\u770b\u5411\u540c\u4e00\u5730\u65b9\uff0c\u6240\u770b\u5230\u7684\u53cd\u5c04\u5185\u5bb9\u662f\u4e0d\u540c\u7684<\/strong>\u3002\u8fd9\u5c31\u5bfc\u81f4\u53ef\u80fd\u4f1a\u770b\u5230\u9519\u8bef\u7684\u53cd\u5c04\u6548\u679c<br \/>\n<img decoding=\"async\"   class=\"lazyload\" data-src=\"https:\/\/pic.imgdb.cn\/item\/671a794dd29ded1a8c484719.png\" src=\"https:\/\/cdn.jsdelivr.net\/gh\/moezx\/cdn@3.0.2\/img\/svg\/loader\/trans.ajax-spinner-preloader.svg\" onerror=\"imgError(this)\"  alt=\"\" \/><\/p >\n<noscript><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/671a794dd29ded1a8c484719.png\" alt=\"\" \/><\/p><\/noscript>\n<h1>\u4ec0\u4e48\u662fSSSR?<\/h1>\n<ul>\n<li>SSSR = SSR + PBR<\/li>\n<\/ul>\n<p>\u5728IBL\u4e2d\uff0c\u4f1a\u7528\u5230cube map\u6765\u5b9e\u73b0\u9ad8\u5149\u7684\u53cd\u5c04\uff1b\u800c\u5728SSSR\u4e2d\uff0c\u4f1a\u5728SSR\u7684\u57fa\u7840\u4e0a\u914d\u5408\u5c4f\u5e55\u7a7a\u95f4\uff0c\u6765\u5b9e\u73b0\u53cd\u5c04<\/p>\n<h1>\u7279\u70b9<\/h1>\n<ul>\n<li>\u652f\u6301\u6e05\u6670\u548c\u6a21\u7cca\u53cd\u5c04<\/li>\n<li>\u8d8a\u8fd1\u53cd\u5c04\u8d8a\u6e05\u6670<\/li>\n<li>\u9ad8\u5149\u62c9\u4f38<\/li>\n<\/ul>\n<h1>SSR<\/h1>\n<p>\u5173\u4e8eSSR\uff0c\u7b14\u8005\u5728\u5148\u524d\u7684Blog\u4e2d\u5df2\u7ecf\u4ecb\u7ecd\u8fc7\uff0c\u4e0d\u61c2\u7684\u53ef\u4ee5\u770b\u8fd9\u54e6<a class=\"wp-editor-md-post-content-link\" href=\"http:\/\/chenglixue.top\/?p=224\">unity \u5c4f\u5e55\u7a7a\u95f4\u53cd\u5c04(Screen Space Reflect)<\/a><\/p>\n<p>SSR\u501f\u7528IBL\u7684\u601d\u8def\uff0c\u5bf9\u53cd\u5c04\u5185\u5bb9\u57fa\u4e8eroughness\u91c7\u6837mipmap\uff0c\u8fd9\u6837\u7684\u65b9\u5f0f\u662f\u975ePBR\u7684\uff0c\u4f1a\u5bfc\u81f4\u5f97\u5230\u7684\u53cd\u5c04\u56fe\u50cf\u53ef\u80fd\u5b58\u5728\u4e00\u4e9b\u975e\u7269\u7406\u7684\u95ee\u9898\uff1b\u800cSSSR\u867d\u7136\u4e5f\u501f\u7528\u4e86IBL\u7684\u601d\u8def\uff0c\u4f46\u4e0eSSR\u7684\u65b9\u6cd5\u4e0d\u540c\u4e4b\u5904\u5728\u4e8e\uff0cSSSR\u6a21\u7cca\u7684\u662f\u8fdc\u5904\u7684\u5149\u7167\uff0c\u8fd9\u5c31\u4f7f\u5f97\u8ba1\u7b97\u5f97\u5230\u7684\u7ed3\u679c\u662f\u57fa\u4e8e\u7269\u7406\u7684\uff0c\u800c\u975e\u7b80\u5355\u6a21\u7cca\u7684\u6570\u636e<\/p>\n<h1>Hi-Z tracing<\/h1>\n<p>Hi-Z\u5c06\u5c4f\u5e55\u6df1\u5ea6\u7684\u5c42\u6b21\u5173\u7cfb\u5b58\u50a8\u5728MipMap\u5c42\u7ea7\u4e2d\uff0c\u7528\u4e8e\u52a0\u901f\u53cd\u5c04\u5149\u7ebf\u7684\u6c42\u4ea4<\/p>\n<p>Hi-Z\u7684\u6784\u5efa\u65f6\uff0c\u5bf9\u5c4f\u5e55\u5c3a\u5bf8\u7684\u6df1\u5ea6\u8fdb\u884c\u6ee4\u6ce2\uff0c\u6bcf\u6b21\u4fdd\u5b582x2\u50cf\u7d20\u4e2d\u6700\u6d45\u7684\u50cf\u7d20<\/p>\n<p><strong>\u5728\u6bd4\u8f83\u76f8\u673a\u89c6\u89d2\u7684\u573a\u666f\u6df1\u5ea6\u548c\u53cd\u5c04\u5149\u7ebf\u7684\u6df1\u5ea6\u65f6\uff0c\u82e5\u53cd\u5c04\u5149\u7ebf\u7684\u6df1\u5ea6\u5c0f\u4e8e\u573a\u666f\u6df1\u5ea6\uff0cmipMap Level++\uff1b\u82e5\u53cd\u5c04\u5149\u7ebf\u7684\u6df1\u5ea6\u5927\u4e8e\u7b49\u4e8e\u573a\u666f\u6df1\u5ea6\uff0cmipMap Level--\u3002\u968f\u540e\u7ee7\u7eed\u6b65\u8fdb\uff0c\u91cd\u590d\u4e0a\u8ff0\u6b65\u9aa4\uff0c\u76f4\u81f3mipMap Level\u5c0f\u4e8e0\uff0c\u5f53\u524d\u5f97\u5230\u7684\u573a\u666f\u6df1\u5ea6\u5373\u4e3a\u60f3\u8981\u7684<\/strong><\/p>\n<p>\u5b9e\u73b0\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"line-numbers\">#pragma kernel GetHiZ\n\nTexture2D&lt;float4&gt;   _SourceTex;\nRWTexture2D&lt;float4&gt; _RW_OutputTex;\n\n\/\/ xy: last mipmap's texel size;\n\/\/ zw: curr mipmap's texel size\nfloat4 _HiZTexSize;\n\nfloat SampleSourceTex(float2 uv, float2 offset)\n{\n    return _SourceTex.SampleLevel(Smp_ClampU_ClampV_Linear, uv + offset * _HiZTexSize.xy, 0).r;\n}\n\n[numthreads(8,8,1)]\nvoid GetHiZ (uint3 id : SV_DispatchThreadID)\n{\n    float2 uv = (float2(id.xy) + 0.5f) * _HiZTexSize.zw;\n    float minZ = SampleSourceTex(uv, 0);\n    minZ = max(minZ, SampleSourceTex(uv, float2(-1.f, -1.f)));\n    minZ = max(minZ, SampleSourceTex(uv, float2(-1.f, 1.f)));\n    minZ = max(minZ, SampleSourceTex(uv, float2(1.f, 1.f)));\n    minZ = max(minZ, SampleSourceTex(uv, float2(1.f, -1.f)));\n\n    _RW_OutputTex[id.xy] = minZ;\n}\n\n\/\/ \u5148\u5728_HiZDepthRT[0]\u91c7\u6837\u573a\u666f\u6df1\u5ea6\uff0c\u57fa\u4e8e\u8be5\u6df1\u5ea6\u56fe\u751f\u6210Mipmap\nprivate const int _maxMipMapLevels = 7;\nprivate RenderTargetIdentifier[] _HiZDepthRT = new RenderTargetIdentifier[_maxMipMapLevels];\nprivate static int[] _HiZDepthTexID   = new int[_maxMipMapLevels];\n\nvoid DoHizDepth(CommandBuffer cmd, ref RenderingData renderingData, ScriptableRenderContext context, RenderTargetIdentifier targetRT)\n{\n    var computeShader = Resources.Load&lt;ComputeShader&gt;(\"HiZ\/CS_HiZ\");\n    if (computeShader == null) return;\n\n    var tempDesc = _descriptor;\n    tempDesc.enableRandomWrite = true;\n    tempDesc.colorFormat       = RenderTextureFormat.RFloat;\n    tempDesc.useMipMap         = true;\n    tempDesc.autoGenerateMips  = false;\n\n    Vector2Int currTexSize = new Vector2Int(_descriptor.width, _descriptor.height);\n    Vector2Int lastTexSize = currTexSize;\n    var lastHizDepthRT = targetRT;\n\n    for (int i = 1; i &lt; _maxMipMapLevels; ++i)\n    {\n        currTexSize.x \/= 2;\n        currTexSize.y \/= 2;\n\n        tempDesc.width = currTexSize.x;\n        tempDesc.height = currTexSize.y;\n        _HiZDepthTexID[i] = Shader.PropertyToID(\"_HiZDepthTex\" + i);\n        _HiZDepthRT[i]    = new RenderTargetIdentifier(_HiZDepthTexID[i]);\n        cmd.GetTemporaryRT(_HiZDepthTexID[i], tempDesc, FilterMode.Point);\n\n        int kernelID = computeShader.FindKernel(\"GetHiZ\");\n        computeShader.GetKernelThreadGroupSizes(kernelID, out uint x, out uint y, out uint z);\n        cmd.SetComputeTextureParam(computeShader, kernelID, Shader.PropertyToID(\"_SourceTex\"), lastHizDepthRT);\n        cmd.SetComputeTextureParam(computeShader, kernelID, Shader.PropertyToID(\"_RW_OutputTex\"), _HiZDepthRT[i]);\n        cmd.SetComputeVectorParam(computeShader, Shader.PropertyToID(\"_HiZTexSize\"), \n            new Vector4(1f \/ lastTexSize.x, 1f \/ lastTexSize.y, 1f \/ currTexSize.x, 1f \/ currTexSize.y));\n        cmd.DispatchCompute(computeShader, kernelID,\n            Mathf.CeilToInt((float)currTexSize.x \/ x),\n            Mathf.CeilToInt((float)currTexSize.y \/ y),\n            1);\n\n        cmd.CopyTexture(_HiZDepthRT[i], 0, 0,targetRT, 0, i);\n\n        lastTexSize = currTexSize;\n        lastHizDepthRT = _HiZDepthRT[i];\n    }\n\n    for (int i = 1; i &lt; _maxMipMapLevels; ++i)\n    {\n        cmd.ReleaseTemporaryRT(_HiZDepthTexID[i]);\n    }\n}\n<\/code><\/pre>\n<h1>Importance Sampling<\/h1>\n<p>\u4e3a\u4e86\u5f97\u5230\u6a21\u7cca\u7684\u5149\u7167\u7ed3\u679c\uff0c\u4e00\u79cd\u65b9\u6cd5\u662f\u5bf9\u7269\u4f53\u8868\u9762\u7684normal\u6296\u52a8\uff0c\u53e6\u4e00\u79cd\u662f\u5bf9\u53cd\u5c04\u5149\u7ebf\u6296\u52a8\u3002\u5728BRDF\u4e2d\uff0c\u4e0e\u9ad8\u5149\u6548\u679c\u76f4\u63a5\u6302\u94a9\u7684\u662f\u6cd5\u7ebf\u5206\u5e03\u51fd\u6570\uff0c\u5b83\u76f4\u63a5\u8868\u793a\u4e86\u9ad8\u5149\u662f\u6e05\u6670\u8fd8\u662f\u6a21\u7cca\uff0c\u4e3a\u4e86\u5f97\u5230\u66f4\u52a0\u7269\u7406\u7684\u5149\u7167\u6548\u679c\uff0c\u53ef\u4ee5\u4f7f\u7528NDF GGX\u57fa\u4e8eroughness\u6765\u8ba1\u7b97\u7269\u4f53\u8868\u9762\u7684\u5fae\u8868\u9762\u6cd5\u7ebf\uff0c\u4ece\u800c\u8fbe\u5230\u6296\u52a8normal\u7684\u6548\u679c<\/p>\n<p>NDF GGX\u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a\u91cd\u8981\u6027\u91c7\u6837\u51fd\u6570\uff0c\u800c\u91cd\u8981\u6027\u91c7\u6837\u7684\u7cbe\u9ad3\u5728\u4e8e\u6982\u7387\u5bc6\u5ea6\u5206\u5e03\u51fd\u6570\uff0c\u5728\u91cd\u8981\u6027\u91c7\u6837\u5f53\u4e2d\uff0c\u4e3a\u4e86\u903c\u8fd1\u66b4\u529b\u7ed3\u7b97\uff08\u7a77\u4e3e\uff09\uff0c<strong>\u9700\u8981\u7ed9\u5f97\u5230\u7684\u6570\u636e\u4e58\u4ee5\u4e00\u4e2a\u6743\u91cd\uff0c\u6700\u540e\u518d\u52a0\u8d77\u6765\u5f97\u5230\u5e73\u5747\u503c\u4f5c\u4e3a\u6700\u540e\u7684\u91c7\u6837\u7ed3\u679c<\/strong><\/p>\n<p>\u5de5\u4e1a\u754c\u7684NDF GGX\u51fd\u6570\u5982\u4e0b\uff1a<span class=\"katex math multi-line\">D_{GGX}(h) = \\frac{\u03b1^2}{\u03a0((\u03b1^2 - 1)cos^2_{\u03b8_h} + 1)^2}<\/span><\/p>\n<p>\u5176\u4e2d\uff0c<span class=\"katex math inline\">\u03b1<\/span>\u4e3aroughness\uff0c<span class=\"katex math inline\">\u03b8_h<\/span>\u4e3a\u534a\u7a0b\u5411\u91cf\uff08\u5373\u91c7\u6837\u65b9\u5411\uff09\u4e0e\u5b8f\u89c2\u6cd5\u7ebf\u5939\u89d2<\/p>\n<p>\u5bf9\u5e94\u7684PDF\u4e3a\uff1a<span class=\"katex math multi-line\">\\frac{\u03b1^2 cos\u03b8}{\u03a0((\u03b1^2 - 1)cos^2_{\u03b8_h} + 1)^2}<\/span><\/p>\n<p><span class=\"katex math inline\">cos\u03b8 = \\sqrt{\\frac{1 - E}{1 + (\u03b1^2 - 1)E}}<\/span>\uff0c\u5176\u4e2dE\u4e3a[0, 1]\u4e0a\u5747\u5300\u5206\u5e03\u7684\u968f\u673a\u6570<\/p>\n<p>\u6700\u7ec8\u5f97\u5230\u7684\u5fae\u8868\u9762\u6cd5\u7ebf(\u534a\u7a0b\u5411\u91cf)\u4e3a\uff1a<\/p>\n<pre><code class=\"line-numbers\">float3 H;\nH.x = SinTheta * cos(Phi);\nH.y = SinTheta * sin(Phi);\nH.z = CosTheta;\n<\/code><\/pre>\n<p>\u5b9e\u73b0\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"line-numbers\">float4 ImportanceSampleGGX(float2 Xi, float Roughness)\n{\n    float m = Roughness * Roughness;\n    float m2 = m * m;\n\n    float Phi = 2 * PI * Xi.x;\n\n    float CosTheta = sqrt((1.0 - Xi.y) \/ (1.0 + (m2 - 1.0) * Xi.y));\n    float SinTheta = sqrt(max(1e-5, 1.0 - CosTheta * CosTheta));\n\n    \/\/ \u534a\u7a0b\u5411\u91cf(\u91c7\u6837\u65b9\u5411)\n    float3 H;\n    H.x = SinTheta * cos(Phi);\n    H.y = SinTheta * sin(Phi);\n    H.z = CosTheta;\n\n    float d = (CosTheta * m2 - CosTheta) * CosTheta + 1;\n    float D = m2 \/ (PI * d * d);\n    float pdf = D * CosTheta;\n\n    return float4(H, pdf);\n}\n<\/code><\/pre>\n<h1>Multi sample<\/h1>\n<p>\u5f53\u91cd\u8981\u6027\u91c7\u6837\u79ef\u5206\u6b21\u6570\u4e0d\u591f\u4f1a\u5bfc\u81f4\u566a\u70b9\u8fc7\u591a\uff0c\u5982\u4f55\u964d\u566a\u5462\uff1f\u5f53\u8ba1\u7b97\u51fa\u53cd\u5c04\u5149\u7ebf\u4e0e\u573a\u666f\u4ea4\u53c9\u65f6\uff0c\u53ef\u4ee5\u7528\u5b83\u76f8\u90bb\u7684uv\u6570\u636e\u5047\u88c5\u6210\u5b83\u53d1\u5c04\u7684\u5149\u7ebf\uff0c\u4ece\u800c\u5f97\u5230\u66f4\u591a\u7684\u6837\u672c<br \/>\n<img decoding=\"async\"   class=\"lazyload\" data-src=\"https:\/\/pic.imgdb.cn\/item\/671a9b85d29ded1a8c601412.png\" src=\"https:\/\/cdn.jsdelivr.net\/gh\/moezx\/cdn@3.0.2\/img\/svg\/loader\/trans.ajax-spinner-preloader.svg\" onerror=\"imgError(this)\"  alt=\"\" \/><\/p >\n<noscript><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/671a9b85d29ded1a8c601412.png\" alt=\"\" \/><\/p><\/noscript>\n<p>\u5b9e\u73b0\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"line-numbers\">static const int2 offset[9] =\n{\n    int2(-2.0, -2.0),\n    int2(0.0, -2.0),\n    int2(2.0, -2.0),\n    int2(-2.0, 0.0),\n    int2(0.0, 0.0),\n    int2(2.0, 0.0),\n    int2(-2.0, 2.0),\n    int2(0.0, 2.0),\n    int2(2.0, 2.0)\n}; \nfloat2 ditherUV     = fmod(i.positionCS.xy, 4);\nfloat2 jitter       = _BlueNoiseTex.SampleLevel(Smp_ClampU_ClampV_Linear, ditherUV \/ 4.f + float2(0.5 \/ 4.f, 0.5f \/ 4.f), 0).xy;\nfloat2x2 offsetRotationMat = float2x2(jitter.x, jitter.y, -jitter.y, -jitter.x);\n\n\/\/ \u504f\u79fbuv\uff0c\u590d\u7528\u53cd\u5c04\u6570\u636e\nfor(int i = 0; i &lt; 4; ++i)\n{\n    float2 offsetUV         = mul(offsetRotationMat, offset[i] * _ResolvedTexSize.zw);\n    float2 neighborUV       = uv + offsetUV;\n\n    float4 hitData          = _SSRHitData.SampleLevel(Smp_ClampU_ClampV_Linear, neighborUV, 0);\n    float2 hitUV            = hitData.rg;\n    float  hitZ             = hitData.b;\n    float  pdf              = hitData.a;\n    float4 hitPositionCS    = GetPositionCS(hitUV, hitZ);\n    float4 hitPositionVS    = GetPositionVS(hitPositionCS);\n\n    \/\/...\n}\n<\/code><\/pre>\n<p>\u4f46Multi sample\u4e5f\u5b58\u5728\u4e00\u5b9a\u7684\u95ee\u9898\uff1a\u56e0\u4e3a\u5404\u4e2a\u70b9\u7684PDF\u662f\u4e0d\u540c\u7684\u3002<strong>\u82e5\u51e0\u4e2a\u70b9\u7684<span class=\"katex math inline\">\u03b8_h<\/span>\u4e3a\u534a\u7a0b\u5411\u91cf\uff08\u5373\u91c7\u6837\u65b9\u5411\uff09\u4e0e\u5b8f\u89c2\u6cd5\u7ebf\u5939\u89d2\u5dee\u5f02\u8f83\u5927\uff0c\u5f97\u5230\u7684PDF\u7684\u5dee\u5f02\u4e5f\u4f1a\u8f83\u5927<\/strong>\uff0c\u90a3\u4e48\u53cd\u5c04\u7ed3\u679c\u5c31\u5b58\u5728\u566a\u70b9<\/p>\n<p>\u4e3a\u4e86\u907f\u514d\u5f53\u4fef\u89d2\u5dee\u5f02\u8fc7\u5927\u5bfc\u81f4\u7684PDF\u5dee\u5f02\u8fc7\u5927\uff0c\u53ef\u4ee5\u5bf9\u968f\u673a\u6570\u8fdb\u884c\u622a\u65ad(\u622a\u65ad\u8f83\u5c0f\u7684\u503c)\u5e76\u91cd\u6620\u5c04\uff0c\u8fdb\u800c\u5f97\u5230\u66f4\u4e3a\u5e73\u7f13\u7684PDF\u503c<\/p>\n<p><img decoding=\"async\"   class=\"lazyload\" data-src=\"https:\/\/pic.imgdb.cn\/item\/671aa404d29ded1a8c640c52.png\" src=\"https:\/\/cdn.jsdelivr.net\/gh\/moezx\/cdn@3.0.2\/img\/svg\/loader\/trans.ajax-spinner-preloader.svg\" onerror=\"imgError(this)\"  alt=\"\" \/><\/p >\n<noscript><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/671aa404d29ded1a8c640c52.png\" alt=\"\" \/><\/p><\/noscript>\n<p>\u5b9e\u73b0\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"line-numbers\">float2 ditherUV = fmod(i.positionCS.xy, 4);\nfloat2 jitter = _BlueNoiseTex.SampleLevel(Smp_ClampU_ClampV_Linear, ditherUV \/ 4.f + float2(0.5 \/ 4.f, 0.5f \/ 4.f), 0).xy;\njitter.y = lerp(jitter.y, 0.f, _BRDFBias);\n\nfloat4 halfVector = TransformTangentToView(normalWS, ImportanceSampleGGX(jitter, 1 - smoothness));\n<\/code><\/pre>\n<h1>Patiofilter<\/h1>\n<p>\u65e2\u7136\u95ee\u9898\u51fa\u5728\u6cd5\u7ebf\uff0c\u90a3\u4e48\u5bf9\u8fd9\u5757\u533a\u57df\u6c42\u5e73\u5747\u53ef\u4ee5\u5417\uff1f\u7b54\u6848\u662f\u53ef\u4ee5\u7684\uff0c\u8fd9\u4e5f\u5c31\u662f\u7a7a\u95f4\u6ee4\u6ce2(Patiofilter)\u7684\u89e3\u51b3\u601d\u8def<\/p>\n<p>\u4f2a\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\"   class=\"lazyload\" data-src=\"https:\/\/pic.imgdb.cn\/item\/671a9e71d29ded1a8c6178a5.png\" src=\"https:\/\/cdn.jsdelivr.net\/gh\/moezx\/cdn@3.0.2\/img\/svg\/loader\/trans.ajax-spinner-preloader.svg\" onerror=\"imgError(this)\"  alt=\"\" \/><\/p >\n<noscript><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/671a9e71d29ded1a8c6178a5.png\" alt=\"\" \/><\/p><\/noscript>\n<h1>Temporalfilter<\/h1>\n<p>\u65e2\u7136\u7a7a\u95f4\u4e0a\u53ef\u4ee5\u590d\u7528\u5c04\u7ebf\uff0c\u65f6\u95f4\u4e0a\u53ef\u4ee5\u5417\uff1f\u5f53\u7136\u53ef\u4ee5\uff0c\u4e5f\u5c31\u662f\u5e38\u7528\u5230\u7684TAA\uff0c\u5373\u5b58\u50a8\u524dN\u5e27\u7684\u53cd\u5c04\u6570\u636e\uff0c\u5728\u5f53\u524d\u5e27\u548c\u524dN\u5e27\u7684\u53cd\u5c04\u6570\u636elerp\u5373\u53ef<\/p>\n<pre><code class=\"line-numbers\">void Temporalfilter(PSInput i, out PSOutput o)\n{\n    float2 uv = i.uv;\n    float  hitDepth = _SSRHitData.SampleLevel(Smp_ClampU_ClampV_Linear, uv, 0).b;\n    float roughness = GetRoughness(GetSmoothness(uv));\n    float3 normalWS = GetNormalWS(uv);\n\n    float2 depthVelocity  = _MotionVectorTexture.SampleLevel(Smp_ClampU_ClampV_Linear, uv, 0).rg;\n    float2 rayVelocity    = GetCameraMotionVector(1 - hitDepth, uv, Matrix_I_VP, _Pre_Matrix_VP, Matrix_VP);\n    float Velocity_Weight = saturate(dot(normalWS, float3(0, 1, 0)));\n    float2 velocity = lerp(depthVelocity, rayVelocity, Velocity_Weight);\n\n    float2 du = float2(_TAATexSize.z, 0);\n    float2 dv = float2(0, _TAATexSize.w);\n\n    float4 minColor = 1e10, maxColor = 0;\n    for(int i = -1; i &lt;= 1; ++i)\n    {\n        for(int j = -1; j &lt;= 1; ++j)\n        {\n            float4 currColor = _ResolvedTex.SampleLevel(Smp_ClampU_ClampV_Linear, uv + du * i + dv * j, 0);\n            minColor = min(minColor, currColor);\n            maxColor = max(maxColor, currColor);\n        }\n    }\n    float4 averageColor = (minColor + maxColor) * 0.5f;\n    minColor = (minColor - averageColor) * _TAAScale + averageColor;\n    maxColor = (maxColor - averageColor) * _TAAScale + averageColor;\n\n    float4 TAAPreColor = _TAAPreTex.SampleLevel(Smp_ClampU_ClampV_Linear, uv - velocity, 0);\n    TAAPreColor = clamp(TAAPreColor, minColor, maxColor);\n    float4 TAACurrColor = _ResolvedTex.SampleLevel(Smp_ClampU_ClampV_Linear, uv, 0);\n\n    float TAAWeight = 0.f;\n    if(roughness &gt; 0.1)\n    {\n        TAAWeight = _TAAWeight;\n    }\n    else\n    {\n        TAAWeight = 0.92f;\n    }\n\n    float weight = saturate(clamp(0, 0.96f, TAAWeight) * (1.f - length(velocity) * 8));\n    float4 reflectColor = lerp(TAACurrColor, TAAPreColor, weight);\n\n    o.color = reflectColor;\n}\n<\/code><\/pre>\n<h1>\u964d\u91c7\u6837<\/h1>\n<p>\u60f3\u8981\u8fdb\u4e00\u6b65\u4f18\u5316\u6027\u80fd\uff0c\u53ef\u4ee5\u5bf9Render Target\u8fdb\u884c\u964d\u91c7\u6837<\/p>\n<h1>\u6700\u7ec8\u6548\u679c<\/h1>\n<p><img decoding=\"async\"   class=\"lazyload\" data-src=\"https:\/\/pic.imgdb.cn\/item\/67211d34d29ded1a8c8e1d2c.png\" src=\"https:\/\/cdn.jsdelivr.net\/gh\/moezx\/cdn@3.0.2\/img\/svg\/loader\/trans.ajax-spinner-preloader.svg\" onerror=\"imgError(this)\"  alt=\"\" \/><\/p >\n<noscript><img decoding=\"async\" src=\"https:\/\/pic.imgdb.cn\/item\/67211d34d29ded1a8c8e1d2c.png\" alt=\"\" \/><\/p><\/noscript>\n<p>\u57281k\u6e05\u6670\u5ea6\u4e0b\uff0c\u964d\u91c7\u68374\u500d\uff0c\u6027\u80fd\u6d88\u8017\uff1a1.793ms<\/p>\n<h1>\u9879\u76ee\u5730\u5740<\/h1>\n<p>https:\/\/github.com\/chenglixue\/unity-Stochastic-Screen-Space-Reflections\/tree\/main<\/p>\n<h1>Reference<\/h1>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/www.bilibili.com\/video\/BV1xe4y1t7Uj\/?spm_id_from=333.999.0.0&amp;vd_source=9421d881d6e2b0ef91b5e1db463db73f\" target=\"_blank\"  rel=\"nofollow\" >\u3010UE|\u9ad8\u8d28\u91cf\u6e32\u67d3\u3011Stochastic Screen-Space Reflections \u9ad8\u8d28\u91cf\u6e32\u67d3\u2014\u968f\u673a\u5c4f\u5e55\u7a7a\u95f4\u53cd\u5c04\u9ad8\u8d28\u91cf\uff0cIBL\u8865\u5b8c<\/a><\/p>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/zhuanlan.zhihu.com\/p\/505284731\" target=\"_blank\"  rel=\"nofollow\" >\u56db\u3001brdf\u91cd\u8981\u6027\u91c7\u6837<\/a><\/p>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/www.cnblogs.com\/minggoddess\/p\/14645677.html\" target=\"_blank\"  rel=\"nofollow\" >\u91cd\u8981\u6027\u91c7\u6837 ggx<\/a><\/p>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/blog.csdn.net\/qq_42999564\/article\/details\/127631258?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127631258%22%2C%22source%22%3A%22qq_42999564%22%7D\" target=\"_blank\"  rel=\"nofollow\" >\u3010\u9ad8\u8d28\u91cf\u6e32\u67d3\u3011\u2014\u968f\u673a\u5c4f\u5e55\u7a7a\u95f4\u53cd\u5c04(SSSR)<\/a><\/p>\n<p><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/zhuanlan.zhihu.com\/p\/605734440\" target=\"_blank\"  rel=\"nofollow\" >Stochastic Screen Space Reflections\u8bba\u6587\u9605\u8bfb<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4e3a\u4ec0\u4e48\u9700\u8981SSSR? \u5728\u5b9e\u65f6\u6e32\u67d3\u4e2d\u53cd\u5c04\u624b\u6bb5\u7ecf\u5e38\u7528\u5230\u7684\u53cd\u5c04\u63a2\u9488\uff0c\u8fd9\u79cd\u65b9\u6cd5\u975e\u5e38\u8282\u7701\u6027\u80fd\uff0c\u4f46\u5b83\u4e5f\u5b58\u5728\u4e00\u5b9a\u7684\u95ee\u9898\u2014\u2014\u5373\u4ece\u4e0d\u540c\u89c6\u89d2\u770b\u5411\u540c\u4e00\u5730 &#8230;<\/p>","protected":false},"author":1,"featured_media":232,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"_links":{"self":[{"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/posts\/266"}],"collection":[{"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=266"}],"version-history":[{"count":3,"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/posts\/266\/revisions"}],"predecessor-version":[{"id":269,"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/posts\/266\/revisions\/269"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=\/wp\/v2\/media\/232"}],"wp:attachment":[{"href":"http:\/\/chenglixue.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=266"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=266"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/chenglixue.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=266"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}