Initial commit.

This commit is contained in:
hal8174 2024-04-23 10:14:24 +02:00
commit d3bb49b3f5
1073 changed files with 484757 additions and 0 deletions

View file

@ -0,0 +1,77 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "light.h"
#include <sampling.hpp>
#include <math/linearspace3.h>
#include "helper.hpp"
namespace embree {
struct AmbientLight {
Light super; //!< inherited light fields
Vec3fa radiance; //!< RGB color and intensity of light
};
// Implementation
//////////////////////////////////////////////////////////////////////////////
// XXX importance sampling is only done into the positive hemisphere
// ==> poor support for translucent materials
Light_SampleRes AmbientLight_sample(const Light* super,
const Sample& dg,
const Vec2f& s) {
AmbientLight* self = (AmbientLight *) super;
Light_SampleRes res;
const Vec3fa localDir = cosineSampleHemisphere(s);
res.dir = frame(dg.Ns) * localDir;
res.pdf = cosineSampleHemispherePDF(localDir);
res.dist = inf;
res.weight = self->radiance * rcp(res.pdf);
return res;
}
Light_EvalRes AmbientLight_eval(const Light* super,
const Sample& dg,
const Vec3fa& dir) {
AmbientLight* self = (AmbientLight *) super;
Light_EvalRes res;
res.value = self->radiance;
res.dist = inf;
res.pdf = cosineSampleHemispherePDF(max(dot(dg.Ns, dir), 0.f));
return res;
}
void AmbientLight_Constructor(AmbientLight* self,
const Vec3fa& radiance) {
Light_Constructor(&self->super);
self->radiance = radiance;
//self->super.sample = GET_FUNCTION_POINTER(AmbientLight_sample);
//self->super.eval = GET_FUNCTION_POINTER(AmbientLight_eval);
self->super.type = LIGHT_AMBIENT;
}
// Exports (called from C++)
//////////////////////////////////////////////////////////////////////////////
//! Create an ispc-side AmbientLight object
extern "C" void* AmbientLight_create() {
AmbientLight* self = (AmbientLight *) alignedUSMMalloc(sizeof(AmbientLight), 16);
AmbientLight_Constructor(self, Vec3fa(1.f));
return self;
}
//! Set the parameters of an ispc-side AmbientLight object
extern "C" void AmbientLight_set(void* super,
const Vec3fa& radiance) {
AmbientLight* self = (AmbientLight *) super;
self->radiance = radiance;
}
} // namespace embree

View file

@ -0,0 +1,23 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <math/vec.h>
#include "light.h"
namespace embree {
Light_SampleRes AmbientLight_sample(const Light* super,
const Sample& dg,
const Vec2f& s);
Light_EvalRes AmbientLight_eval(const Light* super,
const Sample& dg,
const Vec3fa& dir);
extern "C" void* AmbientLight_create();
extern "C" void AmbientLight_set(void* super,
const Vec3fa& radiance);
extern "C" void Light_destroy(Light* light);
}

View file

