定向照明在 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);
// [...]
}
问题:当物体位置改变时,平行光的方向也会改变。
我看过有类似问题的帖子:
基于这些帖子,我尝试应用这个:
#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);
// [...]
}