alexrnov
alexrnov

Reputation: 2534

Diffuse lighting for a moving object

When calculating diffuse lighting for a moving object, I have to move the luminous source along with the object itself:

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

Snippet of vertex shader:

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

Is this the right approach? Or is there another rational option with stationary luminous source so as not to expend resources on calculating the position of the luminous source each frame? Note: Increasing the distance does not help. Thanks in advance.

SOLUTION:

On the advice of Rabbid76 I applied directional light as described here.

Upvotes: 3

Views: 398

Answers (1)

Rabbid76
Rabbid76

Reputation: 211166

I have to move the luminous source along with the object itself

Why does the light source move with the object?

If the light is a point light source in the world, and the object moves, then the illumination of the object changes (in the "real" world).

In your case, the lighting is computed in view space. If the light source is a point in the world, then you have to transform the position by the view matrix (the view matrix transforms from world space to view space). e.g:

uniform mat4 u_viewMatrix;

void main()
{
    // [...]

    vec3 lightPosView = vec3(u_viewMatrix * vec4(u_lightPosition.xyz, 1.0)); 
    vec3 lightVector  = normalize(u_lightPosition - modelViewVertex);

    // [...]
}

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);

    // [...]
}

If you want a light, that doesn't depend on the position, the you have to use a directional light. In that case the light source is not a point in the world, it is a direction only. e.g.:

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


If the light source is anchored to the camera, no transformations are required at all (because you the light calculations in view space).

Upvotes: 5

Related Questions