Java:OpenGl ES 2.0 Shader Light

时间:2016-02-11 20:43:18

标签: java android shader opengl-es-2.0

我需要一个着色器来创建一个只受正常光源和光源之间角度影响的漫反射光。我目前使用距离和角度影响的着色器如下所示:

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)是两个独立的变量。

1 个答案:

答案 0 :(得分: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]);
    ...
}

你很清楚地命名你的变量,否则我就不会发现它。