Colored refraction shader

This commit is contained in:
Maximilian Giller 2023-01-24 19:59:13 +01:00
parent 7ec5a8a5f4
commit 3b76969ff2
2 changed files with 63 additions and 51 deletions

View file

@ -1,51 +1,60 @@
#include "scene/scene.h" #include "scene/scene.h"
#include "shader/refractionshader.h" #include "shader/refractionshader.h"
RefractionShader::RefractionShader(float indexInside, float indexOutside) : indexInside(indexInside), indexOutside(indexOutside) {} RefractionShader::RefractionShader(float indexInside, float indexOutside, Color const &objectColor) : indexInside(
indexInside), indexOutside(indexOutside), objectColor(objectColor)
{}
Color RefractionShader::shade(Scene const &scene, Ray const &ray) const { Color RefractionShader::shade(Scene const &scene, Ray const &ray) const
// Circumvent getting environment map color into the mix {
if (ray.getRemainingBounces() > 0) { // Circumvent getting environment map color into the mix
// Get the normal of the primitive which was hit if (ray.getRemainingBounces() > 0)
Vector3d normalVector = ray.normal; {
// Get the normal of the primitive which was hit
Vector3d normalVector = ray.normal;
// Calculate the index of refraction // Calculate the index of refraction
float refractiveIndex = indexOutside / indexInside; float refractiveIndex = indexOutside / indexInside;
// What if we are already inside the object? // What if we are already inside the object?
if (dotProduct(normalVector, ray.direction) > 0) { if (dotProduct(normalVector, ray.direction) > 0)
normalVector = -normalVector; {
refractiveIndex = indexInside / indexOutside; normalVector = -normalVector;
refractiveIndex = indexInside / indexOutside;
}
// Using the notation from the lecture
float cosineTheta = dotProduct(normalVector, -ray.direction);
float cosinePhi = std::sqrt(1 + refractiveIndex * refractiveIndex * (cosineTheta * cosineTheta - 1));
// Calculate t, the new ray direction
Vector3d t = refractiveIndex * ray.direction + (refractiveIndex * cosineTheta - cosinePhi) * normalVector;
// Create the refraction ray
Ray refractionRay = ray;
// Reset the ray
refractionRay.length = INFINITY;
refractionRay.primitive = nullptr;
// Check whether it is a refraction.
if (dotProduct(t, normalVector) <= 0.0)
{
refractionRay.origin = ray.origin + (ray.length + REFR_EPS) * ray.direction;
refractionRay.direction = normalized(t);
} else
{ // Otherwise, it is a total reflection.
refractionRay.origin = ray.origin + (ray.length - REFR_EPS) * ray.direction;
// Next we get the reflection vector
Vector3d const reflectionVector =
ray.direction - 2.0f * dotProduct(normalVector, ray.direction) * normalVector;
// Change the ray direction and origin
refractionRay.direction = normalized(reflectionVector);
}
// Send out a new refracted ray into the scene
return scene.traceRay(refractionRay) * objectColor;
} }
return Color(0.0f, 0.0f, 0.0f);
// Using the notation from the lecture
float cosineTheta = dotProduct(normalVector, -ray.direction);
float cosinePhi = std::sqrt(1 + refractiveIndex * refractiveIndex * (cosineTheta * cosineTheta - 1));
// Calculate t, the new ray direction
Vector3d t = refractiveIndex * ray.direction + (refractiveIndex * cosineTheta - cosinePhi) * normalVector;
// Create the refraction ray
Ray refractionRay = ray;
// Reset the ray
refractionRay.length = INFINITY;
refractionRay.primitive = nullptr;
// Check whether it is a refraction.
if (dotProduct(t, normalVector) <= 0.0) {
refractionRay.origin = ray.origin + (ray.length + REFR_EPS) * ray.direction;
refractionRay.direction = normalized(t);
} else { // Otherwise, it is a total reflection.
refractionRay.origin = ray.origin + (ray.length - REFR_EPS) * ray.direction;
// Next we get the reflection vector
Vector3d const reflectionVector = ray.direction - 2.0f * dotProduct(normalVector, ray.direction) * normalVector;
// Change the ray direction and origin
refractionRay.direction = normalized(reflectionVector);
}
// Send out a new refracted ray into the scene
return scene.traceRay(refractionRay);
}
return Color(0.0f, 0.0f, 0.0f);
} }
bool RefractionShader::isTransparent() const { return true; } bool RefractionShader::isTransparent() const
{ return true; }

View file

@ -3,19 +3,22 @@
#include "shader/shader.h" #include "shader/shader.h"
class RefractionShader : public Shader { class RefractionShader : public Shader
{
public: public:
// Constructor // Constructor
RefractionShader(float indexInside, float indexOutside); RefractionShader(float indexInside, float indexOutside, Color const &objectColor = Color(1, 1, 1));
// Shader functions // Shader functions
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;
private: private:
float indexInside; float indexInside;
float indexOutside; float indexOutside;
Color objectColor;
}; };
#endif #endif