#pragma once #include "material.hpp" /*! \brief A procedural material. */ class WoodMaterial : public Material { Vector kinks[20]; public: WoodMaterial() :Material(Vector(0.7f, 0.5f, 0.3f), Vector(0.2f, 0.2f, 0.2f), 4.0f) { for(int k=0; k<20; k++) kinks[k] = Vector(20.0f - 40.0f * rand() / RAND_MAX, -15.5f - 4.0f * rand() / RAND_MAX, 15.0f - 20.0f * rand() / RAND_MAX); } Vector getProceduralDiffuseBrdf(const Vector& atPoint) const { float x2 = atPoint.x * atPoint.x; float y2 = atPoint.y * atPoint.y; float d = sqrtf(x2 + y2) * 6.0f; for(int k=0; k < 20; k++) { Vector diff; diff.setDifference(kinks[k], atPoint); d *= 1.0f - (1.0f / (diff.norm2() + 1.0f)); } d *= 0.5f; float c = 1.0f - (1.0f + cosf(d)) / 2.0f; c *= c; //c *= c; c = 1.0f - c; c *= 0.25f; return Vector(0.35f + c, 0.15f + c, c); } void proceduralScatteringProbability (const Vector& atPoint, const Vector& in, Vector& out, const Vector& normal, Vector& result) const { float nDotOut = normal * out; float nDotIn = - (normal * in); if ( nDotOut < 0) { result = Vector::RGBBLACK; return; } // add diffuse part result = getProceduralDiffuseBrdf(atPoint); // add specular using max Phong shading Vector idealReflected; idealReflected.setIdealReflectedDirection (in, normal); float dotProduct = idealReflected* out; if(dotProduct > 0) { float scale = (float)pow (dotProduct, ns) * (ns + 2.0f) * 0.5f / 3.14159265358979323846f ; if(nDotOut > nDotIn) scale /= nDotOut; else scale /= nDotIn; result += ks * scale; } result *= nDotOut; } };