问题描述
好的,所以我试图在一个对象中循环并使用多种颜色,但似乎无法弄清楚并诚实地将头发撕开,但是此代码来自Android指南,我一直在玩现在绕过它一分钟,并尝试了许多不同的方法,但总是最后回到问题所在:“是片段着色器,还是我只是在使用函数GLES20.glUniform4fv(colorHandle,2,color,0)错误?如果不能接受颜色的数组参数,为什么要有一个'count'值和一个数组参数?”
class Triangle {
private var mProgram: Int
private var vPMatrixHandle: Int = 0
private var positionHandle: Int = 0
private var mColorHandle: Int = 0
private val fragmentShaderCode: String =
"precision mediump float;\n" +
"uniform vec4 vColor[];\n" +
"void main() {\n" +
"\tgl_FragColor = vColor;\n" +
"}"
private val vertexShaderCode: String =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec4 vPosition;\n" +
"void main() {\n" +
"\tgl_Position = uMVPMatrix * vPosition;\n" +
"}"
private val COORDS_PER_VERTEX: Int = 3
private var triangleCoords: FloatArray = floatArrayOf(
-0.5f,-0.5f,0.5f,0.5f
)
private val color: FloatArray = floatArrayOf(
0.63671875f,0.76953125f,0.22265625f,1.0f,0.63671875f,0.22953125f,0.78265625f,1.0f
)
private val indiceCoords: ByteArray = byteArrayOf(
0,4,5,1,6,2,7,3,2
)
private val vertexCount: Int = triangleCoords.size / COORDS_PER_VERTEX
private val vertexStride: Int = COORDS_PER_VERTEX * 4
private var vertexBuffer: FloatBuffer =
ByteBuffer.allocateDirect(triangleCoords.size * 4).run {
order(ByteOrder.nativeOrder())
asFloatBuffer().apply {
put(triangleCoords)
position(0)
}
}
private var indiceBuffer: ByteBuffer =
ByteBuffer.allocateDirect(indiceCoords.size * 4).run {
order(ByteOrder.nativeOrder()).apply {
put(indiceCoords)
position(0)
}
}
init {
val vertexShader: Int = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode)
val fragmentShader: Int = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode)
mProgram = GLES20.glCreateProgram().also {
GLES20.glAttachShader(it,vertexShader)
GLES20.glAttachShader(it,fragmentShader)
GLES20.glLinkProgram(it)
}
}
fun loadShader(type: Int,shaderCode: String): Int {
return GLES20.glCreateShader(type).also { shader ->
GLES20.glShaderSource(shader,shaderCode)
GLES20.glCompileShader(shader)
}
}
fun draw(mvpMatrix: FloatArray) {
GLES20.glUseProgram(mProgram)
positionHandle = GLES20.glGetAttribLocation(mProgram,"vPosition").also {
GLES20.glEnableVertexAttribArray(it)
GLES20.glVertexAttribPointer(
it,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,vertexStride,vertexBuffer
)
mColorHandle = GLES20.glGetUniformLocation(mProgram,"vColor").also { colorHandle ->
GLES20.glUniform4fv(colorHandle,color,0)
}
vPMatrixHandle = GLES20.glGetUniformLocation(mProgram,"uMVPMatrix")
GLES20.glUniformMatrix4fv(vPMatrixHandle,mvpMatrix,0)
GLES20.glDrawElements(GL10.GL_TRIANGLES,36,GL10.GL_UNSIGNED_BYTE,indiceBuffer)
GLES20.glDisableVertexAttribArray(it)
}
}
}
解决方法
如果要将颜色与顶点关联,则必须添加其他属性。颜色的数量必须与顶点的数量相同。
将颜色属性添加到顶点着色器(attribute vec4 vColor;
)。将属性从顶点着色器传递到片段着色器(varying vec4 color;
):
private val fragmentShaderCode: String =
"precision mediump float;\n" +
"varying vec4 color;\n" +
"void main() {\n" +
"\tgl_FragColor = color;\n" +
"}"
private val vertexShaderCode: String =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec4 vPosition;\n" +
"attribute vec4 vColor;\n" +
"varying vec4 color;\n" +
"void main() {\n" +
"\tcolor = vColor;\n" +
"\tgl_Position = uMVPMatrix * vPosition;\n" +
"}"
定义8种颜色的数组。例如:
private val COORDS_PER_COLOR: Int = 4
private val color: FloatArray = floatArrayOf(
0.63671875f,0.76953125f,0.22265625f,1.0f,0.63671875f,0.22953125f,0.78265625f,0.0f,1.0f
)
private val colorCount: Int = color.size / COORDS_PER_COLOR
private val colorStride: Int = COORDS_PER_COLOR * 4
为颜色属性创建缓冲区:
private var colorBuffer: FloatBuffer =
ByteBuffer.allocateDirect(color.size * 4).run {
order(ByteOrder.nativeOrder())
asFloatBuffer().apply {
put(color)
position(0)
}
}
指定颜色属性数组:
mColorHandle = GLES20.glGetAttribLocation(mProgram,"vColor").also { colorHandle ->
GLES20.glEnableVertexAttribArray(colorHandle)
GLES20.glVertexAttribPointer(
colorHandle,COORDS_PER_COLOR,GLES20.GL_FLOAT,false,colorStride,colorBuffer
)
}
,
如果要使用“统一”数组(vColor []),请在声明中显式指定数组大小。
private val fragmentShaderCode: String =
"precision mediump float;\n" +
"uniform vec4 vColor[2];\n" +
"varying vec4 vParam;" +
"void main() {\n" +
"\tgl_FragColor = vColor[int(step(vParam.x * vParam.y * vParam.z,0.0))];\n" +
"}"
private val vertexShaderCode: String =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec4 vPosition;\n" +
"varying vec4 vParam;" +
"void main() {\n" +
"\tgl_Position = uMVPMatrix * vPosition;\n" +
"\tvParam = vPosition;" +
"}"