2016-02-11 38 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