// Sample an exitant ray Vec3f DirectionalLight::sampleExitantRay( const Scene& scene, const Vec2f& emissionVertexSample, const Vec2f& raySample, RaySample& exitantRaySample, float& emissionVertexPdf) const { Vec3f center; float radius; boundingSphere(scene.getBBox(), center, radius); // Center of the disk center += m_IncidentDirection * radius; Vec2f pos2D = uniformSampleDisk(raySample, radius); auto originPdf = 1.f / (pi<float>() * radius * radius); emissionVertexPdf = 1.f; auto pdf = originPdf * emissionVertexPdf; auto matrix = frameY(center, m_IncidentDirection); auto rayOrigin = Vec3f(matrix * Vec4f(pos2D.x, 0, pos2D.y, 1.f)); exitantRaySample = RaySample(Ray(rayOrigin, -m_IncidentDirection), pdf); return m_Le; }
float PerspectiveCamera::generateRay(const Sample& sample, RayDifferential* ray) const { float invXRes = mFilm->getInvXResolution(); float invYRes = mFilm->getInvYResolution(); float xNDC = +2.0f * sample.imageX * invXRes - 1.0f; float yNDC = -2.0f * sample.imageY * invYRes + 1.0f; float dxNDC = +2.0f * (sample.imageX + 1.0f) * invXRes - 1.0f; float dyNDC = -2.0f * (sample.imageY + 1.0f) * invYRes + 1.0f; // from NDC space to view space // xView = xNDC * zView * tan(fov / 2) * aspectRatio // yView = yNDC * zView * tan(fov / 2) // in projection matrix pro, // pro[0][0] = 1 / (tan(fov / 2) * aspectRatio) // pro[1][1] = 1 / (tan(fov / 2)) float zView = 1.0f; float xView = xNDC / mProj[0][0]; float yView = yNDC / mProj[1][1]; Vector3 viewDir = Vector3(xView, yView, zView); float dxView = dxNDC / mProj[0][0]; Vector3 dxViewDir(dxView, yView, zView); float dyView = dyNDC / mProj[1][1]; Vector3 dyViewDir(xView, dyView, zView); if(mLensRadius == 0.0f) { // view space to world space ray->o = ray->dxOrigin = ray->dyOrigin = mPosition; ray->d = mOrientation * normalize(viewDir); ray->dxDir = mOrientation * normalize(dxViewDir); ray->dyDir = mOrientation * normalize(dyViewDir); } else { // perturb the ray direction for DOF effect float ft = mFocalDistance / viewDir.z; Vector3 pFocus = viewDir * ft; Vector3 pDxFocus = dxViewDir * ft; Vector3 pDyFocus = dyViewDir * ft; Vector2 lensSample = mLensRadius * uniformSampleDisk(sample.lensU1, sample.lensU2); Vector3 viewOrigin(lensSample.x, lensSample.y, 0.0f); ray->o = ray->dxOrigin = ray->dyOrigin = mOrientation * viewOrigin + mPosition; ray->d = mOrientation * normalize(pFocus - viewOrigin); ray->dxDir = mOrientation * normalize(pDxFocus - viewOrigin); ray->dyDir = mOrientation * normalize(pDyFocus - viewOrigin); } ray->mint = 1e-3f; ray->maxt = INFINITY; ray->depth = 0; ray->hasDifferential = true; return 1.0f; }
Vector3 PerspectiveCamera::samplePosition(const Sample& sample, Vector3* surfaceNormal, float* pdfArea) const { Vector3 pCamera; if (mLensRadius > 0.0f) { Vector2 lensSample = mLensRadius * uniformSampleDisk(sample.lensU1, sample.lensU2); Vector3 viewOrigin(lensSample.x, lensSample.y, 0.0f); pCamera = mOrientation * viewOrigin + mPosition; } else { pCamera = mPosition; } if (pdfArea) { *pdfArea = mLensRadius > 0.0f ? 1.0f / (mLensRadius * mLensRadius * PI) : 1.0f; } *surfaceNormal = getLook(); return pCamera; }