OpenGL ES学习第三篇:定义一个最简单的纹理
本文你可以了解到
- OpenGL ES在应用层绘制流程
- 定义一个最简单的三角形纹理过程
- 使用native代码定义一个最简单的三角形纹理
OpenGL ES绘制分为三步
- 定义纹理
- 定义渲染器
- 定义EGL环境
定义纹理
纹理可以理解为Android页面开发中用于绘制在View上的Bitmap,有加载、绘制、释放三个生命周期
- 加载纹理
- 绘制纹理
- 释放纹理
- 辅助方法
1. 定义纹理基类接口类,包括以上生命周期方法
interface ITexture {
//加载纹理
fun surfaceCreated()
//绘制纹理
fun updateTexImage(){}
//释放纹理
fun surfaceDestroyed()
//辅助方法
fun surfaceChanged(w: Int, h: Int){}
fun setTextureSize(w: Int, h: Int){}
}
复制代码
2. 定义最简单的纹理实现:三角形纹理
顶点着色器设计:三角形只有一个平面,我们定义一个顶点数组,并提交给顶点着色器中gl_Position
变量
private val vertexCoords = floatArrayOf(// 需自行了解下OpenGL世界坐标体系
-1f, -1f,//左下
1f, -1f,//右下
0f, 0f//左上
)
private val vertexShader = "attribute vec4 aPosition;" +
"void main(){" +
" gl_Position=aPosition;" +
"}"
复制代码
片段着色器设计:片段着色器给顶点提交的结构进行着色,本例中为写死红色
private val fragShader = "precision mediump float;" +
"void main(){" +
" gl_FragColor=vec4(1.0, 0.0, 0.0, 1.0);" +
"}"
复制代码
然后就可以实现纹理的三个关键生命周期了ShaderUtil
为工具类方法。该方法比较固定,不做描述,自行查看。也奉劝诸位不要在意细节,封装好后基本上不会在查看,除非编译、链接shader代码出错时用来查bug。
override fun surfaceCreated() {
vertexBuffer = ByteBuffer.allocateDirect(vertexCoords.size * 4).run {
order(ByteOrder.nativeOrder())
asFloatBuffer()
}.apply {
put(vertexCoords)
position(0)
}
program = ShaderUtil.createProgram(vertexShader, fragShader)
//获取顶点着色器中的变量handle,用于给三角形赋值坐标
GLES20.glBindAttribLocation(program, aPositionIndex, "aPosition")
}
override fun updateTexImage() {
GLES20.glUseProgram(program)
//给顶点着色器中顶点赋值,第二个参数size为2意思是传入的坐标为2维坐标,绘制平面可以不需要z轴
GLES20.glVertexAttribPointer(aPositionIndex, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer)
GLES20.glEnableVertexAttribArray(aPositionIndex)//启用顶点
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 3)//绘制
GLES20.glDisableVertexAttribArray(aPositionIndex)
}
override fun surfaceDestroyed() {
GLES20.glDisableVertexAttribArray(aPositionIndex)
GLES20.glDeleteProgram(program)
}
复制代码
这样一个2D纹理三角形就定义好了,就可以通过渲染器绘制到屏幕上了
3. 补充:定义三角形纹理的native实现方式
代码类似,直接上,注意API版本从2换成了3,着色器使用稍有改动,可以看出代码写在native里会更简洁,所以OpenGL开发应该主要在native层写代码。
GLfloat vertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
0.0f, 0.0f
};
GLushort indices[] = {0, 1, 2};
void texture_triangle::surfaceCreated() {
char vertexSource[] = "#version 300 es \n"
"layout(location=0) in vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position=vPosition; \n"
"} \n";
char fragmentSource[] = "#version 300 es \n"
"precision mediump float; \n"
"out vec4 fragColor; \n"
"void main() \n"
"{ \n"
" fragColor=vec4(1.0, 0.0, 0.0, 1.0); \n"
"} \n";
program = ShaderUtil::createProgram(vertexSource, fragmentSource);
}
void texture_triangle::surfaceDestroyed() {
if (program) {
glDeleteProgram(program);
program = GL_NONE;
}
}
void texture_triangle::updateTexImage() {
glUseProgram(program);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices);
glUseProgram(GL_NONE);
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END