2016-02-11 3 views
1

Мне нужен шейдер, который создает рассеянный свет, на который влияет только угол между нормальным и источником света. Мой текущий шейдер, зависят от расстояния и угла выглядит следующим образом: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 (куб) - это две отдельные переменные.

+0

Ваши шейдеры выглядят хорошо для меня. Помимо света, делает ли все остальное то, как вы ожидаете, когда будете двигаться? –

+0

Да, все остальное выглядит как ожидалось. Я предполагаю, что я смешиваю некоторые матрицы так, чтобы шейдер фактически не получал угол между нормальным и световым положением, а только «относительное» положение света, которое является постоянным. Я не могу понять, что не так. – Plarsen

+0

О, перейдите в 'mLightPosInWorldSpace', а не' mLightPosInEyeSpace'. –

ответ

0

Светлое положение для диффузных вычислений должно быть выполнено в мировом пространстве. Это означает, что вам необходимо пройти mLightPosInWorldSpace, а не mLightPosInEyeSpace.

public void draw(float[] mvpMatrix, float[] mvMatrix, float[] mLightPosInEyeSpace) { 
    ... 
    // Pass in the light position in world space. 
    GLES20.glUniform3f(LightPosHandle, mLightPosInWorldSpace[0], mLightPosInWorldSpace[1], mLightPosInWorldSpace[2]); 
    ... 
} 

Хорошо, что вы так назвали свои переменные, иначе я бы не заметил этого.

+0

Ах спасибо, я обновил его, чтобы использовать положение космического света в мире, передавая mLightPosInWorldSpace на cube.draw. К сожалению, свет все еще, кажется, следует за кубом вокруг при вращении куба. – Plarsen

+0

Вы перемещаете куб или камеру? Если вы вращаете куб, но не камеру, вы можете не видеть большого изменения уровней освещенности. Попробуйте переместить свет и сохраните куб. –

+0

Свет вращается в круге над двумя кубиками. Один куб фиксируется в позиции, а другой куб я перемещаюсь и вращаюсь. Свет ясно приходит из другого направления на кубе, который я перемещаю, если поворачиваю его на 180 градусов. Я никак не меняю камеру. – Plarsen

Смежные вопросы