From a13dcac22897b846ab0dab50ab1a040ea52ed25b Mon Sep 17 00:00:00 2001 From: DavidBluecame Date: Tue, 26 Jan 2016 14:36:52 +0100 Subject: [PATCH] Oren Nayar workaround for white/black dots when using bump texture Using bump textures and Oren Nayar diffuse method causes sometimes white/black dots. Reported in: http://yafaray.org/node/707 I don't yet fully understand the Oren Nayar method, but I suppose the output of the algorithm should be limited to [0..1] values. However the formula as currently implemented allows values outside that range. From my tests, it seems that when using bump mapping sometimes the output of the Oren Nayar is way out of the [0..1] range, causing the black and white dots. I don't know why is that the case, is it a problem in our implementation of Oren Nayar? I tried other implementation but had similar or worse problems. So, in this case, I'll keep the original Oren Nayar implementation and add a simple workaround, putting limits to the output so it always stays in the range [0..1]. However, this probably would need further review to understand why it happens? --- src/materials/coatedglossy.cc | 5 +++-- src/materials/glossy.cc | 4 ++-- src/materials/glossy2.cc | 4 ++-- src/materials/shinydiffuse.cc | 6 ++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/materials/coatedglossy.cc b/src/materials/coatedglossy.cc index 24f5adbb..45af0cdd 100644 --- a/src/materials/coatedglossy.cc +++ b/src/materials/coatedglossy.cc @@ -188,12 +188,13 @@ float coatedGlossyMat_t::OrenNayar(const vector3d_t &wi, const vector3d_t &wo, c double sigma_squared = textureSigma * textureSigma; double mOrenNayar_TextureA = 1.0 - 0.5 * (sigma_squared / (sigma_squared + 0.33)); double mOrenNayar_TextureB = 0.45 * sigma_squared / (sigma_squared + 0.09); - return mOrenNayar_TextureA + mOrenNayar_TextureB * maxcos_f * sin_alpha * tan_beta; + return std::min(1.f, std::max(0.f, (float) (mOrenNayar_TextureA + mOrenNayar_TextureB * maxcos_f * sin_alpha * tan_beta))); } else { - return orenA + orenB * maxcos_f * sin_alpha * tan_beta; + return std::min(1.f, std::max(0.f, (float) (orenA + orenB * maxcos_f * sin_alpha * tan_beta))); } + } color_t coatedGlossyMat_t::eval(const renderState_t &state, const surfacePoint_t &sp, const vector3d_t &wo, const vector3d_t &wi, BSDF_t bsdfs, bool force_eval)const diff --git a/src/materials/glossy.cc b/src/materials/glossy.cc index ba6f4f62..d834524d 100644 --- a/src/materials/glossy.cc +++ b/src/materials/glossy.cc @@ -157,11 +157,11 @@ float glossyMat_t::OrenNayar(const vector3d_t &wi, const vector3d_t &wo, const v double sigma_squared = textureSigma * textureSigma; double mOrenNayar_TextureA = 1.0 - 0.5 * (sigma_squared / (sigma_squared + 0.33)); double mOrenNayar_TextureB = 0.45 * sigma_squared / (sigma_squared + 0.09); - return mOrenNayar_TextureA + mOrenNayar_TextureB * maxcos_f * sin_alpha * tan_beta; + return std::min(1.f, std::max(0.f, (float) (mOrenNayar_TextureA + mOrenNayar_TextureB * maxcos_f * sin_alpha * tan_beta))); } else { - return orenA + orenB * maxcos_f * sin_alpha * tan_beta; + return std::min(1.f, std::max(0.f, (float) (orenA + orenB * maxcos_f * sin_alpha * tan_beta))); } } diff --git a/src/materials/glossy2.cc b/src/materials/glossy2.cc index ba6f4f62..d834524d 100644 --- a/src/materials/glossy2.cc +++ b/src/materials/glossy2.cc @@ -157,11 +157,11 @@ float glossyMat_t::OrenNayar(const vector3d_t &wi, const vector3d_t &wo, const v double sigma_squared = textureSigma * textureSigma; double mOrenNayar_TextureA = 1.0 - 0.5 * (sigma_squared / (sigma_squared + 0.33)); double mOrenNayar_TextureB = 0.45 * sigma_squared / (sigma_squared + 0.09); - return mOrenNayar_TextureA + mOrenNayar_TextureB * maxcos_f * sin_alpha * tan_beta; + return std::min(1.f, std::max(0.f, (float) (mOrenNayar_TextureA + mOrenNayar_TextureB * maxcos_f * sin_alpha * tan_beta))); } else { - return orenA + orenB * maxcos_f * sin_alpha * tan_beta; + return std::min(1.f, std::max(0.f, (float) (orenA + orenB * maxcos_f * sin_alpha * tan_beta))); } } diff --git a/src/materials/shinydiffuse.cc b/src/materials/shinydiffuse.cc index 3a203a5a..0f480e59 100644 --- a/src/materials/shinydiffuse.cc +++ b/src/materials/shinydiffuse.cc @@ -215,14 +215,12 @@ CFLOAT shinyDiffuseMat_t::OrenNayar(const vector3d_t &wi, const vector3d_t &wo, double sigma_squared = textureSigma * textureSigma; double mOrenNayar_TextureA = 1.0 - 0.5 * (sigma_squared / (sigma_squared + 0.33)); double mOrenNayar_TextureB = 0.45 * sigma_squared / (sigma_squared + 0.09); - - return mOrenNayar_TextureA + mOrenNayar_TextureB * maxcos_f * sin_alpha * tan_beta; + return std::min(1.f, std::max(0.f, (float) (mOrenNayar_TextureA + mOrenNayar_TextureB * maxcos_f * sin_alpha * tan_beta))); } else { - return mOrenNayar_A + mOrenNayar_B * maxcos_f * sin_alpha * tan_beta; + return std::min(1.f, std::max(0.f, (float) (mOrenNayar_A + mOrenNayar_B * maxcos_f * sin_alpha * tan_beta))); } - }