Blinn-Phong照明 - 完整色彩的最佳计算是什么

时间:2015-11-08 23:21:33

标签: c++ opengl glsl phong

我读过的几乎所有文章和书籍都说明最终颜色的构成是: finalColor = ambientColor + lambertianTerm * diffuseColor(= material color)+ specularIntensity * specularColor(=浅色)

lambertianTerm = dot( surfaceNormal, normalize( lightPos - surfacePos ) );

halfVector = normalize( normalize( lightPos - surfacePos ) + normalize( eyePos - surfacePos );
specularFactor = max( dot( halfVector, surfaceNormal ), 0.0f );

specularIntensity = pow( specularFactor, surfaceShininessLevel );

以下是一些使用上述方法计算最终颜色的地方:OpenGL SuperBible第6版 - >渲染技术 - >照明模型 - > Blinn-Phong Lighting,Wikipedia -> Blinn–Phong shading model (see the fragment shader)等。

最终颜色的计算存在问题:光的颜色(也考虑多个光源的情况)不参与漫反射颜色的制定。考虑一下光亮因子是一个大数字的情况 - 假设128.0,所以镜面光斑很小,并且大部分物体区域都是用漫反射项着色的。还要让对象的颜色为绿色,而光的颜色为红色。如果没有环境颜色,上面等式的输出是部分点亮的纯绿色物体,上面有一个小黄点=绿色+红色=来自红色光源的光从绿色物体反射: purely green diffuse color + yellow specular highlight 这是不正确的。当然,绿色+红色是黄色,但肯定你既不会看到纯绿色球也不会看到黄色镜面斑点。手里拿着一个绿色闪亮的球 - 例如台球比赛中的6号球,然后用红灯点亮它 - 我可以向你保证,你不会只看到绿色的漫反射和黄色的镜面反射。相反,你会看到混合的绿色+红色用于漫反射和更红的镜面光斑。到目前为止,我发现的最佳方法是计算最终颜色 - 平均混合:

finalColor = ambient
             + lambertianTerm * ( surfaceColor + lightColor ) / 2.0 
             + specularIntensity * lightColor;

diffuse = yellow with a red accent, specular spot = almost purely red 尝试叠加混合:

const vec4 srgbLuminanceFactor = vec4( 0.2125f, 0.7154f, 0.0721f, 1.0f );
vec4 overlay( vec4 baseColor, vec4 blendColor )
{
    float luminance = dot( baseColor, srgbLuminanceFactor );
    vec4 lowerLumOverlay = 2.0f * blendColor * baseColor;
    if ( luminance < 0.45f )
    {
        return lowerLumOverlay;
    }

    const vec4 whiteColor = vec4( 1.0 );
    vec4 higherLumOverlay = whiteColor - 2.0f * ( whiteColor - blendColor ) * ( whiteColor - baseColor );
    return luminance > 0.55f
           ? higherLumOverlay
           : mix( lowerLumOverlay, higherLumOverlay, ( luminance - 0.45f ) * 10.0f );
}

......但看起来并不好看。 光和物体的颜色可能应该以另一种线性比例混合:

mix( surfaceColor, lightColor, ratio );

......或者以一种我无法想到的非线性方式。

所以最后一个问题:完整颜色的最佳计算是什么? 另外,告诉我,如果我错过了一些东西,但我认为纯绿色图片+纯黄色镜面高光完全不是真实的场景。

1 个答案:

答案 0 :(得分:1)

表面颜色含义是&#34;什么光的颜色可以从这个表面扩散&#34;。

镜面反射颜色含义是&#34;该表面可以反射的颜色是什么颜色&#34;。

浅色含义是&#34;什么光的颜色到达表面&#34;。

所以你必须将它们相乘:

   finalColor = ambient
             + lambertianTerm * surfaceColor * lightColor
             + specularIntensity * specularColor * lightColor;