Color Renderer::render(std::vector<PhotonMap::NearestPhoton>& nearestPhotons, Ray const& ray, int rayBounceCount) const { Color radiance = Color::BLACK; float hitDistance; Scene::Sample hit; if (!scene()->hit(ray, hitDistance, hit)) { return radiance; } { // emitted radiance radiance += hit.emission * hit.emissionPower; } { // photon radiance Color photonRadiance = Color::BLACK; auto nearestPhotonsEnd = photonMap().nearest(hit.position, nearestPhotons.begin(), nearestPhotons.end()); Vector3f const& n = hit.normal; Vector3f v = -ray.direction; auto farthestPhotonIt = nearestPhotons.begin(); float farthestPhotonSqrDistance = farthestPhotonIt->sqrDistance; for (auto& nearestPhoton : nearestPhotons) { Photon const& photon = *nearestPhoton.photon; Vector3f l = -photon.direction; float ln = dot(l, n); if (ln > 0.0f) { photonRadiance += hit.diffuse * ln * photon.power; Vector3f r = reflect(-l, n); float rv = dot(r, v); if (rv > 0.0f) { photonRadiance += hit.specular * pow(rv, hit.specularPower) * photon.power; } } } photonRadiance /= pi() * farthestPhotonSqrDistance * photonCount(); radiance += photonRadiance; } { // reflected radiance if (rayBounceCount + 1 < maxRayBounceCount() && luminance(hit.specular) > 0.0f) { Ray reflectedRay; reflectedRay.origin = hit.position; reflectedRay.direction = reflect(ray.direction, hit.normal); reflectedRay.origin += reflectedRay.direction * 0.001f; radiance += hit.specular * render(nearestPhotons, reflectedRay, rayBounceCount + 1); } } { // transmitted radiance if (rayBounceCount + 1 < maxRayBounceCount() && luminance(hit.transmission) > 0.0f) { Ray transmittedRay; transmittedRay.origin = hit.position; if (dot(hit.normal, ray.direction) <= 0.0f) { transmittedRay.direction = transmit(ray.direction, +hit.normal, 1.0f / hit.refractionIndex); } else { transmittedRay.direction = transmit(ray.direction, -hit.normal, hit.refractionIndex / 1.0f); } transmittedRay.origin += transmittedRay.direction * 0.001f; if (!nan(sqrLength(transmittedRay.direction))) { radiance += hit.transmission * render(nearestPhotons, transmittedRay, rayBounceCount + 1); } } } return radiance; }
void Label::mouseMoveEvent(QMouseEvent* event) { if (m_mousePosition) { Point2i oldMousePosition = *m_mousePosition; *m_mousePosition = Point2i(event->pos().x(), event->pos().y()); Vector2i displacement = *m_mousePosition - oldMousePosition; if (sqrLength(displacement) > 0) { emit mouseMoved(*m_mousePosition, displacement); } } else { m_mousePosition = new Point2i(event->pos().x(), event->pos().y()); emit mouseEntered(*m_mousePosition); } event->accept(); }
//! Return length of vector. Type length() const { return (Type)std::sqrt( sqrLength() ); }
Photon Renderer::emitAndScatter(Random &random) { float currentRefractionIndex = 1.0; Scene::Sample sample; do { sample = scene()->uniformOnSurface(random); } while (luminance(sample.emission) * sample.emissionPower == 0.0f); float hitDistance; Scene::Sample hit; Ray ray; ray.origin = sample.position; do { ray.direction = random.cosineDirection(sample.normal); } while (!scene()->hit(ray, hitDistance, hit)); Photon photon; photon.position = hit.position; photon.direction = ray.direction; photon.power = sample.emission * sample.emissionPower; while (true) { float action = random.uniformInRange01(); float specularLuminance = luminance(hit.specular); if (action < specularLuminance) { Ray reflectedRay; reflectedRay.origin = hit.position; reflectedRay.direction = reflect(ray.direction, hit.normal); reflectedRay.origin += reflectedRay.direction * 0.001f; ray = reflectedRay; if (!scene()->hit(ray, hitDistance, hit)) { photon.power = Color::BLACK; break; } photon.position = hit.position; photon.direction = ray.direction; continue; } else { action -= specularLuminance; } float transmissionLuminance = luminance(hit.transmission); if (action < transmissionLuminance) { Ray transmittedRay; transmittedRay.origin = hit.position; if (dot(hit.normal, ray.direction) <= 0.0f) { transmittedRay.direction = transmit(ray.direction, +hit.normal, 1.0f / hit.refractionIndex); } else { transmittedRay.direction = transmit(ray.direction, -hit.normal, hit.refractionIndex / 1.0f); } transmittedRay.origin += transmittedRay.direction * 0.001f; ray = transmittedRay; if (nan(sqrLength(ray.direction)) || !scene()->hit(ray, hitDistance, hit)) { photon.power = Color::BLACK; break; } photon.position = hit.position; photon.direction = ray.direction; continue; } else { action -= transmissionLuminance; } // absorbtion; break; } return photon; }
float sqrDistance(const Vector4& a, const Vector4& b) { return sqrLength(b - a); }
eF32 length() const { return eSqrt(sqrLength()); }
inline float length(Vector3f const& v) { return sqrt(sqrLength(v)); }