OpenGL

148 阅读5分钟

前言

绘制全屏红色

/**
 * GL测试视图
 */
public class GLView extends GLSurfaceView {
    private GLRender mRender;
    public GLView(Context context) {
        this(context,null);
    }

    public GLView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    private void init(){
        // 设置OpenGL ES 2.0 context
        setEGLContextClientVersion(2);
        mRender = new GLRender();
        // 设置渲染器
        setRenderer(mRender);
    }
}
/**
 * GL渲染类
 */
public class GLRender implements GLSurfaceView.Renderer {
    private static final String TAG = "=Test=GLRender";
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        Log.d(TAG,"onSurfaceCreated");
        // rbga
        GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        Log.d(TAG,"onSurfaceChanged width:"+width+" height:"+height);
        // GL视口
        GLES20.glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        Log.d(TAG,"onDrawFrame");
        // 清除颜色缓冲和深度缓存
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    }
}

绘制三角形

三角形:

/**
 * 三角形
 */
public class Triangle {
    // 顶点缓冲
    private FloatBuffer vertexBuffer;
    // 顶点着色代码
    private final String vertexShaderCode = "attribute vec4 vPosition;" +
            "void main() {" +
            "  gl_Position = vPosition;" +
            "}";
    // 片元着色代码
    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";
    private final int mProgram;
    // 位置句柄
    private int mPositionHandle;
    private int mColorHandle;// 颜色句柄

    static float sCoo[] = {   //以逆时针顺序
            0.0f, 0.0f, 0.0f, // 顶部
            -1.0f, -1.0f, 0.0f, // 左下
            1.0f, -1.0f, 0.0f  // 右下
    };
    // 数组中每个顶点的坐标数
    static final int COORDS_PER_VERTEX = 3;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 3*4=12
    private final int vertexCount = sCoo.length / COORDS_PER_VERTEX;// 顶点个数
    // 颜色,rgba
    float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};

    public Triangle() {
        // 初始化顶点字节缓冲区; 每个浮点数:坐标个数 * 4字节
        ByteBuffer bb = ByteBuffer.allocateDirect(sCoo.length*4);
        // 使用本机硬件设备的字节顺序
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();// 从字节缓冲区创建浮点缓冲区
        vertexBuffer.put(sCoo);// 将坐标添加到loatBuffer
        vertexBuffer.position(0);// 设置缓冲区以读取第一个坐标
        int vertexShader = GLRender.loadShader(GLES20.GL_VERTEX_SHADER// 顶点着色
                ,vertexShaderCode);
        int fragmentShader = GLRender.loadShader(GLES20.GL_FRAGMENT_SHADER// 片元着色
                ,fragmentShaderCode);
        mProgram = GLES20.glCreateProgram();// 创建空的OpenGL ES 程序
        GLES20.glAttachShader(mProgram,vertexShader);// 加入顶点着色器
        GLES20.glAttachShader(mProgram,fragmentShader);// 加入片元着色器
        GLES20.glLinkProgram(mProgram);// 创建可执行的OpenGL ES 项目
    }
    public void draw(){
        // 将程序添加到OpenGL ES环境中
        GLES20.glUseProgram(mProgram);
        // 获取顶点着色器的vPosition成员的句柄
        mPositionHandle = GLES20.glGetAttribLocation(mProgram,"vPosition");
        // 启用三角形顶点的句柄
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        // 准备三角形坐标数据
        GLES20.glVertexAttribPointer(mPositionHandle// int index,索引
                ,COORDS_PER_VERTEX,// int size 大小
                GLES20.GL_FLOAT,// int type 类型
                false,// 是否标准化
                vertexStride// 跨度
                ,vertexBuffer// 缓冲
        );
        // 获取片元着色器的vColor成员句柄
        mColorHandle = GLES20.glGetUniformLocation(mProgram,"vColor");
        // 为三角形设置颜色
        GLES20.glUniform4fv(mColorHandle,1,color,0);
        // 绘制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,vertexCount);
        // 禁用顶点数组:
        /**
         * 禁用index指定的通用顶点属性数组
         * 默认情况下,禁用所有客户端功能,包括所有的通用顶点属性数组
         * 如果启用,将访问通用顶点属性数组中的值
         * 并在调用顶点数组命令(如:glDrawArrays或glDrawElements)时用于呈现。
         */
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }
}

GL渲染类:

/**
 * GL渲染类
 */
public class GLRender implements GLSurfaceView.Renderer {
    private static final String TAG = "=Test=GLRender";
    Triangle mTriangle;

