OpenGL ES 2.0中片段着色器的非均匀颜色值

时间:2016-01-06 13:29:43

标签: opengl-es

尝试修改Android Developer OpenGL Tutorial中的三角形顶点颜色值。三角形呈现但看起来很暗。颜色缓冲区有什么问题?

public class Triangle {

    ...

添加以下行以建立颜色缓冲区。这有必要吗?

    private FloatBuffer colorBuffer;
    static final int COLORS_PER_VERTEX = 4;

    static float triangleColors[] = {
            0.6f, 0.2f, 0.2f, 1.0f,
            0.2f, 0.6f, 0.2f, 1.0f,
            0.9f, 0.9f, 0.2f, 1.0f
    };

    private final int colorStride = COLORS_PER_VERTEX * 4; 

使用以下着色器代码,将原始的“uniform vec4 vColor”替换为属性而不是因为没有GLES20.getVaryingLocation而变化。

    private final String vertexShaderCode =
        "attribute vec4 vPosition;void main(){gl_Position = vPosition;}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    //originally uniform, use varying?
                   "attribute vec4 vColor;" +
                    "void main() {" +
                    "    gl_FragColor = vColor;"+
                    "}";

在构造函数中:

    public Triangle()
    {
        ...

        ByteBuffer cb = ByteBuffer.allocateDirect(triangleColors.length * 4);
        cb.order(ByteOrder.nativeOrder());
        colorBuffer = cb.asFloatBuffer();
        colorBuffer.put(triangleColors);
        colorBuffer.position(0);

        ... //compile and link shaders code is unchanged   
    }

    public void draw()
    {
        GLES20.glUseProgram(mProgram);

        ...

        /*
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);
        */

        mColorHandle = GLES20.glGetAttribLocation(mProgram, "vColor");
        GLES20.glEnableVertexAttribArray(mColorHandle);
        GLES20.glVertexAttribPointer(mColorHandle, COLORS_PER_VERTEX,
                GLES20.GL_FLOAT, false, colorStride, colorBuffer);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
        GLES20.glDisableVertexAttribArray(mPositionHandle);
        GLES20.glDisableVertexAttribArray(mColorHandle);

    }

}

1 个答案:

答案 0 :(得分:1)

你误解了什么是制服,属性和变化。

要进行您所描述的更改,您需要同时使用属性和变量。顶点着色器必须包含颜色的属性,例如attribute vec4 aColor;和变化的输出varying vec4 vColor;。然后在main中,您需要将颜色指定为vColor = aColor;。在片段着色器中,您只需要varying vec4 vColor;并以与在main方法中相同的方式使用它。

解释一下这些是什么:

  • 属性和统一非常相似,但属性是每个顶点,而统一是每个绘制调用(对于所有顶点,片段将具有相同的值)。它们都旨在产生CPU和GPU之间的通信(您可以通过其中任何一个将数据发送到GPU)。
  • 变化有点不同。通常,从属性中分配变量,并在顶点着色器中完成。这意味着每个顶点都将具有自己的属性值,但在完成光栅化后,将根据相对于边界顶点的片段位置对每个变化值进行插值。因此,变量被设计为在顶点和片段着色器之间进行通信(将数据从顶点发送到片段着色器)。

最简单的方法是在由2个点(A,B)定义的直线上进行解释,让我们在渲染缓冲区中说这条线将占用100个像素。如果第一行具有白色C1 = (1,1,1,1)而第二个点具有黑色C2 = (0,0,0,1)。您将在顶点着色器中为变化值指定相同的颜色,并且片段着色器将被调用100次,这是针对每个像素的。现在,片段着色器中的不同颜色将具有位置X的插值,如

color = C1 + (C2-C1)*((X-A).length()/(B-A).length())

因此对于100像素的情况,第46个像素将是

color = (1,1,1,1)-(1,1,1,0)*(64/100)

会产生(.36, .36, .36, 1.0)。 因此像素将从AB线性地淡化为黑色,这将产生漂亮的渐变。

我希望这会清楚一点。