Adds rich transparency for shaders and implements if for light calculations
This commit is contained in:
parent
dcae587b8c
commit
17fd35fe76
11 changed files with 120 additions and 26 deletions
|
@ -20,8 +20,10 @@ Light::Illumination PointLight::illuminate(Scene const &scene, Ray const &ray) c
|
||||||
lightRay.length = distance - LGT_EPS;
|
lightRay.length = distance - LGT_EPS;
|
||||||
|
|
||||||
// If the target is not in shadow...
|
// If the target is not in shadow...
|
||||||
if (!scene.findOcclusion(lightRay))
|
if (!scene.findOcclusion(lightRay)) {
|
||||||
// ... compute the attenuation and light color
|
// ... compute the attenuation and light color
|
||||||
illum.color = 1.0f / (distance * distance) * this->color * this->intensity;
|
Color rayTransparency = scene.getTransparency(lightRay, distance);
|
||||||
|
illum.color = 1.0f / (distance * distance) * this->color * this->intensity * rayTransparency;
|
||||||
|
}
|
||||||
return illum;
|
return illum;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,8 @@ Light::Illumination SpotLight::illuminate(Scene const &scene, Ray const &ray) co
|
||||||
// ... and not in shadow ...
|
// ... and not in shadow ...
|
||||||
if (!scene.findOcclusion(lightRay)) {
|
if (!scene.findOcclusion(lightRay)) {
|
||||||
// ... compute the attenuation and light color ...
|
// ... compute the attenuation and light color ...
|
||||||
illum.color = 1.0f / (distance * distance) * this->color * this->intensity;
|
Color rayTransparency = scene.getTransparency(lightRay, distance);
|
||||||
|
illum.color = 1.0f / (distance * distance) * this->color * this->intensity * rayTransparency;
|
||||||
// ... then compute the falloff towards the edge of the cone
|
// ... then compute the falloff towards the edge of the cone
|
||||||
if (this->alphaMin < alpha)
|
if (this->alphaMin < alpha)
|
||||||
illum.color *= 1.0f - (alpha - this->alphaMin) / (this->alphaMax - this->alphaMin);
|
illum.color *= 1.0f - (alpha - this->alphaMin) / (this->alphaMax - this->alphaMin);
|
||||||
|
|
|
@ -25,7 +25,9 @@ Light::Illumination SunLight::illuminate(Scene const &scene, Ray const &ray) con
|
||||||
// Look at angleIntensity of light
|
// Look at angleIntensity of light
|
||||||
float angleIntensity = dotProduct(-ray.normal,
|
float angleIntensity = dotProduct(-ray.normal,
|
||||||
this->direction); // 0 if light is behind surface, 1 if light is in front of surface
|
this->direction); // 0 if light is behind surface, 1 if light is in front of surface
|
||||||
illum.color = this->color * this->intensity * angleIntensity;
|
|
||||||
|
Color rayTransparency = scene.getTransparency(lightRay, INFINITY);
|
||||||
|
illum.color = this->color * this->intensity * angleIntensity * rayTransparency;
|
||||||
}
|
}
|
||||||
return illum;
|
return illum;
|
||||||
}
|
}
|
|
@ -221,3 +221,27 @@ std::unique_ptr<Node> FastScene::build(Vector3d const &minimumBounds, Vector3d c
|
||||||
node->child[1] = this->build(minimumSplit, maximumBounds, rightPrimitives, depth);
|
node->child[1] = this->build(minimumSplit, maximumBounds, rightPrimitives, depth);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color FastScene::getTransparency(Ray &ray, float maxDistance) const
|
||||||
|
{
|
||||||
|
// TODO: Not taking advantage of the tree structure!
|
||||||
|
|
||||||
|
ray.length = maxDistance;
|
||||||
|
ray.primitive = nullptr;
|
||||||
|
|
||||||
|
Color transparency(1, 1, 1);
|
||||||
|
for (auto i: this->primitives())
|
||||||
|
{
|
||||||
|
Ray r = ray;
|
||||||
|
if (i->intersect(r) && r.length < maxDistance && i->shader()->isTransparent())
|
||||||
|
{
|
||||||
|
r.length = maxDistance; // To allow transparency to be calculated partially for objects
|
||||||
|
|
||||||
|
Color t = i->shader()->transparency(*this, r);
|
||||||
|
transparency.r *= t.r;
|
||||||
|
transparency.g *= t.g;
|
||||||
|
transparency.b *= t.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transparency;
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
// Raytracing functions
|
// Raytracing functions
|
||||||
bool findIntersection(Ray &ray) const override;
|
bool findIntersection(Ray &ray) const override;
|
||||||
bool findOcclusion(Ray &ray) const override;
|
bool findOcclusion(Ray &ray) const override;
|
||||||
|
Color getTransparency(Ray &ray, float maxDistance) const override;
|
||||||
int countNodeIntersections(const Ray &ray) const;
|
int countNodeIntersections(const Ray &ray) const;
|
||||||
|
|
||||||
// Setup functions
|
// Setup functions
|
||||||
|
|
|
@ -41,6 +41,7 @@ public:
|
||||||
Color traceRay(Ray &ray) const;
|
Color traceRay(Ray &ray) const;
|
||||||
virtual bool findIntersection(Ray &ray) const = 0;
|
virtual bool findIntersection(Ray &ray) const = 0;
|
||||||
virtual bool findOcclusion(Ray &ray) const = 0;
|
virtual bool findOcclusion(Ray &ray) const = 0;
|
||||||
|
virtual Color getTransparency(Ray &ray, float maxDistance) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Color backgroundColor;
|
Color backgroundColor;
|
||||||
|
|
|
@ -2,16 +2,40 @@
|
||||||
#include "primitive/primitive.h"
|
#include "primitive/primitive.h"
|
||||||
#include "shader/shader.h"
|
#include "shader/shader.h"
|
||||||
|
|
||||||
bool SimpleScene::findIntersection(Ray &ray) const {
|
bool SimpleScene::findIntersection(Ray &ray) const
|
||||||
bool hit = false;
|
{
|
||||||
for (auto i : this->primitives())
|
bool hit = false;
|
||||||
hit |= i->intersect(ray);
|
for (auto i: this->primitives())
|
||||||
return hit;
|
hit |= i->intersect(ray);
|
||||||
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SimpleScene::findOcclusion(Ray &ray) const {
|
bool SimpleScene::findOcclusion(Ray &ray) const
|
||||||
for (auto i : this->primitives())
|
{
|
||||||
if (i->intersect(ray) && !i->shader()->isTransparent())
|
for (auto i: this->primitives())
|
||||||
return true;
|
if (i->intersect(ray) && !i->shader()->isTransparent())
|
||||||
return false;
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color SimpleScene::getTransparency(Ray &ray, float maxDistance) const
|
||||||
|
{
|
||||||
|
ray.length = maxDistance;
|
||||||
|
ray.primitive = nullptr;
|
||||||
|
|
||||||
|
Color transparency(1, 1, 1);
|
||||||
|
for (auto i: this->primitives())
|
||||||
|
{
|
||||||
|
Ray r = ray;
|
||||||
|
if (i->intersect(r) && r.length < maxDistance && i->shader()->isTransparent())
|
||||||
|
{
|
||||||
|
r.length = maxDistance; // To allow transparency to be calculated partially for objects
|
||||||
|
|
||||||
|
Color t = i->shader()->transparency(*this, r);
|
||||||
|
transparency.r *= t.r;
|
||||||
|
transparency.g *= t.g;
|
||||||
|
transparency.b *= t.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transparency;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ public:
|
||||||
// Raytracing functions
|
// Raytracing functions
|
||||||
bool findIntersection(Ray &ray) const override;
|
bool findIntersection(Ray &ray) const override;
|
||||||
bool findOcclusion(Ray &ray) const override;
|
bool findOcclusion(Ray &ray) const override;
|
||||||
|
Color getTransparency(Ray &ray, float maxDistance) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "scene/scene.h"
|
#include "scene/scene.h"
|
||||||
#include "shader/refractionshader.h"
|
#include "shader/refractionshader.h"
|
||||||
|
|
||||||
RefractionShader::RefractionShader(float indexInside, float indexOutside, Color const &objectColor, float lightLoss) : indexInside(
|
RefractionShader::RefractionShader(float indexInside, float indexOutside, Color const &objectColor, float lightLoss)
|
||||||
|
: indexInside(
|
||||||
indexInside), indexOutside(indexOutside), objectColor(objectColor), lightLoss(lightLoss)
|
indexInside), indexOutside(indexOutside), objectColor(objectColor), lightLoss(lightLoss)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -52,14 +53,36 @@ Color RefractionShader::shade(Scene const &scene, Ray const &ray) const
|
||||||
|
|
||||||
// Send out a new refracted ray into the scene
|
// Send out a new refracted ray into the scene
|
||||||
Color hitColor = scene.traceRay(refractionRay);
|
Color hitColor = scene.traceRay(refractionRay);
|
||||||
|
|
||||||
// Calculate light lost
|
|
||||||
float lightRemaining = 1;
|
float lightRemaining = 1;
|
||||||
if (refractionRay.primitive == ray.primitive) lightRemaining = 1 - lightLoss + exp(-refractionRay.length / 10) * lightLoss;
|
if (ray.primitive == refractionRay.primitive) lightRemaining = remainingLightIntensity(refractionRay.length);
|
||||||
|
|
||||||
return hitColor * objectColor * lightRemaining;
|
return hitColor * objectColor * lightRemaining;
|
||||||
}
|
}
|
||||||
return Color(0.0f, 0.0f, 0.0f);
|
return Color(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float RefractionShader::remainingLightIntensity(float distanceThroughObject) const
|
||||||
|
{
|
||||||
|
return 1 - lightLoss + exp(-distanceThroughObject / 10) * lightLoss;
|
||||||
|
}
|
||||||
|
|
||||||
bool RefractionShader::isTransparent() const
|
bool RefractionShader::isTransparent() const
|
||||||
{ return true; }
|
{ return true; }
|
||||||
|
|
||||||
|
Color RefractionShader::transparency(const Scene &scene, const Ray &ray) const
|
||||||
|
{
|
||||||
|
// Determine length through the object
|
||||||
|
Ray lengthRay = ray;
|
||||||
|
// Reset the ray
|
||||||
|
lengthRay.length = INFINITY;
|
||||||
|
lengthRay.primitive = nullptr;
|
||||||
|
lengthRay.origin = ray.origin + (ray.length + REFR_EPS) * ray.direction;
|
||||||
|
|
||||||
|
scene.traceRay(lengthRay);
|
||||||
|
|
||||||
|
float transparencyDistance = std::min(ray.length, lengthRay.length);
|
||||||
|
float lightRemaining = 1;
|
||||||
|
if (ray.primitive == lengthRay.primitive) lightRemaining = remainingLightIntensity(transparencyDistance);
|
||||||
|
|
||||||
|
return objectColor * lightRemaining;
|
||||||
|
}
|
||||||
|
|
|
@ -14,12 +14,15 @@ public:
|
||||||
Color shade(Scene const &scene, Ray const &ray) const override;
|
Color shade(Scene const &scene, Ray const &ray) const override;
|
||||||
|
|
||||||
bool isTransparent() const override;
|
bool isTransparent() const override;
|
||||||
|
Color transparency(Scene const &scene, Ray const &ray) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float indexInside;
|
float indexInside;
|
||||||
float indexOutside;
|
float indexOutside;
|
||||||
float lightLoss;
|
float lightLoss;
|
||||||
Color objectColor;
|
Color objectColor;
|
||||||
|
|
||||||
|
float remainingLightIntensity(float distanceThroughObject) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,17 +7,29 @@
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
class Scene;
|
class Scene;
|
||||||
|
|
||||||
class Shader {
|
class Shader
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
// Constructor / Desctructor
|
// Constructor / Desctructor
|
||||||
Shader() = default;
|
Shader() = default;
|
||||||
virtual ~Shader() = default;
|
|
||||||
|
|
||||||
// Get
|
virtual ~Shader() = default;
|
||||||
virtual bool isTransparent() const { return false; }
|
|
||||||
|
|
||||||
// Shader functions
|
// Get
|
||||||
virtual Color shade(Scene const &scene, Ray const &ray) const = 0;
|
virtual bool isTransparent() const
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Especially used for lighting calculations.
|
||||||
|
* @brief Returns the light let through the shader in opposite direction of the given ray.
|
||||||
|
* @param ray Origin and direction of the desired path.
|
||||||
|
* @return 0 if the shader is opaque, 1 if the shader is transparent, for each color channel.
|
||||||
|
*/
|
||||||
|
virtual Color transparency(Scene const &scene, Ray const &ray) const
|
||||||
|
{ return isTransparent() ? Color(1, 1, 1) : Color(0, 0, 0); }
|
||||||
|
|
||||||
|
// Shader functions
|
||||||
|
virtual Color shade(Scene const &scene, Ray const &ray) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue