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; }
bool SmoothMeshTriangle::intersects(const Rayd& ray, State& state) const { int ku = mod3[k + 1]; int kv = mod3[k + 2]; const Vector4d& O = ray.origin(); const Vector3d& D = ray.direction(); const Vector3d& A = m_mesh->vertices[m_index0].point; const double lnd = 1.0f / (D[k] + nu * D[ku] + nv * D[kv]); const double t = (nd - O[k] - nu * O[ku] - nv * O[kv]) * lnd; if (t < 0) { state.shadowMiss("SmoothMeshTriangle, behind ray"); return false; } const double hu = O[ku] + t * D[ku] - A[ku]; const double hv = O[kv] + t * D[kv] - A[kv]; const double beta = hv * bnu + hu * bnv; if (beta < 0 || beta > 1) { state.shadowMiss("SmoothMeshTriangle, beta not in [0, 1]"); return false; } const double gamma = hu * cnu + hv * cnv; if (gamma < 0 || (beta + gamma) > 1) { state.shadowMiss("SmoothMeshTriangle, gamma < 0 or beta + gamma > 1"); return false; } state.shadowHit("SmoothMeshTriangle"); return true; }
bool Sphere::intersects(const Rayd& ray, State& state) const { const Vector3d& o = ray.origin() - m_origin, d = ray.direction(); double od = o * d, dd = d * d; double discriminant = od * od - dd * (o * o - m_radius * m_radius); if (discriminant < 0) { state.shadowMiss(this, "Sphere, ray miss"); return false; } else if (discriminant > 0) { double discriminantRoot = sqrt(discriminant); double t1 = (-od - discriminantRoot) / dd; double t2 = (-od + discriminantRoot) / dd; if (t1 <= 0 && t2 <= 0) { state.shadowMiss(this, "Sphere, behind ray"); return false; } state.shadowHit(this, "Sphere"); return true; } state.shadowMiss(this, "Sphere, ray miss"); return false; }
void Display::mousePressEvent(QMouseEvent* event) { QtDisplay::mousePressEvent(event); Rayd ray = m_camera->rayForPixel(event->pos().x(), event->pos().y()); if (ray.direction().isDefined()) { auto state = m_raytracer->rayState(ray); cout << state.hitPoint.primitive() << " - " << state.hitPoint << endl; } }
void Display::mousePressEvent(QMouseEvent* event) { QtDisplay::mousePressEvent(event); if (event->modifiers() & Qt::ControlModifier) { Rayd ray = m_raytracer->camera()->rayForPixel(event->pos().x(), event->pos().y()); if (ray.direction().isDefined()) { auto state = m_raytracer->rayState(ray); cout << state.hitPoint.primitive() << " - " << state.hitPoint << endl; cout << "maxRecursionDepth: " << state.maxRecursionDepth << endl; cout << "intersectionHits: " << state.intersectionHits << endl; cout << "intersectionMisses: " << state.intersectionMisses << endl; cout << "shadowIntersectionHits: " << state.shadowIntersectionHits << endl; cout << "shadowIntersectionMisses: " << state.shadowIntersectionMisses << endl; for (const auto& event : *state.events) { cout << event << endl; } } } }
void Camera::render(std::shared_ptr<Raytracer> raytracer, Buffer<unsigned int>& buffer, const Recti& rect) const { if (isCancelled()) return; auto plane = viewPlane(); for (ViewPlane::Iterator pixel = plane->begin(rect), end = plane->end(rect); pixel != end; ++pixel) { Colord pixelColor; for (const auto& sample : plane->sampler()->sampleSet()) { Rayd ray = rayForPixel(pixel.pixel() + sample); if (ray.direction().isDefined()) { State state; pixelColor += raytracer->rayColor(ray, state); } } plot(buffer, rect, pixel, pixelColor); if (isCancelled()) break; } }
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; } }