cloudy-raytracer/shader/marbleshader.cpp

111 lines
3.1 KiB
C++

#include "marbleshader.h"
Color MarbleShader::shade(const Scene &scene, const Ray &ray) const
{ // Get the intersection point of the ray and the object
Vector3d intersection = ray.origin + ray.direction * ray.length;
// Create a noise value based on the intersection point
float noise = getMarbleNoise(intersection, scale);
// return noise * Color(1, 1, 1);
// Use the noise value to determine the color of the marble
Color color = baseColor;
if (noise > 0.5)
{
float fade = 1 - (noise - 0.5f) * 2 * edgeFade;
fade = clamp(fade, 0, 1);
color = color + (veinColor - baseColor) * fade;
}
// Get the lighting for the point
// for (const auto &light: scene.lights())
// {
// Light::Illumination illum = light->illuminate(scene, ray);
// color = color * illum.color;
// }
return color;
}
MarbleShader::MarbleShader(Color baseColor, Color veinColor, float scale, float edgeFade)
: baseColor(baseColor), veinColor(veinColor), scale(scale), edgeFade(edgeFade)
{
}
float MarbleShader::getMarbleNoise(Vector3d position, float scale) const
{
float x = position.x * scale;
float y = position.y * scale;
float z = position.z * scale;
// Calculate the integer coordinates of the point
int xi = (int)floor(x);
int yi = (int)floor(y);
int zi = (int)floor(z);
int xo = xi + 1;
int yo = yi + 1;
int zo = zi + 1;
// Calculate colors of the corners in a three-dimensional vector
float cube[2][2][2];
srand(xi + yi * 57 + zi * 997);
cube[0][0][0] = rand() / (float)RAND_MAX;
srand(xo + yi * 57 + zi * 997);
cube[1][0][0] = rand() / (float)RAND_MAX;
srand(xi + yo * 57 + zi * 997);
cube[0][1][0] = rand() / (float)RAND_MAX;
srand(xo + yo * 57 + zi * 997);
cube[1][1][0] = rand() / (float)RAND_MAX;
srand(xi + yi * 57 + zo * 997);
cube[0][0][1] = rand() / (float)RAND_MAX;
srand(xo + yi * 57 + zo * 997);
cube[1][0][1] = rand() / (float)RAND_MAX;
srand(xi + yo * 57 + zo * 997);
cube[0][1][1] = rand() / (float)RAND_MAX;
srand(xo + yo * 57 + zo * 997);
cube[1][1][1] = rand() / (float)RAND_MAX;
// Calculate the fractional part of the point
float xf = x - xi;
float yf = y - yi;
float zf = z - zi;
// Interpolate along x
float dot1 = smoothstep(cube[0][0][0], cube[1][0][0], xf);
float dot2 = smoothstep(cube[0][1][0], cube[1][1][0], xf);
float dot3 = smoothstep(cube[0][0][1], cube[1][0][1], xf);
float dot4 = smoothstep(cube[0][1][1], cube[1][1][1], xf);
// Interpolate along y
float dot5 = smoothstep(dot1, dot2, yf);
float dot6 = smoothstep(dot3, dot4, yf);
// Interpolate along z
float dot7 = smoothstep(dot5, dot6, zf);
return dot7;
}
float MarbleShader::smoothstep(float edge0, float edge1, float x) const {
float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3 - 2 * t);
}
float MarbleShader::lerp(float a, float b, float t) const {
return a + t * (b - a);
}
float MarbleShader::clamp(float x, float lower, float upper) const {
return std::max(lower, std::min(x, upper));
}