运动物体的漫射照明

在计算移动物体的漫射照明时,我必须将发光源与物体本身一起移动:

@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);
  ...
}

这是正确的方法吗?还是有固定光源的另一种合理选择,以便不花费资源来计算每帧的光源位置?注意:增加距离无济于事。提前致谢。

评论
  • asaepe
    asaepe 回复
    我必须将光源与对象本身一起移动

    光源为什么随物体移动?

    Anyway, if the object moves and the light source is somehow anchored to the object, the you have to apply the transformations, which are applied to the vertices of the object, to the light source, too.
    In that case u_lightPosition has to be a position in the model space of the object, that means it is relative to the object (u_lightModelPosition). Then you can do:

    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 has to be in the space of the light calculations. Since the lighting is computed in view space, u_lightRayDirection has to in view space, too. If u_lightRayDirection is a vector in world space, then it has to be transformed by mat3(viewMatrix).
    A directional light has no distance (or a constant distance).