尝试从Android开发人员OpenGL教程中修改三角形顶点颜色值。三角形将进行渲染,但显示为深色。颜色缓冲区出了什么问题?
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"替换为attribute,而不是variable,因为没有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);
}
}
您误解了什么是统一、属性和变体。
要进行所描述的更改,您需要一个属性和一个变量。顶点着色器必须包括颜色的属性(如attribute vec4 aColor;
)和变化的输出(如varying vec4 vColor;
)。然后主要需要将颜色指定为vColor = aColor;
。在片段着色器中,您只需要varying vec4 vColor;
,并以与在主方法中相同的方式使用它。
解释一下这些是什么:
- 属性和统一体非常相似,但属性是每个顶点的,而统一体是每个绘制调用的(对于所有顶点、片段都具有相同的值)。它们都是为了在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)
从而产生CCD_ 11。因此,从A
到B
,像素将线性地变黑,这将产生良好的梯度。
我希望这能让事情稍微明朗一点。