@ -0,0 +1,89 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "light.h"
#include <sampling.hpp>
#include <math/linearspace3.h>
namespace embree {
struct DirectionalLight {
Light super; //!< inherited light fields
LinearSpace3fa frame; //!< coordinate frame, with vz == direction *towards* the light source
Vec3fa radiance; //!< RGB color and intensity of light
float cosAngle;
//!< Angular limit of the cone light in an easier to use form: cosine of the half angle in radians
float pdf; //!< Probability to sample a direction to the light
};
// for very small cones treat as singular light, because float precision is not good enough
#define COS_ANGLE_MAX 0.99999988f
// Implementation
//////////////////////////////////////////////////////////////////////////////
Light_SampleRes DirectionalLight_sample(const Light* super,
const Sample& 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;
}
Light_EvalRes DirectionalLight_eval(const Light* super,
const Sample&,
const Vec3fa& dir) {
DirectionalLight* self = (DirectionalLight *) super;
Light_EvalRes res;
res.dist = inf;
if (self->cosAngle < COS_ANGLE_MAX && dot(self->frame.vz, dir) > self->cosAngle) {
res.value = self->radiance * self->pdf;
res.pdf = self->pdf;
} else {
res.value = Vec3fa(0.f);
res.pdf = 0.f;
}
return res;
}
// Exports (called from C++)
//////////////////////////////////////////////////////////////////////////////
//! Set the parameters of an ispc-side DirectionalLight object
extern "C" void DirectionalLight_set(void* super,
const Vec3fa& direction,
const Vec3fa& radiance,
float cosAngle) {
DirectionalLight* self = (DirectionalLight *) super;
self->frame = frame(direction);
self->radiance = radiance;
self->cosAngle = cosAngle;
self->pdf = cosAngle < COS_ANGLE_MAX ? uniformSampleConePDF(cosAngle) : inf;
}
//! Create an ispc-side DirectionalLight object
extern "C" void* DirectionalLight_create() {
DirectionalLight* self = (DirectionalLight *) alignedUSMMalloc(sizeof(DirectionalLight), 16);
Light_Constructor(&self->super);
//self->super.sample = GET_FUNCTION_POINTER(DirectionalLight_sample);
//self->super.eval = GET_FUNCTION_POINTER(DirectionalLight_eval);
self->super.type = LIGHT_DIRECTIONAL;
DirectionalLight_set(self, Vec3fa(0.f, 0.f, 1.f), Vec3fa(1.f), 1.f);
return self;
}
} // namespace embree

View file

@ -0,0 +1,23 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <math/vec.h>
namespace embree {
Light_SampleRes DirectionalLight_sample(const Light* super,
const Sample& dg,
const Vec2f& s);
Light_EvalRes DirectionalLight_eval(const Light* super,
const Sample&,
const Vec3fa& dir);
extern "C" void* DirectionalLight_create();
extern "C" void DirectionalLight_set(void* super,
const Vec3fa& direction,
const Vec3fa& radiance,
float cosAngle);
}

View file

@ -0,0 +1,21 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "light.h"
namespace embree {
Light_EvalRes Light_eval(const Light* uniform, const Sample&, const Vec3fa&) {
Light_EvalRes res;
res.value = Vec3fa(0.f);
res.dist = inf;
res.pdf = 0.f;
return res;
}
extern "C" void Light_destroy(Light* light) {
alignedUSMFree(light);
}
extern "C" void dummy() {
} // just to avoid linker warning under MacOSX
} // namespace embree

58
Framework/lights/light.h Normal file
View file

@ -0,0 +1,58 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <math/vec.h>
// #include "helper.hpp"
struct Sample;
namespace embree {
enum LightType {
LIGHT_AMBIENT,
LIGHT_POINT,
LIGHT_DIRECTIONAL,
LIGHT_SPOT,
LIGHT_DISTANT,
LIGHT_TRIANGLE,
LIGHT_QUAD,
};
struct Light {
//Light_SampleFunc sample;
//Light_EvalFunc eval;
LightType type;
};
struct Light_EvalRes {
Vec3fa value; //!< radiance that arrives at the given point (not weighted by pdf)
float dist;
float pdf; //!< probability density that the direction would have been sampled
};
//! compute the radiance, distance and pdf caused by the light source (pointed to by the given direction)
typedef Light_EvalRes (*Light_EvalFunc)(const Light* self,
const Sample& sp, /*! point to evaluate illumination for >*/
const Vec3fa& dir); /*! direction towards the light source >*/
Light_EvalRes Light_eval(const Light* self, const Sample& sp, const Vec3fa& dir);
inline void Light_Constructor(Light* self) {
//self->eval = GET_FUNCTION_POINTER(Light_eval);
}
struct Light_SampleRes {
Vec3fa weight; //!< radiance that arrives at the given point divided by pdf
Vec3fa dir; //!< direction towards the light source
float dist; //!< largest valid t_far value for a shadow ray
float pdf; //!< probability density that this sample was taken
};
//! compute the weighted radiance at a point caused by a sample on the light source
// by convention, giving (0, 0) as "random" numbers should sample the "center"
// of the light source (used by the raytracing renderers such as the OBJ renderer)
typedef Light_SampleRes (*Light_SampleFunc)(const Light* self,
const Sample& sp, /*! point to generate the sample for >*/
const Vec2f& s); /*! random numbers to generate the sample >*/
} // namespace embree

