我成功地跟踪了
this guide
用OpenGL画一个三角形,现在我试图修改代码来画一个圆。教程没有教我怎么做,所以我试着使用
here
,在页面的“For your toolbox”部分,我采用的方法是在OpenGL中定义一个正方形,然后按照建议
here
,使用片段着色器在正方形内绘制圆。这是我的圆类代码:
package com.example.onwards
import android.content.res.Resources
import android.opengl.GLES30
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
class Circle {
private val vertexCoords = floatArrayOf(
-0.5f, 0.5f, 0.0f, // top left
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f, // bottom right
0.5f, 0.5f, 0.0f // top right
)
private val resolution = floatArrayOf(
getScreenWidth().toFloat(),
getScreenHeight().toFloat()
)
private val vertexShaderCode =
""" |attribute vec4 vPosition;
|void main() {
| gl_Position = vPosition;
|}
|""".trimMargin()
private val fragmentShaderCode =
""" |precision mediump float;
|
|uniform vec2 vResolution;
|
|float circle(in vec2 st, in float r) {
| vec2 dist = st - vec2(0.5);
| return 1. - step(r * r, dot(dist, dist));
|}
|
|void main() {
| vec2 st = gl_FragCoord.xy / vResolution.xy;
| vec3 color = vec3(circle(st, 0.5));
| // TODO: Set alpha to 0 outside of circle
| gl_FragColor = vec4(color, 1.);
|}
|""".trimMargin()
private val vertexBuffer: FloatBuffer =
ByteBuffer.allocateDirect(vertexCoords.size * 4).run {
order(ByteOrder.nativeOrder())
asFloatBuffer().apply {
put(vertexCoords)
position(0)
}
}
private val vertexCount: Int = vertexCoords.size / COORDS_PER_VERTEX
private val vertexStride: Int = COORDS_PER_VERTEX * 4
private var program: Int
private var positionHandle: Int = 0
init {
val vertexShader: Int = loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode)
val fragmentShader: Int = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode)
program = GLES30.glCreateProgram().also {
GLES30.glAttachShader(it, vertexShader)
GLES30.glAttachShader(it, fragmentShader)
GLES30.glLinkProgram(it)
}
}
private fun loadShader(type: Int, shaderCode: String): Int {
return GLES30.glCreateShader(type).also { shader ->
GLES30.glShaderSource(shader, shaderCode)
GLES30.glCompileShader(shader)
}
}
private fun getScreenWidth(): Int {
return Resources.getSystem().displayMetrics.widthPixels
}
private fun getScreenHeight(): Int {
return Resources.getSystem().displayMetrics.heightPixels
}
fun draw() {
GLES30.glUseProgram(program)
positionHandle = GLES30.glGetAttribLocation(program, "vPosition").also {
GLES30.glEnableVertexAttribArray(it)
GLES30.glVertexAttribPointer(
it,
COORDS_PER_VERTEX,
GLES30.GL_FLOAT,
false,
vertexStride,
vertexBuffer
)
GLES30.glGetUniformLocation(program, "vResolution").also { resHandle ->
GLES30.glUniform2fv(resHandle, 1, resolution, 0)
}
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexCount)
GLES30.glDisableVertexAttribArray(it)
}
}
}
但是,运行这个应用程序只会在屏幕中央产生一个白色三角形。它的顶点在左上角、左下角和右下角,所以OpenGL似乎只绘制了正方形所需的一个三角形。
我注意到
drawOrder
和
drawListBuffer
变量来自
this section
在本教程的下一部分中从未使用过;它们只专注于绘制三角形而不是正方形。也许这和它有关?