#pragma once #include "Maths.h" namespace dae { namespace BRDF { /** * \param kd Diffuse Reflection Coefficient * \param cd Diffuse Color * \return Lambert Diffuse Color */ static ColorRGB Lambert(float kd, const ColorRGB &cd) { return (kd / PI) * cd; } static ColorRGB Lambert(const ColorRGB &kd, const ColorRGB &cd) { return (kd * PI) * cd; } /** * \brief todo * \param ks Specular Reflection Coefficient * \param exp Phong Exponent * \param l Incoming (incident) Light Direction * \param v View Direction * \param n Normal of the Surface * \return Phong Specular Color */ static ColorRGB Phong(float ks, float exp, const Vector3 &l, const Vector3 &v, const Vector3 &n) { Vector3 reflect{l - 2 * Vector3::Dot(n, l) * n}; float cosAngle{Vector3::Dot(reflect, v)}; return {ks * powf(std::max(0.f, cosAngle), exp) * colors::White}; } /** * \brief BRDF Fresnel Function >> Schlick * \param h Normalized Halfvector between View and Light directions * \param v Normalized View direction * \param f0 Base reflectivity of a surface based on IOR (Indices Of Refrection), this is different for Dielectrics (Non-Metal) and Conductors (Metal) * \return */ static ColorRGB FresnelFunction_Schlick(const Vector3 &h, const Vector3 &v, const ColorRGB &f0) { const float base = std::pow(1 - Vector3::Dot(h, v), 5); auto returnValue{f0 + (colors::White - f0) * base}; return returnValue; } /** * \brief BRDF NormalDistribution >> Trowbridge-Reitz GGX (UE4 implemetation - squared(roughness)) * \param n Surface normal * \param h Normalized half vector * \param roughness Roughness of the material * \return BRDF Normal Distribution Term using Trowbridge-Reitz GGX */ static float NormalDistribution_GGX(const Vector3 &n, const Vector3 &h, float roughness) { const float a = roughness * roughness; const float a2 = a * a; const float dot{Vector3::Dot(n, h)}; const float div{dot * dot * (a2 - 1) + 1}; return a2 / (M_PI * div * div); } /** * \brief BRDF Geometry Function >> Schlick GGX (Direct Lighting + UE4 implementation - squared(roughness)) * \param n Normal of the surface * \param v Normalized view direction * \param roughness Roughness of the material * \return BRDF Geometry Term using SchlickGGX */ static float GeometryFunction_SchlickGGX(const Vector3 &n, const Vector3 &v, float roughness) { float cosAngle{ Vector3::Dot(n,v) }; float k{ (roughness + 1) * (roughness + 1) / 8 }; return {cosAngle / (cosAngle * (1 - k) + k) }; } /** * \brief BRDF Geometry Function >> Smith (Direct Lighting) * \param n Normal of the surface * \param v Normalized view direction * \param l Normalized light direction * \param roughness Roughness of the material * \return BRDF Geometry Term using Smith (> SchlickGGX(n,v,roughness) * SchlickGGX(n,l,roughness)) */ static float GeometryFunction_Smith(const Vector3 &n, const Vector3 &v, const Vector3 &l, float roughness) { return { GeometryFunction_SchlickGGX(n,v,roughness) * GeometryFunction_SchlickGGX(n,l,roughness) }; } } }