这里主要以三角形的例子进行;最重要红色字体部分,没有这部分,是无法描绘出来的画面的
AndroidManifest.xml设置
<!--opengl 版本 选择3.2-->
<uses-feature android:glEsVersion="0x00030002" android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
在Activity里面获取到GLSurfaceview的实例,通过setEGLContextClientVersion获取OPENGL ES上下文。这个方法的作用是为了确保OpenGL ES 3.2的上下文环境被正确地初始化和使用。在使用OpenGL ES 3.2进行渲染时,必须通过这个函数来激活OpenGL E 3.2的上下文环境。只有在有效的OpenGL ES上下文环境下,才能进行渲染操作
GLSurfaceView glSurfaceView=findViewById(R.id.gl);
glSurfaceView.setEGLContextClientVersion(3);
glSurfaceView.setRenderer(new GLTriangleRender());
其他的大部分在网上可以查到,我这里给一个完整的Triangle例子。
GLTriangle.class
package xxx.xiao.mulviewshow;
import android.opengl.GLES32;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
/**
* author:tiwolf
* create date:2023/5/13
* Describe: 画三角形
*/
public class GLTriangle {
// 顶点着色器的脚本
String vertexShaderCode =
" attribute vec4 vPosition;" + // 应用程序传入顶点着色器的顶点位置
" void main() {" +
" gl_Position = vPosition;" + // 此次绘制此顶点位置
" }";
// 片元着色器的脚本
String fragmentShaderCode =
" precision mediump float;" + // 设置工作精度
" uniform vec4 vColor;" + // 接收从顶点着色器过来的顶点颜色数据
" void main() {" +
" gl_FragColor = vColor;" + // 给此片元的填充色
" }";
private FloatBuffer vertexBuffer; //顶点坐标数据要转化成FloatBuffer格式
// 数组中每3个值作为一个坐标点
static final int COORDS_PER_VERTEX = 3;
//三角形的坐标数组
static float triangleCoords[] = {
0.0f, 0.5f, 0.0f, // top
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f // bottom right
};
//顶点个数,计算得出
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
//一个顶点有3个float,一个float是4个字节,所以一个顶点要12字节
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
//三角形的颜色数组,rgba
private float[] mColor = {
0.0f, 1.0f, 0.0f, 1.0f,
};
//当前绘制的顶点位置句柄
private int vPosition;
//片元着色器颜色句柄
private int vColor;
//这个可以理解为一个OpenGL程序句柄
private final int mProgram;
public GLTriangle() {
/** 1、数据转换,顶点坐标数据float类型转换成OpenGL格式FloatBuffer,int和short同理*/
vertexBuffer = GLUtil.floatArray2FloatBuffer(triangleCoords);
/** 2、加载编译顶点着色器和片元着色器*/
int vertexShader = GLUtil.loadShader(GLES32.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = GLUtil.loadShader(GLES32.GL_FRAGMENT_SHADER,
fragmentShaderCode);
/** 3、创建空的OpenGL ES程序,并把着色器添加进去*/
mProgram = GLES32.glCreateProgram();
// 添加顶点着色器到程序中
GLES32.glAttachShader(mProgram, vertexShader);
// 添加片段着色器到程序中
GLES32.glAttachShader(mProgram, fragmentShader);
/** 4、链接程序*/
GLES32.glLinkProgram(mProgram);
}
public void draw() {
// 将程序添加到OpenGL ES环境
GLES32.glUseProgram(mProgram);
/***在什么位置显示什么颜色*/
// 获取顶点着色器的位置的句柄(这里可以理解为当前绘制的顶点位置)
vPosition = GLES32.glGetAttribLocation(mProgram, "vPosition");
// 启用顶点属性
GLES32.glEnableVertexAttribArray(vPosition);
//准备三角形坐标数据
GLES32.glVertexAttribPointer(vPosition, COORDS_PER_VERTEX,
GLES32.GL_FLOAT, false,
vertexStride, vertexBuffer);
// 获取片段着色器的vColor属性
vColor = GLES32.glGetUniformLocation(mProgram, "vColor");
// 设置绘制三角形的颜色
GLES32.glUniform4fv(vColor, 1, mColor, 0);
// 绘制三角形
GLES32.glDrawArrays(GLES32.GL_TRIANGLES, 0, vertexCount);
// 禁用顶点数组
GLES32.glDisableVertexAttribArray(vPosition);
}
}
GLTriangleRender.java
package xxx.xiao.mulviewshow.render;
import android.opengl.GLES32;
import android.opengl.GLES32;
import android.opengl.GLSurfaceView;
import android.util.Log;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import xxx.xiao.mulviewshow.GLTriangle;
/**
* author:tiwolf
* create date:2023/5/13
* Describe:
*/
public class GLTriangleRender implements GLSurfaceView.Renderer {
private GLTriangle mGlTriangle;
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
Log.i("TAG", "onSurfaceCreated: 创建着色器脚本");
//进行背景色描绘
GLES32.glClearColor(0.0f,0.5f,0.5f,0.5f);
GLES32.glClear(GLES32.GL_COLOR_BUFFER_BIT);
//进行着色器脚本相关创建
mGlTriangle=new GLTriangle();
}
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
// 设置绘图的窗口
Log.i("TAG", "onSurfaceCreated: 绘制绘图窗口");
GLES32.glViewport(100,100,200,300);
}
@Override
public void onDrawFrame(GL10 gl10) {
Log.i("TAG", "onDrawFrame: 开始刷新绘制");
mGlTriangle.draw();
}
}
GLUtil.java
package xxx.xiao.mulviewshow;
import android.opengl.GLES32;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
/**
* author:tiwolf
* create date:2023/5/13
* Describe:
*/
public class GLUtil {
public static FloatBuffer floatArray2FloatBuffer(float[] floatArra){
FloatBuffer vertexBuffer= ByteBuffer.allocateDirect(floatArra.length*4) //一个float占4个字节
.order(ByteOrder.nativeOrder()) //使用本地字节库
.asFloatBuffer();
vertexBuffer.put(floatArra);
vertexBuffer.position(0); //重置Buffer位置,使其可以被OpenGL读取
return vertexBuffer;
}
public static int loadShader(int shaderType,String source){
// 创造顶点着色器类型(GLES32.GL_VERTEX_SHADER)
// 或者是片段着色器类型 (GLES32.GL_FRAGMENT_SHADER)
int shader = GLES32.glCreateShader(shaderType);
// 添加上面编写的着色器代码并编译它
GLES32.glShaderSource(shader, source);
GLES32.glCompileShader(shader);
return shader;
}
}