Light_SampleRes PointLight_sample(const Light* super,
                                  const DifferentialGeometry& dg,
                                  const Vec2f& s)
{
  const PointLight* self = (PointLight*)super;
  Light_SampleRes res;

  // extant light vector from the hit point
  const Vec3fa dir = self->position - dg.P;
  const float dist2 = dot(dir, dir);
  const float invdist = rsqrt(dist2);

  // normalized light vector
  res.dir = dir * invdist;
  res.dist = dist2 * invdist;

  res.pdf = inf; // per default we always take this res

  // convert from power to radiance by attenuating by distance^2
  res.weight = self->power * sqr(invdist);
  const float sinTheta = self->radius * invdist;

  if ((self->radius > 0.f) & (sinTheta > 0.005f)) {
    // res surface of sphere as seen by hit point -> cone of directions
    // for very small cones treat as point light, because float precision is not good enough
    if (sinTheta < 1.f) {
      const float cosTheta = sqrt(1.f - sinTheta * sinTheta);
      const Vec3fa localDir = uniformSampleCone(cosTheta, s);
      res.dir = frame(res.dir) * localDir;
      res.pdf = uniformSampleConePDF(cosTheta);
      const float c = localDir.z;
      res.dist = c*res.dist - sqrt(sqr(self->radius) - (1.f - c*c) * dist2);
      // TODO scale radiance by actual distance
    } else { // inside sphere
      const Vec3fa localDir = cosineSampleHemisphere(s);
      res.dir = frame(dg.Ns) * localDir;
      res.pdf = cosineSampleHemispherePDF(localDir);
      // TODO:
      res.weight = self->power * rcp(sqr(self->radius));
      res.dist = self->radius;
    }
  }

  return res;
}
Light_SampleRes DirectionalLight_sample(const Light* super,
                                        const DifferentialGeometry& dg,
                                        const Vec2f& s)
{
  const DirectionalLight* self = (DirectionalLight*)super;
  Light_SampleRes res;

  res.dir = self->frame.vz;
  res.dist = inf;
  res.pdf = self->pdf;

  if (self->cosAngle < COS_ANGLE_MAX)
    res.dir = self->frame * uniformSampleCone(self->cosAngle, s);

  res.weight = self->radiance; // *pdf/pdf cancel

  return res;
}
Beispiel #3
0
/*! Uniform sampling of spherical cone. Cone direction is provided as argument. */
inline direction_sample uniformSampleCone(real u, real v, real angle, const real3& N) {
    direction_sample s = uniformSampleCone(u, v, angle);
    return direction_sample(frameZ(N) * s.value(), s.density());
}