From c117e87cdec96343495e907c98eca9964f16b30f Mon Sep 17 00:00:00 2001 From: gamebabyrocksun <41750362@qq.com> Date: Sat, 18 Mar 2023 10:54:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E8=BE=90=E7=85=A7=E5=BA=A6?= =?UTF-8?q?=E9=A2=84=E7=A7=AF=E5=88=86=E8=B4=B4=E5=9B=BE=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E7=9A=84=E9=87=8D=E8=A6=81=E6=80=A7=E9=87=87=E6=A0=B7=E7=AE=97?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Shader/GRS_IBL_BRDF_Integration_LUT.hlsl | 2 +- ...iance_Convolution_With_Monte_Carlo_PS.hlsl | 86 +++++++------------ 2 files changed, 33 insertions(+), 55 deletions(-) diff --git a/25-IBL-MultiInstance-Sphere/Shader/GRS_IBL_BRDF_Integration_LUT.hlsl b/25-IBL-MultiInstance-Sphere/Shader/GRS_IBL_BRDF_Integration_LUT.hlsl index 3cc2e58..e5c4c50 100644 --- a/25-IBL-MultiInstance-Sphere/Shader/GRS_IBL_BRDF_Integration_LUT.hlsl +++ b/25-IBL-MultiInstance-Sphere/Shader/GRS_IBL_BRDF_Integration_LUT.hlsl @@ -48,7 +48,7 @@ float2 IntegrateBRDF(float NdotV, float roughness) float NdotH = max(H.z, 0.0); // N = (0.0f, 0.0f, 1.0f); float VdotH = max(dot(V, H), 0.0); - if (NdotL > 0.0) + if ( NdotL > 0.0 ) { float G = GeometrySmith_IBL(N, V, L, roughness); float G_Vis = (G * VdotH) / (NdotH * NdotV); diff --git a/25-IBL-MultiInstance-Sphere/Shader/GRS_IBL_Diffuse_Irradiance_Convolution_With_Monte_Carlo_PS.hlsl b/25-IBL-MultiInstance-Sphere/Shader/GRS_IBL_Diffuse_Irradiance_Convolution_With_Monte_Carlo_PS.hlsl index 699b196..3c62fc5 100644 --- a/25-IBL-MultiInstance-Sphere/Shader/GRS_IBL_Diffuse_Irradiance_Convolution_With_Monte_Carlo_PS.hlsl +++ b/25-IBL-MultiInstance-Sphere/Shader/GRS_IBL_Diffuse_Irradiance_Convolution_With_Monte_Carlo_PS.hlsl @@ -10,72 +10,50 @@ struct ST_GRS_HLSL_PS_INPUT float3 m_v4WPos : POSITION; }; -float2 UniformOnDisk(float Xi) -{ - float theta = TWO_PI * Xi; - return float2(cos(theta), sin(theta)); -} - -float3 CosOnHalfSphere(float2 Xi) -{ - float r = sqrt(Xi.x); - float2 pInDisk = r * UniformOnDisk(Xi.y); - float z = sqrt(1 - Xi.x); - return float3(pInDisk, z); -} - -float4 Quarternion_ZTo(float3 to) -{ - // from = (0, 0, 1) - //float cosTheta = dot(from, to); - //float cosHalfTheta = sqrt(max(0, (cosTheta + 1) * 0.5)); - float cosHalfTheta = sqrt(max(0, (to.z + 1) * 0.5)); - //float3 axisSinTheta = cross(from, to); - // 0 0 1 - // to.x to.y to.z - //float3 axisSinTheta = float3(-to.y, to.x, 0); - float twoCosHalfTheta = 2 * cosHalfTheta; - return float4(-to.y / twoCosHalfTheta, to.x / twoCosHalfTheta, 0, cosHalfTheta); -} - -float4 Quarternion_Inverse(float4 q) -{ - return float4(-q.xyz, q.w); -} - -float3 Quarternion_Rotate(float4 q, float3 p) -{ - // Quarternion_Mul(Quarternion_Mul(q, float4(p, 0)), Quarternion_Inverse(q)).xyz; - - float4 qp = float4(q.w * p + cross(q.xyz, p), -dot(q.xyz, p)); - float4 invQ = Quarternion_Inverse(q); - float3 qpInvQ = qp.w * invQ.xyz + invQ.w * qp.xyz + cross(qp.xyz, invQ.xyz); - return qpInvQ; -} - -float3 CosOnHalfSphere(float2 Xi, float3 N) -{ - float3 p = CosOnHalfSphere(Xi); - float4 rot = Quarternion_ZTo(N); - return Quarternion_Rotate(rot, p); -} - float4 PSMain(ST_GRS_HLSL_PS_INPUT stPSInput) :SV_Target { float3 N = normalize(stPSInput.m_v4WPos.xyz); float3 irradiance = float3(0.0f,0.0f,0.0f); - const uint SAMPLE_NUM = GRS_INT_SAMPLES_CNT; + // 计算切空间 + float3 Up = float3(0.0f, 1.0f, 0.0f); + float fdot = dot(Up, N); + if ((1.0 - fdot) > 1e-6) + { + Up = float3(1.0f, 0.0f, 0.0f); + } + + float3 Right = normalize(cross(Up, N)); + Up = normalize(cross(N, Right)); + N = normalize(cross(Right, Up)); + + float theta = 0.0f; + float phi = 0.0f; + float2 Xi; + float3 L; + + const uint SAMPLE_NUM = 4096u; + // 蒙特卡洛积分循环 for (uint i = 0u; i < SAMPLE_NUM; i++) { - float2 Xi = Hammersley(i, SAMPLE_NUM); - float3 L = CosOnHalfSphere(Xi, N); + // 产生均匀分布随机数 + Xi = Hammersley(i, SAMPLE_NUM); + + // 根据 CDF 反函数计算指定分布的随机变量 + phi = TWO_PI * Xi.x; + theta = asin(sqrt(Xi.y)); + // 球坐标转换到笛卡尔坐标(切空间) + L = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // 切空间转换到世界坐标空间 + L = L.x * Right + L.y * Up + L.z * N; + + // 采样求和统计入射辐照度 irradiance += g_texHDREnvCubemap.Sample(g_sapLinear, L).xyz; } - + // 取平均得到最终结果 irradiance *= 1.0 / float(SAMPLE_NUM); return float4(irradiance,1.0f); -- GitLab