[计算移动物体的漫射照明时,我必须将发光源与物体本身一起移动:
@Override
public void draw() { // draw frame
...
// Move object
GLES20.glVertexAttribPointer(aPositionLink, 3, GLES30.GL_FLOAT,
false, 0, object3D.getVertices());
// The luminous source moves nearby the object, so the
// object is always illuminated from one side
GLES20.glUniform3f(lightPositionLink, object3D.getX(),
object3D.getY(), object3D.getZ() + 2.0f);
...
}
顶点着色器片段:
#version 300 es
uniform mat4 u_mvMatrix; // model-view matrix of object
uniform vec3 u_lightPosition; // position of the luminous source
in vec4 a_position; // vertex data is loaded here
in vec3 a_normal; // normal data is loaded here
struct DiffuseLight {
vec3 color;
float intensity;
};
uniform DiffuseLight u_diffuseLight;
...
void main() {
...
vec3 modelViewNormal = vec3(u_mvMatrix * vec4(a_normal, 0.0));
vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
// calculate the light vector by subtracting the
// position of the object from the light position
vec3 lightVector = normalize(u_lightPosition - modelViewVertex);
float diffuse = max(dot(modelViewNormal, lightVector), 0.1);
float distance = length(u_lightPosition - modelViewVertex);
diffuse = diffuse * (1.0 / (1.0 + pow(distance, 2.0)));
// calculate the final color for diffuse lighting
lowp vec3 diffuseColor = diffuse * u_diffuseLight.color * u_diffuseLight.intensity;
v_commonLight = vec4((ambientColor + diffuseColor), 1.0);
...
}
这是正确的方法吗?还是有固定光源的另一种合理选择,以便不花费资源来计算每帧的光源位置?注意:增加距离无济于事。预先感谢。
SOLUTION:
根据Rabbid76的建议,我应用了定向光:
#version 300 es
const vec3 directionLight = vec3(0.7, 0.0, -1.0); // directional light vector
...
void main() {
...
vec3 modelViewNormal = vec3(u_mvMatrix * vec4(a_normal, 0.0));
float diffuse = max(-dot(modelViewNormal, directionLight), 0.0);
lowp vec3 diffuseColor = diffuse * u_diffuseLight.color * u_diffuseLight.intensity;
v_commonLight = vec4((ambientColor + diffuseColor), 1.0);
...
}
我必须将发光源与对象本身一起移动
为什么光源与物体一起移动?
如果光是世界上的点光源,并且对象移动,那么对象的照明就会发生变化(在“真实”世界中)。
在您的情况下,照明是在视图空间中计算的。如果光源是世界上的一个点,则必须通过视图矩阵转换位置(视图矩阵从世界空间转换为视图空间)。例如:
uniform mat4 u_viewMatrix;
void main()
{
// [...]
vec3 lightPosView = vec3(u_viewMatrix * vec4(u_lightPosition.xyz, 1.0));
vec3 lightVector = normalize(u_lightPosition - modelViewVertex);
// [...]
}
无论如何,如果对象移动并且光源以某种方式固定到对象,则还必须将应用于对象顶点的变换也应用于光源。在这种情况下,u_lightPosition
必须是对象在模型空间中的位置,这意味着它相对于对象(u_lightModelPosition
)。然后,您可以执行以下操作:
uniform vec3 u_lightModelPosition;
void main()
{
mat3 normalMat = inverse(transpose(mat3(u_mvMatrix)));
vec3 modelViewNormal = normalMat * a_normal;
vec3 modelViewVertex = vec3(u_mvMatrix * a_position);
vec3 modelViewLight = vec3(u_mvMatrix * vec4(u_lightModelPosition, 1.0));
vec3 lightVector = normalize(modelViewLight - modelViewVertex);
// [...]
}
如果您想要一个不依赖于位置的灯,则必须使用定向灯。在那种情况下,光源不是世界上的一个点,而仅仅是一个方向。例如:
vec3 lightVector = -u_lightRayDirection;
u_lightRayDirection
必须在光照计算的范围内。由于照明是在视图空间中计算的,因此u_lightRayDirection
也必须是视图空间中的方向。如果u_lightRayDirection
是世界空间中的向量,则必须将其转换为mat3(u_viewMatrix)
。定向光没有距离(或恒定距离)。
如果光源固定在相机上,则根本不需要进行任何转换(因为您在视图空间中进行了光计算)。