这种模型可以使用给定的权重混合任意两种材质,它会首先复制一份 SurfaceInteraction ,接着在两个 SI 上使用两种材质生成原始的 BSDF ,最后使用权重在原始的 SI 上重新生成 ScaledBSDF。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
voidMixMaterial::ComputeScatteringFunctions(SurfaceInteraction *si, MemoryArena &arena, TransportMode mode, bool allowMultipleLobes)const{ // Compute weights and original _BxDF_s for mix material Spectrum s1 = scale->Evaluate(*si).Clamp(); Spectrum s2 = (Spectrum(1.f) - s1).Clamp(); SurfaceInteraction si2 = *si; m1->ComputeScatteringFunctions(si, arena, mode, allowMultipleLobes); m2->ComputeScatteringFunctions(&si2, arena, mode, allowMultipleLobes);
// Initialize _si->bsdf_ with weighted mixture of _BxDF_s int n1 = si->bsdf->NumComponents(), n2 = si2.bsdf->NumComponents(); for (int i = 0; i < n1; ++i) si->bsdf->bxdfs[i] = ARENA_ALLOC(arena, ScaledBxDF)(si->bsdf->bxdfs[i], s1); for (int i = 0; i < n2; ++i) si->bsdf->Add(ARENA_ALLOC(arena, ScaledBxDF)(si2.bsdf->bxdfs[i], s2)); }
// Shift _siEval_ _du_ in the $u$ direction Float du = .5f * (std::abs(si->dudx) + std::abs(si->dudy)); // The most common reason for du to be zero is for ray that start from // light sources, where no differentials are available. In this case, // we try to choose a small enough du so that we still get a decently // accurate bump value. if (du == 0) du = .0005f; siEval.p = si->p + du * si->shading.dpdu; siEval.uv = si->uv + Vector2f(du, 0.f); siEval.n = Normalize((Normal3f)Cross(si->shading.dpdu, si->shading.dpdv) + du * si->dndu); Float uDisplace = d->Evaluate(siEval);
// Shift _siEval_ _dv_ in the $v$ direction Float dv = .5f * (std::abs(si->dvdx) + std::abs(si->dvdy)); if (dv == 0) dv = .0005f; siEval.p = si->p + dv * si->shading.dpdv; siEval.uv = si->uv + Vector2f(0.f, dv); siEval.n = Normalize((Normal3f)Cross(si->shading.dpdu, si->shading.dpdv) + dv * si->dndv); Float vDisplace = d->Evaluate(siEval); Float displace = d->Evaluate(*si);