首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Blinn-Phong照明-什么是最佳的计算完整的颜色

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

Stack Overflow用户
提问于 2015-11-08 23:21:32
回答 1查看 1.9K关注 0票数 1

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

代码语言:javascript
复制
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照明、Wikipedia -> Blinn–Phong shading model (see the fragment shader)等。

在计算最终颜色时存在一个问题:光线的颜色(也考虑多个光源的情况)不参与漫射颜色的制定。假设亮度因子是一个很大的数字- 128.0,所以镜面光斑很小,物体的大部分区域都是用漫射项着色的。还要让物体的颜色是绿色的,而光线是红色的。如果没有环境颜色,上述方程的输出是部分照明的纯绿色物体,上面有一个小黄点=绿色+红色=从绿色物体反射的红光光源发出的光:

这不对。当然,绿色+红色是黄色的,但你肯定不会看到纯绿色的球,也不会看到黄色的镜面斑点。手里拿着一个绿色发亮的球--比如台球比赛中的大6球,然后用红灯点亮它--我可以向你保证,你不会只看到绿色的漫射和黄色的镜面。相反,你会看到一个混合绿色+红色的漫射点和更红色的镜面。到目前为止,我找到的计算最终颜色平均混合的最佳方法是:

代码语言:javascript
复制
finalColor = ambient
             + lambertianTerm * ( surfaceColor + lightColor ) / 2.0 
             + specularIntensity * lightColor;

尝试覆盖混合:

代码语言:javascript
复制
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 );
}

..。但看起来不太好。也许光和物体的颜色应该以另一个线性比例混合:

代码语言:javascript
复制
mix( surfaceColor, lightColor, ratio );

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

因此,最后一个问题:什么是最佳的计算完整的颜色?此外,告诉我,如果我错过了什么,但在我看来,纯粹的绿色图片+纯黄色镜面亮点是完全不是一个真实的世界场景。

EN

回答 1

Stack Overflow用户

发布于 2015-11-09 01:42:11

表面颜色的意思是“什么光的颜色可以从这个表面扩散”。

镜面颜色的意思是“什么光的颜色可以反射从这个表面”。

浅色的意思是“什么光的颜色到达表面”。

所以你必须把它们相乘:

代码语言:javascript
复制
   finalColor = ambient
             + lambertianTerm * surfaceColor * lightColor
             + specularIntensity * specularColor * lightColor;
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33600223

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档