Java:OpenGl ES 2.0 着色器灯

标签 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(光)和mAngle(立方体)是两个独立的变量。

最佳答案

漫反射计算的灯光位置需要在世界空间中完成。这意味着您需要传入 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]);
    ...
}

幸好你这么清楚地命名了你的变量,否则我就不会发现这一点。

关于Java:OpenGl ES 2.0 着色器灯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35349651/

相关文章:

java - 在 OsmDroid 中获取我的位置不起作用

c++ - OpenGL 投影/矩阵混淆

xcode - 手动编译 Metal 着色器

java - Gradle 将依赖配置与任务绑定(bind)

java.lang.ExceptionInInitializerError Spring创建Application Context时抛出的异常

java - 不支持菱形运算符

android - 单元测试网络响应。调试时有效,实际运行时无效

c++ - 通过 TCS 和 TES 传递数据

java - 如果 C3P0 无法获得数据库连接,Tomcat 将挂起

c# - 无法检测到 webview Appium