Spectrum SampleIntegrator::E(const Scene *scene, const Point &p, const Normal &n, Float time, const Medium *medium, Sampler *sampler, int nSamples, bool handleIndirect) const { Spectrum E(0.0f); LuminaireSamplingRecord lRec; RadianceQueryRecord rRec(scene, sampler); Frame frame(n); sampler->generate(); for (int i=0; i<nSamples; i++) { rRec.newQuery(RadianceQueryRecord::ERadianceNoEmission, medium); /* Direct */ if (scene->sampleAttenuatedLuminaire(p, time, medium, lRec, rRec.nextSample2D())) { Float dp = dot(lRec.d, n); if (dp < 0) E -= lRec.value * dp; } /* Indirect */ if (handleIndirect) { Vector d = frame.toWorld(squareToHemispherePSA(rRec.nextSample2D())); ++rRec.depth; E += Li(RayDifferential(p, d, time), rRec) * M_PI; } sampler->advance(); } return E / (Float) nSamples; }
void sampleEmission(EmissionRecord &eRec, const Point2 &sample1, const Point2 &sample2) const { eRec.pdfArea = m_shape->sampleArea(eRec.sRec, sample1); Vector wo = squareToHemispherePSA(sample2); eRec.pdfDir = Frame::cosTheta(wo) * INV_PI; eRec.d = Frame(eRec.sRec.n).toWorld(wo); eRec.value = m_intensity; }
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const { if (!(bRec.typeMask & EDiffuseTransmission)) return Spectrum(0.0f); bRec.wo = squareToHemispherePSA(sample); if (Frame::cosTheta(bRec.wi) > 0) bRec.wo.z *= -1; bRec.sampledComponent = 0; bRec.sampledType = EDiffuseTransmission; return m_transmittance->getValue(bRec.its); }
void VPLShaderManager::setVPL(const VPL &vpl) { Point p = vpl.its.p + vpl.its.shFrame.n * 0.01; Intersection its; /* Estimate good near and far plane locations by tracing some rays */ Float nearClip = std::numeric_limits<Float>::infinity(), farClip = -std::numeric_limits<Float>::infinity(); Ray ray; ray.o = p; if (m_shadowMap == NULL || m_shadowMapResolution != m_shadowMap->getSize().x) { m_shadowMap = m_renderer->createGPUTexture("Shadow cube map", NULL); m_shadowMap->setSize(Point3i(m_shadowMapResolution, m_shadowMapResolution, 1)); m_shadowMap->setFrameBufferType(GPUTexture::EDepthBuffer); m_shadowMap->setType(GPUTexture::ETextureCubeMap); m_shadowMap->setWrapType(GPUTexture::EClampToEdge); m_shadowMap->setFilterType(GPUTexture::ENearest); m_shadowMap->setDepthMode(GPUTexture::ENormal); m_shadowMap->init(); } const int sampleCount = 200; const Float invSampleCount = 1.0f/sampleCount; for (int i=1; i<=sampleCount; ++i) { Vector dir; Point2 seed(i*invSampleCount, radicalInverse(2, i)); // Hammersley seq. if (vpl.type == ESurfaceVPL || vpl.luminaire->getType() & Luminaire::EOnSurface) dir = vpl.its.shFrame.toWorld(squareToHemispherePSA(seed)); else dir = squareToSphere(seed); ray.setDirection(dir); if (m_scene->rayIntersect(ray, its)) { nearClip = std::min(nearClip, its.t); farClip = std::max(farClip, its.t); } } m_minDist = nearClip + (farClip - nearClip) * m_clamping; nearClip = std::min(nearClip, (Float) 0.001f); farClip = std::min(farClip * 1.5f, m_maxClipDist); if (farClip < 0 || nearClip >= farClip) { /* Unable to find any surface - just default values based on the scene size */ nearClip = 1e-3f * m_scene->getBSphere().radius; farClip = 2 * m_scene->getBSphere().radius; m_minDist = 0; } farClip = std::min(farClip, 5.0f*m_scene->getBSphere().radius); m_nearClip = nearClip; m_invClipRange = 1/(farClip-nearClip); Transform lightViewTrafo, lightProjTrafo = Transform::glPerspective(90.0f, nearClip, farClip); Matrix4x4 identity; identity.setIdentity(); m_renderer->setCamera(identity, identity); m_shadowMap->activateTarget(); if (m_singlePass && m_shadowProgram != NULL) { /* "Fancy": render the whole cube map in a single pass using a geometry program. On anything but brand-new hardware, this is actually slower. */ m_shadowMap->activateSide(-1); m_shadowMap->clear(); m_shadowProgram->bind(); try { for (int i=0; i<6; ++i) { switch (i) { case 0: lightViewTrafo = Transform::lookAt(p, p + Vector(1, 0, 0), Vector(0, 1, 0)).inverse(); break; case 1: lightViewTrafo = Transform::lookAt(p, p + Vector(-1, 0, 0), Vector(0, 1, 0)).inverse(); break; case 2: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 1, 0), Vector(0, 0, -1)).inverse(); break; case 3: lightViewTrafo = Transform::lookAt(p, p + Vector(0, -1, 0), Vector(0, 0, 1)).inverse(); break; case 4: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 0, 1), Vector(0, 1, 0)).inverse(); break; case 5: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 0, -1), Vector(0, 1, 0)).inverse(); break; } lightViewTrafo = Transform::scale(Vector(-1, 1, 1)) * lightViewTrafo; const Matrix4x4 &viewMatrix = lightViewTrafo.getMatrix(); m_shadowProgram->setParameter(m_shadowProgramParam_cubeMapTransform[i], lightProjTrafo * lightViewTrafo); m_shadowProgram->setParameter(m_shadowProgramParam_depthVec[i], Vector4( -viewMatrix.m[2][0] * m_invClipRange, -viewMatrix.m[2][1] * m_invClipRange, -viewMatrix.m[2][2] * m_invClipRange, (-viewMatrix.m[2][3] - m_nearClip) * m_invClipRange )); } m_renderer->drawAll(m_drawList); } catch (const std::exception &ex) { m_shadowProgram->unbind(); throw ex; } m_shadowProgram->unbind(); } else { /* Old-fashioned: render 6 times, once for each cube map face */ m_altShadowProgram->bind(); try { for (int i=0; i<6; ++i) { switch (i) { case 0: lightViewTrafo = Transform::lookAt(p, p + Vector(1, 0, 0), Vector(0, 1, 0)).inverse(); break; case 1: lightViewTrafo = Transform::lookAt(p, p + Vector(-1, 0, 0), Vector(0, 1, 0)).inverse(); break; case 2: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 1, 0), Vector(0, 0, -1)).inverse(); break; case 3: lightViewTrafo = Transform::lookAt(p, p + Vector(0, -1, 0), Vector(0, 0, 1)).inverse(); break; case 4: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 0, 1), Vector(0, 1, 0)).inverse(); break; case 5: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 0, -1), Vector(0, 1, 0)).inverse(); break; } lightViewTrafo = Transform::scale(Vector(-1, 1, 1)) * lightViewTrafo; const Matrix4x4 &viewMatrix = lightViewTrafo.getMatrix(); m_altShadowProgram->setParameter(m_altShadowProgramParam_cubeMapTransform, lightProjTrafo * lightViewTrafo); m_altShadowProgram->setParameter(m_altShadowProgramParam_depthVec, Vector4( -viewMatrix.m[2][0] * m_invClipRange, -viewMatrix.m[2][1] * m_invClipRange, -viewMatrix.m[2][2] * m_invClipRange, (-viewMatrix.m[2][3] - m_nearClip) * m_invClipRange )); m_shadowMap->activateSide(i); m_shadowMap->clear(); m_renderer->drawAll(m_drawList); } } catch (std::exception &ex) { m_altShadowProgram->unbind(); throw ex; } m_altShadowProgram->unbind(); } m_shadowMap->releaseTarget(); }
Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const { Vector wo = squareToHemispherePSA(sample); eRec.d = Frame(eRec.sRec.n).toWorld(wo); eRec.pdfDir = Frame::cosTheta(wo) * INV_PI; return Spectrum(INV_PI); }