OpenGL ES:基本形状的绘制(三角形、正方形、正方体)
三角形的绘制
-
编写顶点着色器和片段着色器代码
输入和输出:基于OpenGL的渲染流程,从而每个着色器都有输入和输出,这样才能进行数据交流和传递。GLSL定义了in和out关键字专门来达成这个目的。只要一个输出变量与下一个着色器阶段的输入匹配,它就会传递下去。
Uniform关键字:Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同。
- uniform是全局的(Global)
- 无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新
//顶点着色器
//声明OpenGL es版本
#version 300 es
//in 代表输入属性
//顶点坐标属性
layout(location = 0) in vec3 aPos;
//颜色属性
layout(location = 1) in vec3 aColor;
//out 代表传递给片段着色器的属性
out vec3 color;
void main(){
//gl_Position是内置的属性
gl_Position= vec4(aPos.x,aPos.y,aPos.z,1.0f);
color= aColor;
}
//片段着色器
#version 300 es
//定义浮点精度
precision mediump float;
//颜色采样输出
out vec4 fragColor;
//链接顶点着色器的同名输出
in vec3 color;
void main(){
fragColor=vec4(color,1.0f);
}
-
编写渲染类,实现GLSurfaceView.Renderer接口中的三个方法:
onSurfaceCreated: 做一些初始化操作
- 创建OpenGL ES执行程序
- 加载顶点着色器和片段着色器并将它们依附到执行程序上
- 链接程序
public static int createGlProgram(String vertexSourcePath, String fragmentSourcePath, Resources resources){
//创建OpenGL ES执行程序
int program = GLES30.glCreateProgram();
if (vertexSourcePath != null && fragmentSourcePath != null) {
//加载着色器
int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, getSource(vertexSourcePath,resources));
int fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, getSource(fragmentSourcePath,resources));
//把着色器依附到program上
GLES30.glAttachShader(program,vertexShader);
GLES30.glAttachShader(program,fragmentShader);
}
//链接program
GLES30.glLinkProgram(program);
//检查是否链接成功
int[] linked = new int[1];
GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, linked, 0);
if (linked[0] == 0) {
Log.d("error", GLES30.glGetProgramInfoLog(program));
GLES30.glDeleteProgram(program);
}
return program;
}
onSurfaceChanged: surface尺寸改变回调,可在其中进行相应的OpenGL的视图尺寸设置。
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES30.glViewport(0,0,width,width);
}
onDrawFrame: 在此回调中绘制图形
//使用顶点数组对象和顶点缓存对象 推荐使用此方法
private void drawByVaoAndVbo(){
//清除颜色和深度信息
GLES30.glClearColor(1f,1f,1f,0.0f);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
//设置执行程序
//使用此program 添加此program到OpenGL ES环境中去
GLES30.glUseProgram(program);
//生成VBO并绑定
int[] VBOs = new int[1];
GLES30.glGenBuffers(1, VBOs, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOs[0]);
//赋予数据
//size 指的是 数组的总字节数
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertices.length*4, OpenGlUtils.array2Buffer(vertices), GLES30.GL_STATIC_DRAW);
//激活顶点位置属性并赋值
GLES30.glEnableVertexAttribArray(0);
GLES30.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 6 * 4, 0);
//激活颜色属性并赋值
GLES30.glEnableVertexAttribArray(1);
GLES30.glVertexAttribPointer(1,3,GLES20.GL_FLOAT,false,6*4,3*4);
//绘制三角形
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN,0,3);
//删除缓存
GLES30.glDeleteBuffers(1,VBOs,0);
}
//以顶点数组的方式绘制
private void draw(){
//设置背景颜色
GLES30.glClearColor(1f,1f,1f,0.0f);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
//使用此program 添加此program到OpenGL ES环境中去
GLES30.glUseProgram(program);
GLES30.glEnableVertexAttribArray(0);
GLES30.glEnableVertexAttribArray(1);
//index 代表属性位置值 size 代表这个顶点属性的分量数 stride 代表一个顶点到下一个顶点到跨距(单位:字节) offset 代表偏移
GLES30.glVertexAttribPointer(0,3, GLES20.GL_FLOAT,false,3*4,OpenGlUtils.array2Buffer(points));
GLES30.glVertexAttribPointer(1,3,GLES20.GL_FLOAT,false,12,OpenGlUtils.array2Buffer(colors));
GLES30.glDrawArrays(GLES30.GL_TRIANGLES,0,3);
}
- 交给GLSurfaceView渲染
//设置OpenGL ES的版本
glSurfaceView.setEGLContextClientVersion(3);
//设置渲染对象
glSurfaceView.setRenderer(renderer);
//设置渲染模式 1.持续渲染(默认) 2.单次渲染
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
学习了三角形的绘制,大概可以了解到OpenGL 图元的绘制流程,其他图形的绘制流程也一样,无非是绘制的代码有所变动。