    /**
     * 加载作色器
     * @param type 顶点着色(GLES20.GL_VERTEX_SHADER); 片元着色(GLES20.GL_FRAGMENT_SHADER)
     * @param shaderCode 着色代码
     * @return 作色器
     */
    public static int loadShader(int type,String shaderCode){
        int shader = GLES20.glCreateShader(type);// 创建着色器
        GLES20.glShaderSource(shader,shaderCode);// 添加着色器源代码
        GLES20.glCompileShader(shader);// 编译
        return shader;
    }
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        Log.d(TAG,"onSurfaceCreated");
        // rbga
        GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
        mTriangle = new Triangle();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        Log.d(TAG,"onSurfaceChanged width:"+width+" height:"+height);
        // GL视口
        GLES20.glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        Log.d(TAG,"onDrawFrame");
        // 清除颜色缓冲和深度缓存
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        mTriangle.draw();
    }
}

OpenGl ES 着色脚本语言

GLSL(OpenGL Shader Language)。没有统一的拓展名。

.vert - 顶点着色器
.tesc - 曲面细分控制着色器
.tese - 曲面细分评估着色器
.geom - 集合着色器
.frag - 片元着色器
.comp - 计算着色器

原生数据类型:

float 浮点型
bool 布尔型
int 整型
|--- 支持8进制(0开头) 16进制(0x开头)

向量:存储及操作 颜色、位置、纹理坐标等

vec2 二维向量-浮点型
vec3 三维向量-浮点型
vec4 四维向量-浮点型

ivec2 二维向量-整型
ivec3 三维向量-整型
ivec4 四维向量-整型

bvec2 二维向量-布尔型
bvec3 三维向量-布尔型
bvec4 四维向量-布尔型

矩阵:根据矩阵的运算进行变换操作

mat2 2x2矩阵-浮点型
mat3 3x3矩阵-浮点型
mat4 4x4矩阵-浮点型

采样器:

sampler2D 二维纹理
sampler3D 三维纹理
samplerCube 立方贴图纹理

结构体:

struct ball{
    // 三维向量浮点型
    vec3 color;
    vec3 position;
}

数组:

vec3 pos[];// 声明不定大小的三维向量浮点数组
vec3 pos[6];// 声明6个三维向量浮点数组

限定符:

attribute 顶点的变量,如:顶点位置、颜色
uniform
varying 用于从顶点着色其传递到片元着色器的变量
const
precision 精度
|---lowp
|---mediump
|---highp

资源文件读取:

/**
 * OpenGL ES 辅助工具:资源文件读取
 */
public class GLUtils {
    /**
     * 从脚本中加载shader内容的方法
     */
    public static int loadShaderAssets(Context ctx,int type,String name){
        String result = null;
        try {
            InputStream in = ctx.getAssets().open(name);
            int ch =0;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((ch-in.read())!=-1){
                baos.write(ch);
            }
            byte[] buff = baos.toByteArray();
            baos.close();
            in.close();
            result = new String(buff,"UTF-8");
            result = result.replaceAll("\r\n","\n");
        }catch (Exception e){
            e.printStackTrace();
        }
        return load
    }

    /**
     * 加载着色器
     * @param type 着色器类型;顶点着色器(GLES20.GL_VERTEX_SHADER); 片元着色器(GLES20.FRAGMENT_SHADER)
     * @param shaderCode 着色代码
     * @return 着色器
     */
    public static int loadShader(int type,String shaderCode){
        int shader = GLES20.glCreateShader(type);// 创建着色器
        if (shader==0){// 加载失败,直接返回
            return 0;
        }
        GLES20.glShaderSource(shader,shaderCode);// 加载着色器源代码
        GLES20.glCompileShader(shader);// 编译
        return checkCompile(type,shader);
    }

    /**
     * 检查shader代码是否编译成功
     * @param type 着色器类型
     * @param shader 着色器
     * @return 着色器
     */
    private static int checkCompile(int type,int shader){
        int[] compiled = new int[1];// 存放编译成功shader数量的数组
        // 获取shader编译情况
        GLES20.glGetShaderiv(shader,GLES20.GL_COMPILE_STATUS,compiled,0);
        if (compiled[0]==0){// 若编译失败则显示错误日志
            Log.e("ES20_COMPILE_ERR","Could not compile shader "+type+":"+
                    GLES20.glGetShaderInfoLog(shader));
            shader = 0;
        }
        return shader;
    }

}

片元

tri.frag 声明片元精度;声明片元颜色,gl_FragColor是gl内定名。

precision mediump float;
uniform vec4 vColor;
void main() {
  gl_FragColor = vColor;
}
// 颜色,rgba
float color[] = {0.63671875f, 0.76953125f, 0.22265625f, 1.0f};

顶点

tri.vert

定义了一个四维向量给gl_Position

attribute vec4 vPosition;
void main() {
  gl_Position = vPosition;
}