#include #include "toneshader.h" ToneShader::ToneShader(std::shared_ptr light, const Color &highlightColor, const Color &midtoneColor, const Color &shadowColor, float edgeFade) : light(light), highlightColor(highlightColor), midtoneColor(midtoneColor), shadowColor(shadowColor), edgeFade(edgeFade) { } Color ToneShader::shade(const Scene &scene, const Ray &ray) const { float brightness; // Look at light Light::Illumination illum; illum = light->illuminate(scene, ray); if (illum.color.r < 0.01f) // Light does not reach the surface brightness = 0; else // Look at angle of light brightness = dotProduct(illum.direction, -ray.normal); // 0 if light is behind surface, 1 if light is in front of surface // Get the tone color base on the brightness float const HIGHLIGHT_THRESHOLD = 0.95f; float const MIDTONE_HIGHLIGHT_THRESHOLD = HIGHLIGHT_THRESHOLD - 0.2f * edgeFade; float const SHADOW_MIDTONE_THRESHOLD = 0.01f; float const MIDTONE_THRESHOLD = SHADOW_MIDTONE_THRESHOLD + 0.4f * edgeFade; // Used for transitions std::random_device dev; std::uniform_real_distribution randomDistribution(0, 1); Color tone; if (brightness > HIGHLIGHT_THRESHOLD) { tone = highlightColor; } else if (brightness > MIDTONE_HIGHLIGHT_THRESHOLD) { float transition = (brightness - MIDTONE_HIGHLIGHT_THRESHOLD) / (HIGHLIGHT_THRESHOLD - MIDTONE_HIGHLIGHT_THRESHOLD); tone = highlightColor * transition + midtoneColor * (1 - transition); } else if (brightness > MIDTONE_THRESHOLD) { tone = midtoneColor; } else if (brightness > SHADOW_MIDTONE_THRESHOLD) { float transition = (brightness - SHADOW_MIDTONE_THRESHOLD) / (MIDTONE_THRESHOLD - SHADOW_MIDTONE_THRESHOLD); tone = midtoneColor * transition + shadowColor * (1 - transition); } else { tone = shadowColor; } return tone; }