accelerated-raytracer/src/RenderMaterial.cpp

57 lines
3.7 KiB
C++

#include "RenderMaterial.h"
namespace raytry {
RenderMaterial::RenderMaterial(QColor materialColor) : diffuseColor{materialColor}, ambientIntensity{0.1f}, diffuseIntensity{0.75f}, specularIntensity{0.15f}, specularFalloff{10.0f}, reflectivity{0}, transparency{0}, refractionIndex{0} {
ambientColor = mixColor(materialColor, 0.25f);
specularColor = addColors({204, 204, 204}, mixColor(materialColor, 0.2f));
}
RenderMaterial::RenderMaterial(float ambientIntensity, const QColor &ambientColor, float diffuseIntensity, const QColor &diffuseColor, float specularIntensity, float specularFalloff, const QColor &specularColor) : ambientIntensity(ambientIntensity), ambientColor(ambientColor), diffuseIntensity(diffuseIntensity), diffuseColor(diffuseColor), specularIntensity(specularIntensity), specularFalloff(specularFalloff), specularColor(specularColor), reflectivity{0}, transparency{0}, refractionIndex{0} {
assert(ambientIntensity >= 0 && ambientIntensity <= 1);
assert(diffuseIntensity >= 0 && diffuseIntensity <= 1);
assert(specularIntensity >= 0 && specularIntensity <= 1);
assert(qFuzzyCompare(1.0f, ambientIntensity + diffuseIntensity + specularIntensity));
}
RenderMaterial::RenderMaterial(float ambientIntensity, const QColor &ambientColor, float diffuseIntensity, const QColor &diffuseColor, float specularIntensity, float specularFalloff, const QColor &specularColor, float reflectivity, float transparency, float refractionIndex) : ambientIntensity(ambientIntensity), ambientColor(ambientColor), diffuseIntensity(diffuseIntensity), diffuseColor(diffuseColor), specularIntensity(specularIntensity), specularFalloff(specularFalloff), specularColor(specularColor), reflectivity(reflectivity), transparency(transparency), refractionIndex(refractionIndex) {
assert(ambientIntensity >= 0 && ambientIntensity <= 1);
assert(diffuseIntensity >= 0 && diffuseIntensity <= 1);
assert(specularIntensity >= 0 && specularIntensity <= 1);
assert(qFuzzyCompare(1.0f, ambientIntensity + diffuseIntensity + specularIntensity));
}
std::optional<Ray> RenderMaterial::refractionRay(const Ray &incoming, const QVector3D &hitpoint, const QVector3D &normal) const {
// source: https://www.scratchapixel.com/code.php?id=32&origin=/lessons/3d-basic-rendering/phong-shader-BRDF
float cosi = std::clamp(QVector3D::dotProduct(incoming.directionVec, normal), -1.0f, 1.0f);
float etai = 1, etat = refractionIndex;
QVector3D n = normal;
if (cosi < 0) { cosi = -cosi; } else { std::swap(etai, etat); n= -normal; }
float eta = etai / etat;
float k = 1 - eta * eta * (1 - cosi * cosi);
if (k < 0) {
return std::nullopt;
} else {
return std::make_optional<Ray>(hitpoint, eta * incoming.directionVec + (eta * cosi - sqrtf(k)) * n);
}
}
Ray RenderMaterial::reflectionRay(const Ray &incoming, const QVector3D &hitpoint, const QVector3D &normal) const {
// source: https://www.scratchapixel.com/code.php?id=32&origin=/lessons/3d-basic-rendering/phong-shader-BRDF
return {hitpoint, incoming.directionVec - (2 * QVector3D::dotProduct(incoming.directionVec, normal) * normal)};
}
QColor mixColor(QColor input, float intensity) {
input.setRedF(input.redF() * intensity);
input.setGreenF(input.greenF() * intensity);
input.setBlueF(input.blueF() * intensity);
return input;
}
QColor addColors(QColor color1, const QColor& color2) {
color1.setRedF(color1.redF() + color2.redF());
color1.setGreenF(color1.greenF() + color2.greenF());
color1.setBlueF(color1.blueF() + color2.blueF());
return color1;
}
}