android - GLES20.glUniform4fv和fragshader

标签 android kotlin opengl-es

好吧,所以我试图在一个对象中循环并使用多种颜色,但似乎无法弄清楚并诚实地将头发撕开,但是这段代码来自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, -0.5f, -0.5f,
        0.5f, 0.5f, -0.5f,
        -0.5f, 0.5f, -0.5f,
        -0.5f, -0.5f, 0.5f,
        0.5f, -0.5f, 0.5f,
        0.5f, 0.5f, 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, 0, 5, 1,
        1, 5, 6, 1, 6, 2,
        2, 6, 7, 2, 7, 3,
        3, 7, 4, 3, 4, 0,
        4, 7, 6, 4, 6, 5,
        3, 0, 1, 3, 1, 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, 2, color, 0)
            }
            vPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix")
            GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, 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, 1.0f,
    1.0f, 0.0f, 0.0f, 1.0f,
    0.0f, 1.0f, 0.0f, 1.0f,
    0.0f, 0.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 0.0f, 1.0f,
    1.0f, 0.0f, 1.0f, 1.0f,
    0.0f, 1.0f, 1.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
    )
}

关于android - GLES20.glUniform4fv和fragshader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63517374/

相关文章:

android - MVVM+Kotlin+数据绑定(bind)最佳实践

arrays - 我应该从结构和类切换到数组吗?

android - 我可以为 API < 21 更改 android 中可绘制的单选按钮吗?

android - Android Studio 上的 JDOMParseException : Error on line 1: White spaces are required between publicId and systemId.

android - 在 Google Directions API 失效之前缓存路线的最佳 X 分钟是多少?

android - Kotlin 中的 "_"符号是什么意思?

android - YouTubePlayerView 在屏幕方向更改时重新加载视频

android - 使用协程在 api 请求之前从房间数据库加载数据

ios - 如何在 opengl es 中使用由 UIGraphicsBeginImageContextWithOptions() 制作的图像

3D立方体或球体中的android触摸事件