Мне нужен шейдер, который создает рассеянный свет, на который влияет только угол между нормальным и источником света. Мой текущий шейдер, зависят от расстояния и угла выглядит следующим образом:Java: OpenGl ES 2.0 Shader Light
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;" +
"}";
Вот код для заполнения шейдеров:
// 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);
И, наконец, метод cube.draw:
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]);
...
}
Если я оставляю следующую строку из шейдера:
diffuse = diffuse * (1.0/(1.0 + (0.25 * distance * distance)));
Тогда расстояние не учитывается, но побочным эффектом является то, что вращение куба не влияет на цвет сторон куба, например, если источник света следует за кубом вокруг. LightAngleInDegrees (light) и mAngle (куб) - это две отдельные переменные.
Ваши шейдеры выглядят хорошо для меня. Помимо света, делает ли все остальное то, как вы ожидаете, когда будете двигаться? –
Да, все остальное выглядит как ожидалось. Я предполагаю, что я смешиваю некоторые матрицы так, чтобы шейдер фактически не получал угол между нормальным и световым положением, а только «относительное» положение света, которое является постоянным. Я не могу понять, что не так. – Plarsen
О, перейдите в 'mLightPosInWorldSpace', а не' mLightPosInEyeSpace'. –