View file

@ -0,0 +1,129 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "light.h"
#include <sampling.hpp>
#include <math/linearspace3.h>
#include "helper.hpp"
namespace embree {
struct PointLight {
Light super; //!< inherited light fields
Vec3fa position; //!< light position
Vec3fa power; //!< RGB color and intensity of light
float radius; //!< defines the size of the SphereLight
};
// Implementation
//////////////////////////////////////////////////////////////////////////////
Light_SampleRes PointLight_sample(const Light* super,
const Sample& 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_EvalRes PointLight_eval(const Light* super,
const Sample& dg,
const Vec3fa& dir) {
const PointLight* self = (PointLight *) super;
Light_EvalRes res;
res.value = Vec3fa(0.f);
res.dist = inf;
res.pdf = 0.f;
if (self->radius > 0.f) {
const Vec3fa A = self->position - dg.P;
const float a = dot(dir, dir);
const float b = 2.f * dot(dir, A);
const float centerDist2 = dot(A, A);
const float c = centerDist2 - sqr(self->radius);
const float radical = sqr(b) - 4.f * a * c;
if (radical > 0.f) {
const float t_near = (b - sqrt(radical)) / (2.f * a);
const float t_far = (b + sqrt(radical)) / (2.f * a);
if (t_far > 0.0f) {
// TODO: handle interior case
res.dist = t_near;
const float sinTheta2 = sqr(self->radius) * rcp(centerDist2);
const float cosTheta = sqrt(1.f - sinTheta2);
res.pdf = uniformSampleConePDF(cosTheta);
const float invdist = rcp(t_near);
res.value = self->power * res.pdf * sqr(invdist);
}
}
}
return res;
}
// Exports (called from C++)
//////////////////////////////////////////////////////////////////////////////
//! Set the parameters of an ispc-side PointLight object
extern "C" void PointLight_set(void* super,
const Vec3fa& position,
const Vec3fa& power,
float radius) {
PointLight* self = (PointLight *) super;
self->position = position;
self->power = power;
self->radius = radius;
}
//! Create an ispc-side PointLight object
extern "C" void* PointLight_create() {
PointLight* self = (PointLight *) alignedUSMMalloc(sizeof(PointLight), 16);
Light_Constructor(&self->super);
//self->super.sample = GET_FUNCTION_POINTER(PointLight_sample);
//self->super.eval = GET_FUNCTION_POINTER(PointLight_eval);
self->super.type = LIGHT_POINT;
PointLight_set(self, Vec3fa(0.f), Vec3fa(1.f), 0.f);
return self;
}
} // namespace embree

View file

@ -0,0 +1,24 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <math/vec.h>
namespace embree {
Light_SampleRes PointLight_sample(const Light* super,
const Sample& dg,
const Vec2f& s);
Light_EvalRes PointLight_eval(const Light* super,
const Sample& dg,
const Vec3fa& dir);
extern "C" void* PointLight_create();
extern "C" void PointLight_set(void* super,
const Vec3fa& position,
const Vec3fa& power,
float radius);
}

View file

@ -0,0 +1,99 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "light.h"
#include "helper.hpp"
namespace embree {
struct QuadLight {
Light super; //!< inherited light fields
Vec3fa position; //!< world-space corner position of the light
Vec3fa edge1; //!< vectors to adjacent corners
Vec3fa edge2; //!< vectors to adjacent corners
Vec3fa radiance; //!< RGB color and intensity of the QuadLight
Vec3fa nnormal; //!< negated normal, the direction that the QuadLight is not emitting; normalized
float ppdf; // probability to sample point on light = 1/area
};
// Implementation
//////////////////////////////////////////////////////////////////////////////
Light_SampleRes QuadLight_sample(const Light* super,
const Sample& sp,
const Vec2f& s) {
const QuadLight* self = (QuadLight *) super;
Light_SampleRes res;
// res position on light with density ppdf = 1/area
// TODO: use solid angle sampling
const Vec3fa pos = self->position + self->edge1 * s.x + self->edge2 * s.y;
// extant light vector from the hit point
const Vec3fa dir = pos - sp.P;
const float dist = length(dir);
// normalized light vector
res.dir = dir / dist;
res.dist = dist;
// convert to pdf wrt. solid angle
const float cosd = dot(self->nnormal, res.dir);
res.pdf = self->ppdf * (dist * dist) / abs(cosd);
// emit only to one side
res.weight = cosd > 0.f ? self->radiance * rcp(res.pdf) : Vec3fa(0.f);
return res;
}
Light_EvalRes QuadLight_eval(const Light* super,
const Sample& dg,
const Vec3fa& dir) {
Light_EvalRes res;
res.value = Vec3fa(0, 0, 0);
res.dist = inf;
res.pdf = 0.f;
return res;
}
// Exports (called from C++)
//////////////////////////////////////////////////////////////////////////////
//! Set the parameters of an ispc-side QuadLight object
extern "C" void QuadLight_set(void* super,
const Vec3fa& position,
const Vec3fa& edge2,
const Vec3fa& edge1,
const Vec3fa& radiance) {
QuadLight* self = (QuadLight *) super;
self->position = position;
self->edge1 = edge1;
self->edge2 = edge2;
self->radiance = radiance;
const Vec3fa ndirection = cross(edge2, edge1);
self->ppdf = rcp(length(ndirection));
self->nnormal = ndirection * self->ppdf;
}
//! Create an ispc-side QuadLight object
extern "C" void* QuadLight_create() {
QuadLight* self = (QuadLight *) alignedUSMMalloc(sizeof(QuadLight), 16);
Light_Constructor(&self->super);
//self->super.sample = GET_FUNCTION_POINTER(QuadLight_sample);
self->super.type = LIGHT_QUAD;
QuadLight_set(self,
Vec3fa(0.f),
Vec3fa(1.f, 0.f, 0.f),
Vec3fa(0.f, 1.f, 0.f),
Vec3fa(1.f));
return self;
}
} // namespace embree

View file

@ -0,0 +1,24 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <math/vec.h>
namespace embree {
Light_SampleRes QuadLight_sample(const Light* super,
const Sample& sp,
const Vec2f& s);
Light_EvalRes QuadLight_eval(const Light* super,
const Sample& dg,
const Vec3fa& dir);
extern "C" void* QuadLight_create();
extern "C" void QuadLight_set(void* super,
const Vec3fa& position,
const Vec3fa& edge2,
const Vec3fa& edge1,
const Vec3fa& radiance);
}

View file

@ -0,0 +1,136 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "light.h"
#include <sampling.hpp>
#include <math/linearspace3.h>
#include "helper.hpp"
namespace embree {
struct SpotLight {
Light super; //!< inherited light fields
Vec3fa position; //!< Position of the SpotLight
LinearSpace3fa frame; //!< coordinate frame, with vz == direction that the SpotLight is emitting
Vec3fa power; //!< RGB color and intensity of the SpotLight
float cosAngleMax; //!< Angular limit of the spot in an easier to use form: cosine of the half angle in radians
float cosAngleScale; //!< 1/(cos(border of the penumbra area) - cosAngleMax); positive
float radius; //!< defines the size of the (extended) SpotLight
float diskPdf; //!< pdf of disk with radius
};
// Implementation
//////////////////////////////////////////////////////////////////////////////
Light_SampleRes SpotLight_sample(const Light* super,
const Sample& dg,
const Vec2f& s) {
const SpotLight* self = (SpotLight *) super;
Light_SampleRes res;
// extant light vector from the hit point
res.dir = self->position - dg.P;
if (self->radius > 0.0f)
res.dir = self->frame * uniformSampleDisk(self->radius, s) + res.dir;
const float dist2 = dot(res.dir, res.dir);
const float invdist = rsqrt(dist2);
// normalized light vector
res.dir = res.dir * invdist;
res.dist = dist2 * invdist;
// cosine of the negated light direction and light vector.
const float cosAngle = -dot(self->frame.vz, res.dir);
const float angularAttenuation = clamp((cosAngle - self->cosAngleMax) * self->cosAngleScale);
if (self->radius > 0.0f)
res.pdf = self->diskPdf * dist2 * abs(cosAngle);
else
res.pdf = inf; // we always take this res
// convert from power to radiance by attenuating by distance^2; attenuate by angle
res.weight = self->power * (sqr(invdist) * angularAttenuation);
return res;
}
Light_EvalRes SpotLight_eval(const Light* super,
const Sample& dg,
const Vec3fa& dir) {
const SpotLight* self = (SpotLight *) super;
Light_EvalRes res;
res.value = Vec3fa(0.0f);
res.dist = inf;
res.pdf = 0.0f;
if (self->radius > 0.0f) {
// intersect disk
const float cosAngle = -dot(dir, self->frame.vz);
if (cosAngle > self->cosAngleMax) {
// inside illuminated cone?
const Vec3fa vp = dg.P - self->position;
const float dp = dot(vp, self->frame.vz);
if (dp > 0.0f) {
// in front of light?
const float t = dp * rcp(cosAngle);
const Vec3fa vd = vp + t * dir;
if (dot(vd, vd) < sqr(self->radius)) {
// inside disk?
const float angularAttenuation = min((cosAngle - self->cosAngleMax) * self->cosAngleScale, 1.f);
const float pdf = self->diskPdf * cosAngle;
res.value = self->power * (angularAttenuation * pdf); // *sqr(t)/sqr(t) cancels
res.dist = t;
res.pdf = pdf * sqr(t);
}
}
}
}
return res;
}
// Exports (called from C++)
//////////////////////////////////////////////////////////////////////////////
//! Set the parameters of an ispc-side SpotLight object
extern "C" void SpotLight_set(void* super,
const Vec3fa& position,
const Vec3fa& direction,
const Vec3fa& power,
float cosAngleMax,
float cosAngleScale,
float radius) {
SpotLight* self = (SpotLight *) super;
self->position = position;
self->frame = frame(direction);
self->power = power;
self->cosAngleMax = cosAngleMax;
self->cosAngleScale = cosAngleScale;
self->radius = radius;
self->diskPdf = uniformSampleDiskPDF(radius);
}
//! Create an ispc-side SpotLight object
extern "C" void* SpotLight_create() {
SpotLight* self = (SpotLight *) alignedUSMMalloc(sizeof(SpotLight), 16);
Light_Constructor(&self->super);
//self->super.sample = GET_FUNCTION_POINTER(SpotLight_sample);
//self->super.eval = GET_FUNCTION_POINTER(SpotLight_eval);
self->super.type = LIGHT_SPOT;
SpotLight_set(self,
Vec3fa(0.f),
Vec3fa(0.f, 0.f, 1.f),
Vec3fa(1.f),
0.f,
100.f,
0.f);
return self;
}
} // namespace embree

View file

@ -0,0 +1,26 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <math/vec.h>
namespace embree {
Light_SampleRes SpotLight_sample(const Light* super,
const Sample& dg,
const Vec2f& s);
Light_EvalRes SpotLight_eval(const Light* super,
const Sample& dg,
const Vec3fa& dir);
extern "C" void* SpotLight_create();
extern "C" void SpotLight_set(void* super,
const Vec3fa& position,
const Vec3fa& direction,
const Vec3fa& power,
float cosAngleMax,
float cosAngleScale,
float radius);
}