|
1 | 1 | --- |
2 | 2 | author: mos9527 |
3 | | -lastmod: 2025-12-25T16:12:40.471693 |
| 3 | +lastmod: 2025-12-25T16:42:35.007429 |
4 | 4 | title: Foundation 施工笔记 【6】- 路径追踪 |
5 | 5 | tags: ["CG","Vulkan","Foundation"] |
6 | 6 | categories: ["CG","Vulkan"] |
@@ -1082,15 +1082,17 @@ float3 f = (Fss + Fms) * mfDistrib.D(wm) * mfDistrib.G(wo, wi) / (4 * AbsCosThet |
1082 | 1082 | return BSDFSample(f, wi, pdf, BxDFFlags::GlossyReflection); |
1083 | 1083 | ``` |
1084 | 1084 |
|
1085 | | -##### 导体效果 |
| 1085 | +##### 导体 |
1086 | 1086 |
|
1087 | | -一样的白炉测试效果如下。先令所有`metallic=1.0f`,即只看specular lobe: |
| 1087 | +###### 导体效果 |
| 1088 | +
|
| 1089 | +一样的白炉测试效果如下。先令所有`metallic=1.0f`,即只看ConductorBxDF等效部分: |
1088 | 1090 |
|
1089 | 1091 |  |
1090 | 1092 |
|
1091 | 1093 | (注:别忘了Sampler用CLAMP_TO_EDGE - -||) |
1092 | 1094 |
|
1093 | | -##### 电介质表现 |
| 1095 | +##### 电介质 |
1094 | 1096 |
|
1095 | 1097 | 目前为止,我们只对不存在(不考虑:导体中折射即吸收)折射贡献的BRDF做了改进。对于电介质BRDF(及metal<1),这里的工作是不够的:因为算$E$的时候并没有看「折射」后的能量问题。 |
1096 | 1098 |
|
@@ -1168,13 +1170,57 @@ ggxE[dot(p, uint2(1, 32))] = float2(E / samples, Eprime / samples); |
1168 | 1170 |
|
1169 | 1171 | ###### 电介质效果 |
1170 | 1172 |
|
1171 | | -让roughness,metallic反映场景真实情况,效果如下: |
| 1173 | +ImageWorks也提到了对Diffuse lobe的调整(虽然这部分我们也讨论过了):$E\prime\prime$是补偿过的反射量,那么真正能到达底层diffuse lobe的能量即为$1-E\prime\prime$(回顾反射率关系),刚好允许我们进行正确的能量调整:漫反射一定有入射=出射,$1-E\prime\prime$则是混合glossy lobe后其正确的反照率。 |
| 1174 | + |
| 1175 | +至此电介质模型调整完毕,shader节选如下: |
| 1176 | + |
| 1177 | +```c++ |
| 1178 | +... |
| 1179 | +const float mu = AbsCosTheta(wo); |
| 1180 | +const float2 EEp = ggxLutE.SampleLevel(lutSampler, float2(mu, roughness), 0); |
| 1181 | +const float3 Epp = F0 * EEp.x + (F90 - F0) * EEp.y; |
| 1182 | +float probGlossy = NEEGlossyProb(wo); |
| 1183 | +if (uc < probGlossy) { |
| 1184 | + // Sample Glossy |
| 1185 | + if (mfDistrib.EffectivelySmooth()) { |
| 1186 | + // Dirac delta case |
| 1187 | + float3 wi = float3(-wo.x, -wo.y, wo.z); // = wr |
| 1188 | + float3 fGlossy = SchlickFresnel(F0, 1.0f, AbsCosTheta(wi)); |
| 1189 | + // Sampled PDF would be delta, but we represent them as 1s w/o weighting |
| 1190 | + // With NEE this is what you get: |
| 1191 | + return BSDFSample(fGlossy / AbsCosTheta(wi), wi, 1 * probGlossy, BxDFFlags::SpecularReflection); |
| 1192 | + } else { |
| 1193 | + float3 wm = mfDistrib.Sample_wm(wo, u); |
| 1194 | + float3 wi = Reflect(wo, wm); |
| 1195 | + if (!SameHemisphere(wo, wi)) |
| 1196 | + return BSDFSample(); // Absorption |
| 1197 | + |
| 1198 | + float3 Fss = SchlickFresnel(F0, 1.0f, AbsDot(wo, wm)); |
| 1199 | + float3 Fms = F0 * (1/Epp - 1) * Fss; |
| 1200 | + float3 f = (Fms + Fss) * mfDistrib.D(wm) * mfDistrib.G(wo, wi) / (4 * AbsCosTheta(wi) * AbsCosTheta(wo)); |
| 1201 | + |
| 1202 | + float pdf = probGlossy * mfDistrib.PDF(wo, wm) / (4 * AbsDot(wo, wm)); |
| 1203 | + return BSDFSample(f, wi, pdf, BxDFFlags::GlossyReflection); |
| 1204 | + } |
| 1205 | +} else { |
| 1206 | + // Sample Diffuse |
| 1207 | + float3 wi = SampleCosineHemisphere(u); |
| 1208 | + wi = FaceForward(wi, float3(0,0,1)); |
| 1209 | + float3 wm = normalize(wo + wi); |
| 1210 | + |
| 1211 | + float3 cdiff = baseColor * (1.0f - metallic); |
| 1212 | + float3 f = (1-Epp) * cdiff * InvPi; |
1172 | 1213 |
|
1173 | | - |
| 1214 | + float pdf = (1 - probGlossy) * CosineHemispherePDF(ClampedCosTheta(wi)); |
| 1215 | + return BSDFSample(f, wi, pdf, BxDFFlags::DiffuseReflection); |
| 1216 | +} |
| 1217 | +``` |
1174 | 1218 |
|
1175 | | -TBD:中途roughness过补偿? |
| 1219 | +让metallic=0(全电介质)的效果如下: |
1176 | 1220 |
|
| 1221 | + |
1177 | 1222 |
|
| 1223 | + |
1178 | 1224 |
|
1179 | 1225 |
|
1180 | 1226 | <h1 style="color:red">--- 施工中 ---</h1> |
0 commit comments