Colord PerfectSpecular::sample(const HitPoint& hitPoint, const Vector3d& out, Vector3d& in) const { double normalDotOut = hitPoint.normal() * out; in = -out + hitPoint.normal() * 2.0 * normalDotOut; double normalDotIn = hitPoint.normal() * out; return reflectionColor() * reflectionCoefficient() / normalDotIn; }
Colord PhongMaterial::shade(const Raytracer* raytracer, const Rayd& ray, const HitPoint& hitPoint, State& state) const { auto texColor = diffuseTexture() ? diffuseTexture()->evaluate(ray, hitPoint) : Colord::black(); Lambertian ambientBRDF(texColor, ambientCoefficient()); Lambertian diffuseBRDF(texColor, diffuseCoefficient()); Vector3d out = -ray.direction(); auto color = ambientBRDF.reflectance(hitPoint, out) * raytracer->scene()->ambient(); for (const auto& light : raytracer->scene()->lights()) { Vector3d in = light->direction(hitPoint.point()); if (raytracer->scene()->intersects(Rayd(hitPoint.point(), in).epsilonShifted(), state)) { state.shadowHit(this, "PhongMaterial"); } else { state.shadowMiss(this, "PhongMaterial"); double normalDotIn = hitPoint.normal() * in; if (normalDotIn > 0.0) { color += ( diffuseBRDF(hitPoint, out, in) + m_specularBRDF(hitPoint, out, in) ) * light->radiance() * normalDotIn; } } } return color; }
Colord TransparentMaterial::shade(const Raytracer* raytracer, const Rayd& ray, const HitPoint& hitPoint, State& state) const { Vector3d out = -ray.direction(); Vector3d in; Colord reflectedColor = m_reflectiveBRDF.sample(hitPoint, out, in); Rayd reflected(hitPoint.point(), in); if (m_specularBTDF.totalInternalReflection(ray, hitPoint)) { return raytracer->rayColor(reflected.epsilonShifted(), state); } else { auto color = PhongMaterial::shade(raytracer, ray, hitPoint, state); Vector3d trans; Colord transmittedColor = m_specularBTDF.sample(hitPoint, out, trans); Rayd transmitted(hitPoint.point(), trans); state.recordEvent("TransparentMaterial: Tracing reflection"); color += reflectedColor * raytracer->rayColor(reflected.epsilonShifted(), state) * fabs(hitPoint.normal() * in); state.recordEvent("TransparentMaterial: Tracing transmission"); color += transmittedColor * raytracer->rayColor(transmitted.epsilonShifted(), state) * fabs(hitPoint.normal() * trans); return color; } }