I need a shader that create a diffuse light that is only affected by the angle between the normal and the light source. My current shader that is affected by both distance and angle looks like this:
private final String vertexShaderCode2 =
"uniform mat4 uMVPMatrix;" +
"uniform mat4 uMVMatrix;" +
"uniform vec3 uLightPos;" +
"attribute vec4 vPosition;" +
"attribute vec4 aColor;" +
"attribute vec3 aNormal;" +
"varying vec4 vColor;" +
"void main() {" +
" vec3 modelViewVertex = vec3(uMVMatrix * vPosition); " +
" vec3 modelViewNormal = vec3(uMVMatrix * vec4(aNormal, 0.0));" +
" float distance = length(uLightPos - modelViewVertex);" +
" vec3 lightVector = normalize(uLightPos - modelViewVertex);" +
" float diffuse = max(dot(modelViewNormal, lightVector), 0.1);" +
" diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));" +
" vColor = aColor * diffuse;" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
Here is code for populating the shaders:
// Calculate position of the light.
Matrix.setIdentityM(mLightModelMatrix, 0);
Matrix.rotateM(mLightModelMatrix, 0, LightAngleInDegrees, 0.0f, 1.0f, 1.0f);
Matrix.translateM(mLightModelMatrix, 0, 0.0f, 100.0f, -10.0f);
Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, mLightPosInModelSpace, 0);
Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0);
// Player
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, py, px, pz);
Matrix.rotateM(mModelMatrix, 0, mAngle, 0, 0, 1.0f);
Matrix.scaleM(mModelMatrix, 0, scalef, scalef, scalef * 2);
Matrix.multiplyMM(mMVMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVMatrix, 0);
cube.draw(mMVPMatrix, mMVMatrix, mLightPosInWorldSpace);
And finally, the cube.draw method:
public void draw(float[] mvpMatrix, float[] mvMatrix, float[] mLightPosInWorldSpace) {
...
// Pass in the light position in eye space.
GLES20.glUniform3f(LightPosHandle, mLightPosInWorldSpace[0], mLightPosInWorldSpace[1], mLightPosInWorldSpace[2]);
...
}
If I leave the following line out of the Shader:
diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));
Then, distance is not accounted for but a side effect is that rotating the cube is not affecting the color of the cube sides, like if the light source is following the cube around. LightAngleInDegrees (light) and mAngle (cube) is two separate variables.
mLightPosInWorldSpace
, notmLightPosInEyeSpace
. – Andrew Williamson