nuclear@2: #include "brdf.h" nuclear@2: #include "erebus_impl.h" nuclear@2: nuclear@2: ReflAttrib::ReflAttrib() nuclear@2: : value(1), color(1, 1, 1), map(0) nuclear@2: { nuclear@2: } nuclear@2: nuclear@2: ReflAttrib::ReflAttrib(const Color &col, Texture *tex) nuclear@2: { nuclear@2: set_color(col); nuclear@2: map = tex; nuclear@2: } nuclear@2: nuclear@2: void ReflAttrib::set_value(float val) nuclear@2: { nuclear@2: value = val; nuclear@2: color = Color{val, val, val}; nuclear@2: } nuclear@2: nuclear@2: void ReflAttrib::set_color(const Color &col) nuclear@2: { nuclear@2: color = col; nuclear@2: value = color_luminance(col); nuclear@2: } nuclear@2: nuclear@2: void ReflAttrib::set_map(Texture *tex) nuclear@2: { nuclear@2: map = tex; nuclear@2: } nuclear@2: nuclear@2: Texture *ReflAttrib::get_map() const nuclear@2: { nuclear@2: return map; nuclear@2: } nuclear@2: nuclear@2: float ReflAttrib::get_value() const nuclear@2: { nuclear@2: return value; nuclear@2: } nuclear@2: nuclear@2: float ReflAttrib::get_value(float u, float v) const nuclear@2: { nuclear@2: return map ? value * color_luminance(map->lookup(u, v)) : value; nuclear@2: } nuclear@2: nuclear@2: const Color &ReflAttrib::get_color() const nuclear@2: { nuclear@2: return color; nuclear@2: } nuclear@2: nuclear@2: Color ReflAttrib::get_color(float u, float v) const nuclear@2: { nuclear@2: return map ? color * map->lookup(u, v) : color; nuclear@2: } nuclear@2: nuclear@2: // ---- class Reflectance ---- nuclear@2: ReflAttrib Reflectance::def_attrib; nuclear@2: nuclear@2: Reflectance::Reflectance() nuclear@2: { nuclear@2: set_default_attribs(); nuclear@2: } nuclear@2: nuclear@2: void Reflectance::set_attrib(const char *name, const Color &color, Texture *tex) nuclear@2: { nuclear@2: attrib[name] = ReflAttrib{color, tex}; nuclear@2: } nuclear@2: nuclear@2: ReflAttrib &Reflectance::get_attrib(const char *name) nuclear@2: { nuclear@2: auto it = attrib.find(name); nuclear@2: if(it == attrib.end()) { nuclear@2: return def_attrib; nuclear@2: } nuclear@2: return it->second; nuclear@2: } nuclear@2: nuclear@2: const ReflAttrib &Reflectance::get_attrib(const char *name) const nuclear@2: { nuclear@2: auto it = attrib.find(name); nuclear@2: if(it == attrib.end()) { nuclear@2: return def_attrib; nuclear@2: } nuclear@2: return it->second; nuclear@2: } nuclear@2: nuclear@2: float Reflectance::get_attrib_value(const char *name) const nuclear@2: { nuclear@2: return get_attrib(name).get_value(); nuclear@2: } nuclear@2: nuclear@2: float Reflectance::get_attrib_value(const char *name, float u, float v) const nuclear@2: { nuclear@2: return get_attrib(name).get_value(u, v); nuclear@2: } nuclear@2: nuclear@2: Color Reflectance::get_attrib_color(const char *name) const nuclear@2: { nuclear@2: return get_attrib(name).get_color(); nuclear@2: } nuclear@2: nuclear@2: Color Reflectance::get_attrib_color(const char *name, float u, float v) const nuclear@2: { nuclear@2: return get_attrib(name).get_color(u, v); nuclear@2: } nuclear@2: nuclear@2: float Reflectance::sample(const Vector3 &norm, const Vector3 &outdir, Vector3 *indir) const nuclear@2: { nuclear@2: *indir = sample_dir(norm, outdir); nuclear@2: return eval(norm, outdir, *indir); nuclear@2: } nuclear@2: nuclear@2: // --- class LambertRefl --- nuclear@2: nuclear@2: void LambertRefl::set_default_attribs() nuclear@2: { nuclear@2: set_attrib("color", Color(1, 1, 1)); nuclear@2: } nuclear@2: nuclear@2: Vector3 LambertRefl::sample_dir(const Vector3 &norm, const Vector3 &outdir) const nuclear@2: { nuclear@2: Vector3 dir = Vector3{randf(-1, 1), randf(-1, 1), randf(-1, 1)}.normalized(); nuclear@2: return dot_product(dir, norm) < 0.0 ? -dir : dir; nuclear@2: } nuclear@2: nuclear@2: float LambertRefl::eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const nuclear@2: { nuclear@2: return dot_product(norm, outdir); nuclear@2: }