为什么我的镜面高光在多边形边缘上显示得如此强烈?

use*_*321 3 opengl lighting

我有一个简单的应用程序,用单个定向光绘制球体.我是通过从八面体开始并将每个三角形细分为4个较小的三角形来创建球体的.

只需漫射照明,球体看起来非常光滑.但是,当我添加镜面高光时,三角形的边缘显示得相当强烈.这里有些例子:

仅扩散:

球体只有漫射照明

漫反射和镜面反射:

具有漫反射和镜面反射的球体

我相信法线正确插值.只看法线,我明白了:

球体法线

事实上,如果我切换到平面着色,法线是每个多边形而不是每个顶点,我得到这个:

在此输入图像描述

在我的顶点着色器中,我将模型的法线乘以转置逆模型视图矩阵:

#version 330 core

layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec3 vNormal;
layout (location = 2) in vec2 vTexCoord;

out vec3 fNormal;
out vec2 fTexCoord;

uniform mat4 transInvModelView;
uniform mat4 ModelViewMatrix;
uniform mat4 ProjectionMatrix;

void main()
{
    fNormal = vec3(transInvModelView * vec4(vNormal, 0.0));
    fTexCoord = vTexCoord;
    gl_Position = ProjectionMatrix * ModelViewMatrix * vPosition;
}
Run Code Online (Sandbox Code Playgroud)

在片段着色器中,我正在计算镜面高光,如下所示:

#version 330 core

in vec3 fNormal;
in vec2 fTexCoord;

out vec4 color;

uniform sampler2D tex;
uniform vec4 lightColor;        // RGB, assumes multiplied by light intensity
uniform vec3 lightDirection;    // normalized, assumes directional light, lambertian lighting
uniform float specularIntensity;
uniform float specularShininess;
uniform vec3 halfVector;        // Halfway between eye and light
uniform vec4 objectColor;

void main()
{
    vec4    texColor    = objectColor;

    float   specular    = max(dot(halfVector, fNormal), 0.0);
    float   diffuse     = max(dot(lightDirection, fNormal), 0.0);

    if (diffuse == 0.0)
    {
        specular = 0.0;
    }
    else
    {
        specular = pow(specular, specularShininess) * specularIntensity;
    }

    color = texColor * diffuse * lightColor + min(specular * lightColor, vec4(1.0));
}
Run Code Online (Sandbox Code Playgroud)

关于如何计算,我有点困惑halfVector.我在CPU上进行并将其作为制服传递.它的计算如下:

vec3    lightDirection(1.0, 1.0, 1.0);
lightDirection = normalize(lightDirection);
vec3    eyeDirection(0.0, 0.0, 1.0);
eyeDirection = normalize(eyeDirection);
vec3    halfVector  = lightDirection + eyeDirection;
halfVector = normalize(halfVector);
glUniform3fv(halfVectorLoc, 1, &halfVector [ 0 ]);
Run Code Online (Sandbox Code Playgroud)

这是正确的配方halfVector吗?还是需要在着色器中完成?

Nic*_*ler 10

将法线插入面部可以(并且几乎总是会)导致法线缩短.这就是为什么高光在脸部中央更暗,在角落和边缘更亮.如果这样做,只需重新规范片段着色器中的法线:

fNormal = normalize(fNormal);
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你不能预先计算半矢量,因为它是视图相关的(这是镜面光照的整个点).在当前场景中,只需移动相机(保持方向),高光不会改变.

在着色器中执行此操作的一种方法是为眼睛位置传递额外的均匀,然后计算视图方向eyePosition - vertexPosition.然后继续像在CPU上那样继续.