引入了可变变量后,无法获取属性的属性位置

时间:2019-05-14 20:00:33

标签: android shader opengl-es-2.0 fragment-shader vertex-shader

我正在尝试实现一个ModelViewer,它可以用逼真的照明可视化三角形状。 由于使用OpenGL ES 1.0似乎无法实现逼真的照明,并且我需要一种表示单个彩色对象深度的方法,因此该项目使用了OpenGL ES 2.0,这对我来说是新的。 对象本身由使用以下元素绘制的三角形组成:

GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

对于一个测试项目,我已经设置了简单的着色器,该着色器考虑了模型-视图-投影矩阵来绘制对象。在那之后,我的意图是实施照明,但我无法超越第一步。 当使用可变变量时,将找不到顶点属性。 删除各种属性的作品,但我需要传递数据。我已经搜寻了几天的时间来实现顶点着色和片段着色器,这些着色器不仅可以在某个位置显示对象,还可以做更多的事情。

// VERTEX SHADER CODE
    attribute vec4 v_Position;
    uniform mat4 u_MVPMatrix;
    uniform vec4 u_Color;

    varying vec4 v_Color;

    void main() {
        gl_Position = u_MVPMatrix * v_Position;
        v_Color = u_Color;
    };

// FRAGMENT SHADER CODE
    precision mediump float;

    varying vec4 v_Color;

    void main() {
        gl_FragColor = v_Color;
    }

整个班级

public class Object3D {

    private FloatBuffer vertexBuffer;

    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
//    static float triangleCoords[] = {   // in counterclockwise order:
//            0.0f,  0.622008459f, 0.0f, // top
//            -0.5f, -0.311004243f, 0.0f, // bottom left
//            0.5f, -0.311004243f, 0.0f  // bottom right
//    };
    float[] triangleCoords;

    // Set color with red, green, blue and alpha (opacity) values
    float[] colors = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };


    private final String vertexShaderCode =
            "attribute vec4 v_Position;" +
            "uniform float u_Color" +
            "uniform mat4 u_MVPMatrix;" +
                // outgoing
            "varying vec4 v_Color" +
            "void main() {" +
                // the matrix must be included as a modifier of gl_Position
                // Note that the uMVPMatrix factor *must be first* in order
                // for the matrix multiplication product to be correct.
                "gl_Position = u_MVPMatrix * v_Position;" +
                "v_Color = u_Color;" +
            "}";


    private final String fragmentShaderCode =
            "precision mediump float;" +

            "varying vec4 v_Color;" +
            "void main() {" +
                "gl_FragColor = v_Color;" +
            "}";


    // Use to access and set the view transformation
    private int mMVPMatrixHandle;

    private final int mProgram;

    private int mPositionHandle;
    private int mColorHandle;

    private final int vertexCount;
    private final int vertexStride;

    public Object3D(float[] triangleCoords) {
        this.triangleCoords = triangleCoords;

        vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
        vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

        this.colors = new float[4*vertexCount];
        for (int i = 0; i < colors.length; i+=4) {
            colors[i] = 0.63671875f;
            colors[i+1] = 0.76953125f;
            colors[i+2] = 0.22265625f;
            colors[i+3] = 1.0f;
        }

        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                triangleCoords.length * 4);
        // use the device hardware's native byte order
        bb.order(ByteOrder.nativeOrder());

        // create a floating point buffer from the ByteBuffer
        vertexBuffer = bb.asFloatBuffer();
        // add the coordinates to the FloatBuffer
        vertexBuffer.put(triangleCoords);
        // set the buffer to read the first coordinate
        vertexBuffer.position(0);

        int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
                vertexShaderCode);
        int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
                fragmentShaderCode);

        // create empty OpenGL ES Program

        mProgram = GLES20.glCreateProgram();

        // add the vertex shader to program
        GLES20.glAttachShader(mProgram, vertexShader);
        // add the fragment shader to program
        GLES20.glAttachShader(mProgram, fragmentShader);

        GLES20.glBindAttribLocation(mProgram, 0, "v_Position");
//        GLES20.glBindAttribLocation(mProgram, 1, "vColor");

        // creates OpenGL ES program executables
        GLES20.glLinkProgram(mProgram);
    }

    public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
        // Add program to OpenGL environment
        GLES20.glUseProgram(mProgram);

        // get handle to vertex shader's vPosition member
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "v_Position");
//        if (mPositionHandle == -1) {
//            throw new RuntimeException(
//                    "Could not get attrib location for v_Position");
//        }

        // Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(mPositionHandle);

        // Prepare the triangle coordinate data
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);

        // get handle to fragment shader's vColor member
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "v_Color");

        // Set color for drawing the triangle
        GLES20.glUniform4fv(mColorHandle, 1, colors, 0);
        // get handle to shape's transformation matrix
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");

        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

//        // get handle to shape's transformation matrix
//        int mColorHandleU = GLES20.glGetUniformLocation(mProgram, "u_Color");
//
//        // Apply the projection and view transformation
//        GLES20.glUniform4fv(mColorHandleU, 1, new float[] {}, 0);

        // Draw the triangle
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }
}

如果我想进行一些必要的颜色计算,则需要使用变量来将信息从顶点传递到片段着色器。但是,我似乎无法完成这项工作。

我不断收到的错误是:

2019-05-14 21:54:25.122 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glEnableVertexAttribArray:892 GL error 0x501
    Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.123 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glVertexAttribPointer:604 GL error 0x501
    Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.124 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glDisableVertexAttribArray:901 GL error 0x501
    Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.237 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glEnableVertexAttribArray:892 GL error 0x501
    Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.237 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glVertexAttribPointer:604 GL error 0x501
    Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16
2019-05-14 21:54:25.238 8281-8316/com.example.opengles20 E/emuglGLESv2_enc: device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glDisableVertexAttribArray:901 GL error 0x501
    Info: Invalid vertex attribute index. Wanted index: 4294967295. Max index: 16

此外,在实现后会引发以下异常:

mPositionHandle = GLES20.glGetAttribLocation(mProgram, "v_Position");
        if (mPositionHandle == -1) {
            throw new RuntimeException(
                    "Could not get attrib location for v_Position");
        }

我知道对于属性,指令流如下:

GLES20.glBindAttribLocation(...);
-- Link Shader Program --
attributeHandle = GLES20.glGetAttribLocation(programHandle, "a_AttributenName");
GLES20.glEnableVertexAttribArray(attributeHandle);
GLES20.glVertexAttribPointer(programHandle, ..., buffer);

制服的指令顺序如下:

uniformHandle = GLES20.glGetUniformLocation(mProgram, "u_UniformName");
// do something with it, for example:
GLES20.glUniform4fv(uniformHandle, ...);

但是对于可变变量该怎么办?

谢谢!

1 个答案:

答案 0 :(得分:0)

private final String vertexShaderCode =
        "attribute vec4 v_Position;" +
        "uniform float u_Color" +
        "uniform mat4 u_MVPMatrix;" +
            // outgoing
        "varying vec4 v_Color" +
        "void main() {" +

在u_Color和v_Color之后,您缺少分号。大概是您的顶点着色器未编译,并且正在级联为您所看到的错误。

这很痛苦,但是从长远来看,每次OpenGLES调用(glGetError之后检查错误,确实确实节省了时间。获取详细的着色器编译错误日志也很麻烦,但是值得放置-请参见hereglGetShaderInfoLogGL_COMPILE_STATUS)。