57 lines
3.7 KiB
C++
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;
|
|
}
|
|
}
|