开启OpenGL ES探索之旅——EGL环境搭建与三角形纹理渲染初探
2023-11-24 23:12:15
在上一篇探索之旅中,我们成功地创建了一个简单的OpenGL ES应用程序,并向你介绍了基本概念。现在,让我们更进一步,深入了解OpenGL ES的图形渲染机制。
定义渲染器基类
为了让渲染过程更加灵活和可重用,我们将创建一个渲染器基类RendererBase,它将包含所有与渲染相关的通用方法。这样,在后续的渲染任务中,我们只需继承该基类即可。
public abstract class RendererBase implements GLSurfaceView.Renderer {
// 着色器程序
private int mProgram;
// 顶点坐标
private float[] mVertices = {...};
// 纹理坐标
private float[] mTexCoords = {...};
// 纹理ID
private int mTextureId;
// 顶点着色器
private String mVertexShader = {...};
// 片段着色器
private String mFragmentShader = {...};
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// 初始化着色器程序
mProgram = createProgram(mVertexShader, mFragmentShader);
// 加载纹理
mTextureId = loadTexture(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.triangle));
// 启用顶点属性数组
glEnableVertexAttribArray(POSITION_ATTRIBUTE);
glEnableVertexAttribArray(TEXCOORD_ATTRIBUTE);
// 设置顶点属性指针
glVertexAttribPointer(POSITION_ATTRIBUTE, COORDS_PER_VERTEX, GL_FLOAT, false, 0, mVertices);
glVertexAttribPointer(TEXCOORD_ATTRIBUTE, TEXCOORDS_PER_VERTEX, GL_FLOAT, false, 0, mTexCoords);
// 启用纹理单元
glEnable(GL_TEXTURE_2D);
// 绑定纹理到纹理单元
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTextureId);
// 设置纹理环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 设置纹理过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// 设置视口
glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
// 清空颜色缓冲区
glClear(GL_COLOR_BUFFER_BIT);
// 使用着色器程序
glUseProgram(mProgram);
// 绘制三角形
glDrawArrays(GL_TRIANGLES, 0, mVertices.length / COORDS_PER_VERTEX);
}
// 创建着色器程序
private int createProgram(String vertexShader, String fragmentShader) {
// 编译顶点着色器
int vertexShaderId = loadShader(GL_VERTEX_SHADER, vertexShader);
// 编译片段着色器
int fragmentShaderId = loadShader(GL_FRAGMENT_SHADER, fragmentShader);
// 创建着色器程序
int program = glCreateProgram();
// 将顶点着色器和片段着色器附加到程序
glAttachShader(program, vertexShaderId);
glAttachShader(program, fragmentShaderId);
// 链接程序
glLinkProgram(program);
// 检查程序是否链接成功
int[] linkStatus = new int[1];
glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == GL_FALSE) {
throw new RuntimeException("Could not link program: " + glGetProgramInfoLog(program));
}
// 返回程序ID
return program;
}
// 加载着色器
private int loadShader(int type, String shaderCode) {
// 创建着色器对象
int shader = glCreateShader(type);
// 设置着色器源代码
glShaderSource(shader, shaderCode);
// 编译着色器
glCompileShader(shader);
// 检查着色器是否编译成功
int[] compileStatus = new int[1];
glGetShaderiv(shader, GL_COMPILE_STATUS, compileStatus, 0);
if (compileStatus[0] == GL_FALSE) {
throw new RuntimeException("Could not compile shader: " + glGetShaderInfoLog(shader));
}
// 返回着色器对象
return shader;
}
// 加载纹理
private int loadTexture(Bitmap bitmap) {
// 创建纹理对象
int[] textureIds = new int[1];
glGenTextures(1, textureIds, 0);
int textureId = textureIds[0];
// 绑定纹理到纹理单元
glBindTexture(GL_TEXTURE_2D, textureId);
// 设置纹理参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 上传纹理数据
BitmapBuffer bitmapBuffer = new BitmapBuffer(bitmap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap.getWidth(), bitmap.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmapBuffer);
// 解绑纹理
glBindTexture(GL_TEXTURE_2D, 0);
// 返回纹理ID
return textureId;
}
}
使用Android封装好的EGL环境(GLSurfaceView)来渲染三角形纹理
在Android中,我们可以使用GLSurfaceView来方便地创建和管理一个OpenGL ES渲染环境。GLSurfaceView是一个继承自SurfaceView的视图控件,它提供了对OpenGL ES的封装,让我们可以轻松地进行渲染。
首先,在布局文件中添加GLSurfaceView:
<android.opengl.GLSurfaceView
android:id="@+id/glSurfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
然后,在Activity中初始化GLSurfaceView:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GLSurfaceView glSurfaceView = (GLSurfaceView) findViewById(R.id.glSurfaceView);
glSurfaceView.setEGLContextClientVersion(2);
glSurfaceView.setRenderer(new MyRenderer());
}
在上面的代码中,我们首先设置了GLSurfaceView的EGL版本为2.0,然后设置了渲染器为MyRenderer。MyRenderer继承了我们定义的渲染器基类RendererBase,并实现了渲染相关的回调方法。
这样,我们就可以通过GLSurfaceView来渲染三角形纹理了。当GLSurfaceView准备好渲染时,它会调用onSurfaceCreated()方法,我们可以在该方法中初始化着色器程序、加载纹理等。当GLSurfaceView的大小发生变化时,它会调用onSurfaceChanged()方法,我们可以在该方法中设置视口。当GLSurfaceView需要重新渲染时,它会调用onDrawFrame()方法,我们可以在该方法中绘制三角形。
至此,我们就完成了OpenGL ES渲染三角形纹理的示例。通过这篇博客,你已经掌握了OpenGL ES的基本渲染流程和EGL环境的使用方法。在接下来的探索之旅中,我们将继续深入研究OpenGL ES,学习更多的图形渲染技术。
文章概要
-
定义了一个渲染器基类RendererBase,方便后续渲染任务的重用。
-
使用Android封装好的EGL环境(GLSurfaceView)来渲染三角形纹理。
-
介绍了GLSurfaceView的基本用法,包括设置EGL版本、设置渲染器等。
-
OpenGL ES
-
图形渲染