android - 在 Android OpenGL ES 上只能看到没有几何图形的 glClear 颜色

标签 android kotlin opengl-es

我正在尝试编写一个非常简单的 Android 应用程序,它使用 OpenGL 显示绿色背景并在其上渲染一个青色三角形,以验证我的代码是否正确显示了一些几何图形。我遇到了调用 glClearColor/glClear 的问题设置背景可见并使 View 按预期变为绿色,但我看不到调用 glDrawArrays 有明显变化在将第 0 个属性数组指向 FloatBuffer 之后包含顶点坐标。我的顶点着色器所做的就是将位置作为 vec4 传递到 fragment 着色器,它总是只将输出颜色设置为青色,所以我希望看到带有一个青色三角形的绿色 View ,但我却只看到绿色背景,我不确定为什么。

主要 Activity 文件(省略导入):

setupDefaultProgram()
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(gl: GL10?) {
        glRenderer.renderFunc()
    }

}

渲染器代码:

class GlRenderer {

    companion object {
        // Pass through position and UV values
        val vertexSource = """
            #version 300 es
            
            in vec2 position;
            
            void main() {
                gl_Position = vec4(position, -0.5, 1.0);
            }
        """.trimIndent()

        // Eventually get the texture value, for now, just make it cyan so I can see it
        val fragmentSource = """
            #version 300 es
            precision mediump float;
            
            out vec4 fragColor;
            
            void main() {
                fragColor = vec4(0.0, 1.0, 1.0, 1.0);
            }
        """.trimIndent()
    }

    private var vertexBuffer: FloatBuffer

    private var defaultProgram: Int = -1
    private var vertexLocation: Int = -1

    private fun checkGlError(msg: String) {
        val errCodeEgl = EGL14.eglGetError()
        val errCodeGl = GLES30.glGetError()
        if (errCodeEgl != EGL14.EGL_SUCCESS || errCodeGl != GLES30.GL_NO_ERROR) {
            throw RuntimeException(
                "$msg - $errCodeEgl(${GLU.gluErrorString(errCodeEgl)}) : $errCodeGl(${
                    GLU.gluErrorString(
                        errCodeGl
                    )
                })"
            )
        }
    }

    init {
        // Flat square
        // Am I allocating and writing to these correctly?
        val vertices = floatArrayOf(-1f, -1f, 1f, -1f, -1f, 1f, 1f, 1f)
        vertexBuffer = ByteBuffer.allocateDirect(vertices.size * 4).asFloatBuffer().also {
            it.put(vertices)
            it.position(0)
        }
    }

    fun setupDefaultProgram() {
        defaultProgram = makeProgram(
        mapOf(
            GLES30.GL_VERTEX_SHADER to vertexSource,
            GLES30.GL_FRAGMENT_SHADER to fragmentSource
            )
        )
        vertexLocation = GLES30.glGetAttribLocation(defaultProgram, "position")
        checkGlError("Getting uniform")
    }

    private fun compileShader(source: String, shaderType: Int): Int {
        val shaderId = GLES30.glCreateShader(shaderType)
        checkGlError("Create shader")
        if (shaderId == 0) {
            Log.e("Native", "Could not create shader for some reason")
            checkGlError("Could not create shader")
        }
        GLES30.glShaderSource(shaderId, source)
        checkGlError("Setting shader source")
        GLES30.glCompileShader(shaderId)
        val statusBuffer = IntArray(1)
        GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, statusBuffer, 0)
        val shaderLog = GLES30.glGetShaderInfoLog(shaderId)
        Log.d("Native", "Compiling shader #$shaderId : $shaderLog")

        if (statusBuffer[0] == 0) {
            GLES30.glDeleteShader(shaderId)
            checkGlError("Failed to compile shader $shaderId")
        }
        return shaderId
    }

    private fun makeProgram(sources: Map<Int, String>): Int {
        val program = GLES30.glCreateProgram()
        checkGlError("Create program")
        sources.forEach {
            val shader = compileShader(it.value, it.key)
            GLES30.glAttachShader(program, shader)
        }
        val linkBuffer = IntArray(1)
        GLES30.glLinkProgram(program)
        GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, linkBuffer, 0)
        if (linkBuffer[0] == 0) {
            GLES30.glDeleteProgram(program)
            checkGlError("Failed to link program $program")
        }
        return program
    }

    // Called to actually draw to the surface. When fully implemented it should draw whatever is
    // on the associated texture, but for now, to debug, I just want to verify I can draw vertices,
    // but it seems I cannot?
    fun renderFunc() {
        GLES30.glClearColor(0f, 1f, 0.5f, 1f)
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        checkGlError("Clearing")

        GLES30.glUseProgram(defaultProgram)
        checkGlError("Use program")

        GLES30.glEnableVertexAttribArray(vertexLocation)
        vertexBuffer.position(0)
        FloatArray(2 * 4).apply {
            vertexBuffer.get(this)
            vertexBuffer.position(0)
            Log.d("Native", "Vertex buffer ${contentToString()}")
        }
        GLES30.glVertexAttribPointer(vertexLocation, 2, GLES30.GL_FLOAT, false, 0, vertexBuffer)
        checkGlError("Attribute 0")

        // Just render a triangle
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 3)

        GLES30.glFinish()
        checkGlError("Finished GL")
    }

}

我的调试输出记录了我所期望的:

D/Native: Compiling shader #2 : 
D/Native: Compiling shader #3 : 
D/Native: Vertex buffer [-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0]

我包括 <uses-feature android:glEsVersion="0x00020000" android:required="true" />在我的 list 中。三角形的几何图形没有呈现在屏幕上或不可见,我哪里出错了?

最佳答案

当您为 GL 创建 Buffer 时,您需要指定native byte-order

val vertices = floatArrayOf(-1f, -1f, 1f, -1f, -1f, 1f, 1f, 1f)
vertexBuffer = ByteBuffer.allocateDirect(vertices.size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().also {
    it.put(vertices)
    it.position(0)
}

关于android - 在 Android OpenGL ES 上只能看到没有几何图形的 glClear 颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73185048/

相关文章:

android-studio - 原因 : duplicate entry: AndroidManifest. xml

ios - 扭曲图像以在屏幕上产生雨滴效果

ios - EAGLView : rotation doesn't change frame size

android - 如何清除gradle缓存?

java - 我应该在哪里声明我的变量?

android - 自定义 fragment 的偏好

Android View vs SurfaceView vs GLSurfaceView for 2D drawing app with Zoomable User Interface

android - 没有找到类 "mono.android.app.Application"

android - 如何使用 ARCore Camera 拍摄带有物体的图像?

android - ExoPlayer:处理延迟加载播放列表的最佳方法是什么?