bool Cube::samplePosition(PathSampleGenerator &sampler, PositionSample &sample) const { float u = sampler.next1D(); int dim = sampleFace(u); float s = (dim + 1) % 3; float t = (dim + 2) % 3; Vec2f xi = sampler.next2D(); Vec3f n(0.0f); n[dim] = u < 0.5f ? -1.0f : 1.0f; Vec3f p(0.0f); p[dim] = n[dim]*_scale[dim]; p[s] = (xi.x()*2.0f - 1.0f)*_scale[s]; p[t] = (xi.y()*2.0f - 1.0f)*_scale[t]; sample.p = _rot*p + _pos; sample.pdf = _invArea; sample.uv = xi; sample.weight = PI*_area*(*_emission)[sample.uv]; sample.Ng = _rot*n; return true; }
bool MultiQuadLight::sampleDirect(uint32 threadIndex, const Vec3f &p, PathSampleGenerator &pathSampler, LightSample &sample) const { float xi = pathSampler.next1D(EmitterSample); ThreadlocalSampleInfo &sampler = *_samplers[threadIndex]; std::pair<int, float> result = _sampleBvh->sampleLight(p, &sampler.sampleWeights[0], &sampler.insideIds[0], xi, [&](uint32 id) { return approximateQuadContribution(p, id); }); if (result.first == -1) return false; int idx = pathSampler.next1D(EmitterSample) < 0.5f ? result.first*2 : result.first*2 + 1; const QuadGeometry::TriangleInfo &t = _geometry.triangle(idx); Vec3f q = SampleWarp::uniformTriangle(pathSampler.next2D(EmitterSample), t.p0, t.p1, t.p2); Vec3f L = q - p; float rSq = L.lengthSq(); sample.dist = std::sqrt(rSq); sample.d = L/sample.dist; float cosTheta = -(t.Ng.dot(sample.d)); if (cosTheta <= 0.0f) return false; sample.pdf = result.second*0.5f*rSq/(cosTheta*_triangleAreas[idx]); return true; }
bool IsotropicPhaseFunction::sample(PathSampleGenerator &sampler, const Vec3f &/*wi*/, PhaseSample &sample) const { sample.w = SampleWarp::uniformSphere(sampler.next2D()); sample.weight = Vec3f(1.0f); sample.pdf = SampleWarp::uniformSpherePdf(); return true; }
bool Quad::sampleDirection(PathSampleGenerator &sampler, const PositionSample &/*point*/, DirectionSample &sample) const { Vec3f d = SampleWarp::cosineHemisphere(sampler.next2D(EmitterSample)); sample.d = _frame.toGlobal(d); sample.weight = Vec3f(1.0f); sample.pdf = SampleWarp::cosineHemispherePdf(d); return true; }
bool Cube::sampleDirection(PathSampleGenerator &sampler, const PositionSample &point, DirectionSample &sample) const { Vec3f d = SampleWarp::cosineHemisphere(sampler.next2D()); sample.d = TangentFrame(point.Ng).toGlobal(d); sample.weight = Vec3f(1.0f); sample.pdf = SampleWarp::cosineHemispherePdf(d); return true; }
bool Quad::samplePosition(PathSampleGenerator &sampler, PositionSample &sample) const { Vec2f xi = sampler.next2D(EmitterSample); sample.p = _base + xi.x()*_edge0 + xi.y()*_edge1; sample.pdf = _invArea; sample.uv = xi; sample.weight = PI*_area*(*_emission)[sample.uv]; sample.Ng = _frame.normal; return true; }
bool EquirectangularCamera::sampleDirection(PathSampleGenerator &sampler, const PositionSample &/*point*/, Vec2u pixel, DirectionSample &sample) const { float pdf; Vec2f uv = (Vec2f(pixel) + 0.5f + _filter.sample(sampler.next2D(), pdf))*_pixelSize; float sinTheta; sample.d = uvToDirection(uv, sinTheta); sample.weight = Vec3f(1.0f); sample.pdf = INV_PI*INV_TWO_PI/sinTheta; return true; }
bool Quad::sampleDirect(uint32 /*threadIndex*/, const Vec3f &p, PathSampleGenerator &sampler, LightSample &sample) const { if (_frame.normal.dot(p - _base) <= 0.0f) return false; Vec2f xi = sampler.next2D(EmitterSample); Vec3f q = _base + xi.x()*_edge0 + xi.y()*_edge1; sample.d = q - p; float rSq = sample.d.lengthSq(); sample.dist = std::sqrt(rSq); sample.d /= sample.dist; float cosTheta = -_frame.normal.dot(sample.d); sample.pdf = rSq/(cosTheta*_area); return true; }
bool PinholeCamera::sampleDirection(PathSampleGenerator &sampler, const PositionSample &/*point*/, Vec2u pixel, DirectionSample &sample) const { float pdf; Vec2f uv = _filter.sample(sampler.next2D(CameraSample), pdf); Vec3f localD = Vec3f( -1.0f + (float(pixel.x()) + 0.5f + uv.x())*2.0f*_pixelSize.x(), _ratio - (float(pixel.y()) + 0.5f + uv.y())*2.0f*_pixelSize.x(), _planeDist ).normalized(); sample.d = _transform.transformVector(localD); sample.weight = Vec3f(1.0f); sample.pdf = _invPlaneArea/cube(localD.z()); return true; }
bool CubemapCamera::sampleDirection(PathSampleGenerator &sampler, const PositionSample &/*point*/, Vec2u pixel, DirectionSample &sample) const { Vec2f uv = (Vec2f(pixel) + 0.5f)*_pixelSize; int face; if (!uvToFace(uv, face)) return false; float filterPdf; uv += _filter.sample(sampler.next2D(CameraSample), filterPdf)*_pixelSize; sample.d = uvToDirection(face, uv, sample.pdf); sample.weight = Vec3f(1.0f); return true; }
bool HenyeyGreensteinPhaseFunction::sample(PathSampleGenerator &sampler, const Vec3f &wi, PhaseSample &sample) const { Vec2f xi = sampler.next2D(MediumPhaseSample); if (_g == 0.0f) { sample.w = SampleWarp::uniformSphere(xi); sample.weight = Vec3f(1.0f); sample.pdf = SampleWarp::uniformSpherePdf(); } else { float phi = xi.x()*TWO_PI; float cosTheta = (1.0f + _g*_g - sqr((1.0f - _g*_g)/(1.0f + _g*(xi.y()*2.0f - 1.0f))))/(2.0f*_g); float sinTheta = std::sqrt(max(1.0f - cosTheta*cosTheta, 0.0f)); sample.w = TangentFrame(wi).toGlobal(Vec3f( std::cos(phi)*sinTheta, std::sin(phi)*sinTheta, cosTheta )); sample.weight = Vec3f(1.0f); sample.pdf = henyeyGreenstein(cosTheta); } return true; }
bool PinholeCamera::sampleDirection(PathSampleGenerator &sampler, const PositionSample &point, DirectionSample &sample) const { Vec2u pixel(sampler.next2D(CameraSample)*Vec2f(_res)); return sampleDirection(sampler, point, pixel, sample); }