Android OpenGL学习:最小系统绘制
Posted MichaelX_Blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android OpenGL学习:最小系统绘制相关的知识,希望对你有一定的参考价值。
文章目录
最小系统目标
利用OpenGL对应api在屏幕上绘制一个平面三角形。
整体流程
- 编写着色器脚本
- 定义三角形
- 定义渲染器
- 应用渲染器
编写着色器脚本
vertex_shader.glsl 顶点着色器
attribute vec4 vPosition;
void main()
# gl_Position是固定表达
gl_Position = vPosition;
fragment_shader.glsl
precision mediump float;
uniform vec4 vColor;
void main()
# gl_FragColor是固定表达
gl_FragColor = vColor;
将脚本放入res/raw/ 文件夹下。
可参考链接:
《OpenGL shader GLSL 语法和函数详解》
定义三角形
Triangle.java
/**
* 三角形
*
* @version 1.0
* @since 2019/3/8
*/
public class Triangle implements Shape
// 坐标本地内存地址
private FloatBuffer vertexBuffer;
// 取几个点
private static final int COORDS_PER_VERTEX = 3;
// 三角形坐标
private static final float triangleCoords[] =
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.3f, 0.0f
;
// 设置颜色 red, green, blue 和 alpha (可选) values
private static final float color[] = 0.0f, 1.0f, 0f, 1.0f;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
// 顶点数量
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
// 每个顶点4byte
private final int vertexStride = COORDS_PER_VERTEX * 4;
public Triangle(Context context)
vertexBuffer = ByteBuffer.allocateDirect(triangleCoords.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(triangleCoords);
vertexBuffer.put(0);
//根据shader代码和fragment代码 获取到一个渲染程序
mProgram = ShaderUtil.createProgram(ShaderUtil.readRawTxt(context, R.raw.vertex_shader),
ShaderUtil.readRawTxt(context, R.raw.fragment_shader));
if (mProgram > 0)
//获取vertex shader的属性vPosition 的地址
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
//获取fragment shader的属性vColor 的地址
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
@Override
public void draw()
// 使用渲染程序
GLES20.glUseProgram(mProgram);
// 使顶点属性数组有效
GLES20.glEnableVertexAttribArray(mPositionHandle);
// 为顶点属性赋值
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
// 设置颜色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// 绘制图形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// 禁用顶点数组
GLES20.glDisableVertexAttribArray(mPositionHandle);
工具类ShaderUtil.java代码
public class ShaderUtil
private static final String TAG = "ShaderUtil";
public static String readRawTxt(Context context, int rawId)
InputStream inputStream = context.getResources().openRawResource(rawId);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer sb = new StringBuffer();
String line;
try
while ((line = reader.readLine()) != null)
sb.append(line).append("\\n");
reader.close();
catch (Exception e)
e.printStackTrace();
return sb.toString();
public static int loadShader(int shaderType, String source)
// 创建一个顶点或者片段shader
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0)
// 添加代码到shader
GLES20.glShaderSource(shader, source);
// 编译shader
GLES20.glCompileShader(shader);
int[] compile = new int[1];
// 检查编译结果
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0);
int err = GLES20.glGetError();
if (compile[0] != GLES20.GL_TRUE)
Log.e(TAG, "shader compile error:" + err);
GLES20.glDeleteShader(shader);
shader = 0;
return shader;
public static int createProgram(String vertexSource, String fragmentSource)
// 获取片段shader
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (fragmentShader == 0)
return 0;
// 获取顶点shader
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0)
return 0;
// 创建一个空的渲染程序
int program = GLES20.glCreateProgram();
if (program != 0)
//添加vertexShader到渲染程序
GLES20.glAttachShader(program, vertexShader);
//添加fragmentShader到渲染程序
GLES20.glAttachShader(program, fragmentShader);
// 关联可执行渲染程序
GLES20.glLinkProgram(program);
// 检查是否关联成功
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
int err = GLES20.glGetError();
if (linkStatus[0] != GLES20.GL_TRUE)
Log.e(TAG, "link program error:" + err);
GLES20.glDeleteProgram(program);
program = 0;
return program;
插播一条Shader的创建流程图
定义渲染器
MyRender.java
public class MyRender implements GLSurfaceView.Renderer
private Context context;
private Shape shape;
public MyRender(Context context)
this.context = context;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
shape = new Triangle(context);
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
GLES20.glViewport(0, 0, width, height);
@Override
public void onDrawFrame(GL10 gl)
// 清空颜色
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// 绘制三角形
shape.draw();
应用渲染器
MyGLSurfaceView.java
public class MyGLSView extends GLSurfaceView
public MyGLSView(Context context)
this(context, null);
public MyGLSView(Context context, AttributeSet attrs)
super(context, attrs);
setEGLContextClientVersion(2);
// 应用渲染器
setRenderer(new MyRender(context));
只要将MyGLSurfaceView应用到Activity就好了。。。
OpenGL管道概述(题外)
OpenGL是一套流程,而非特定API或者类。如下所示:应用层主要业务是:①,②,⑤。
①读取顶点数据
->②执行顶点着色器
->③组装图元
->④光栅化图元
->⑤执行片段着色器
->⑥写入帧缓冲区
->⑦显示在屏幕上
以上是关于Android OpenGL学习:最小系统绘制的主要内容,如果未能解决你的问题,请参考以下文章