112 lines
3.1 KiB
C++
112 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));
|
||
|
}
|