2016-02-11 41 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(cube)是两个独立的变量。

+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