定向照明在 OpenGL ES 2.0/3.0 中不是恒定的

Directional lighting is not constant in OpenGL ES 2.0/3.0

问题:当物体位置改变时,平行光的方向也会改变。

我看过有类似问题的帖子:

基于这些帖子,我尝试应用这个:

#version 300 es
uniform mat4 u_mvMatrix;
uniform mat4 u_vMatrix;
in vec4 a_position;
in vec3 a_normal;
const vec3 lightDirection = vec3(-1.9, 0.0, -5.0);
...
void main() {
    vec3 modelViewNormal = vec3(u_mvMatrix * vec4(a_normal, 0.0));
    vec3 lightVector = lightDirection * mat3(u_vMatrix);
    float diffuseFactor = max(dot(modelViewNormal, -lightVector), 0.0);
    ...
}

但结果是这样的:

也尝试过:

vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
vec3 lightVector = normalize(lightDirection - modelViewVertex);
float diffuseFactor = max(dot(modelViewNormal, lightVector), 0.0);

并且:

vec3 lightVector = normalize(lightDirection - modelViewVertex);
lightVector = lightVector * mat3(u_vMatrix);

但结果:

需要对代码进行哪些更改才能使所有对象都以相同的方式点亮?

提前致谢!

解法: 实际上,创建定向照明对我来说并不是一件容易的事。根据 Rabbid76 的建议,我更改了乘法的顺序。在另一个Rabbid76的建议上(),我也创建了一个自定义的观点:

Matrix.setLookAtM(pointViewMatrix, rmOffset:0, eyeX:3.8f, eyeY:0.0f, eyeZ:2.8f,
        centerX:0.0f, centerY:0f, centerZ:0f, upX:0f, upY:1.0f, upZ:0.0f)

还计算了眼睛坐标和光向量,虽然相机设置在[0, 0, 0]:

#version 300 es
uniform mat4 u_mvMatrix;
uniform mat4 u_pointViewMatrix;
in vec4 a_position;
in vec3 a_normal;
const vec3 lightPosition = vec3(-5.0, 0.0, 1.0);
...
void main() {
    // transform normal orientation into eye space
    vec3 modelViewNormal = vec3(u_mvMatrix * vec4(a_normal, 0.0));
    vec3 modelViewVertex = vec3(u_mvMatrix * a_position); // eye coordinates
    vec3 lightVector = normalize(lightPosition - modelViewVertex);
    lightVector = mat3(u_pointViewMatrix) * lightVector;
    float diffuseFactor = max(dot(modelViewNormal, lightVector), 0.0);
    ...
}

经过这几步,图片才变好了:

小差异可能是大视角造成的

向量必须与右边的矩阵相乘。参见 GLSL Programming/Vector and Matrix Operations

vec3 lightVector = lightDirection * mat3(u_vMatrix);

vec3 lightVector = mat3(u_vMatrix) * lightDirection;

如果你想在视图 space 中点光源计算,那么法线向量必须从对象(模型)space 转换为模型视图 space矩阵和光线方向 hss 由视图矩阵从世界 space 转换为视图 space。例如:

void main() {
    vec3  modelViewNormal = mat3(u_mvMatrix) * a_normal;
    vec3  lightVector     = mat3(u_vMatrix) * lightDirection;
    float diffuseFactor   = max(dot(modelViewNormal, -lightVector), 0.0);

    // [...]
}