我正在尝试编写一个非常简单的 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/