【OpenGL ES】OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解(一)

一. 程序介绍



1. 样例展示


该程序打开之后会出现一个旋转的三角形, 该三角形一直绕x轴z方向旋转 如图 :

【OpenGL ES】OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解(一)

【OpenGL ES】OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解(一)






2. 程序结构


本程序中定义了四个类 : ShaderUtil , Triangle , MyTDView , MainActivity .



在Activity中加载myTDView对象, MyTDView对象中绘制Triangle 三角形图形, Triangle调用ShaderUtil加载着色脚本并创建着色程序.



四个类之间的关系 :

【OpenGL ES】OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解(一)





3. 方法介绍


(1) ShaderUtil方法


a. 加载着色器方法 : 根据着色器类型 和 着色器脚本字符串获取着色器



public static int loadShader(int shaderType , String source)

流程 : 创建着色器 -> 加载着色器脚本 -> 编译着色器 -> 获取着色器编译结果



b. 检查错误方法 : 检查每一步是否出现错误



public static void checkGLError(String op)

流程 : 循环获取错误信息, 知道出现异常将异常信息打印出来




c. 创建着色器方法 : 根据顶点着色器和片元着色器创建着色程序



public static int createProgram(String vertexSource , String fragmentSource)

流程 : 调用loadShader()加载顶点,片元着色器 -> 创建着色程序 -> 向着色程序中加载顶点,片元着色器 -> 连接程序 -> 获取链接结果




d. 获取着色脚本 : 从assets目录中的着色脚本中获取着色脚本的字符串信息



public static String loadFromAssetsFile(String fileName, Resources resources)

流程 : 打开assets输入流 -> 创建带缓冲区的输出流 -> 读取输入流信息放入缓冲区 -> 将缓冲区数据转为字符




二  ShaderUtils类介绍  

1.安卓基本API

(1) 创建assets目录中文件的输入流


InputStream is = resources.getAssets().open(fileName);

参数 : assets目录中着色脚本的文件名;



返回值 : 着色脚本文件的输入流;


作用 : 使用该输入流可以读取着色脚本信息



(2)带缓冲区的输出流


 

创建一个带缓冲区的输出流, 每次读取一个字节, 注意这里字节读取用的是int类型
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    逐个字节读取数据, 并将读取的数据放入缓冲器中
    while((ch = is.read()) != -1){
    baos.write(ch);
    }
    将缓冲区中的数据转为字节数组, 并将字节数组转换为字符串
    byte[] buffer = baos.toByteArray();


读写单位 : 这个输出流读取字节的单位是int, 这里要特别注意;



读取方法 : read()方法每次读取一个字节, 并返回读取到的字节;  


写出方法 : write()方法将一个字节写入到ByteArrayOutputStream的缓冲区中;


导出数据 : 调用toByteArray()方法可以将缓冲区中的数据转为字节数组, 并返回这个数组;





2.着色器相关API介绍

加载着色器流程 : 创建着色器 --> 加载着色器脚本 --> 编译着色器 --> 获取着色器编译结果

(1)创建着色程器


int shader = GLES20.glCreateShader(shaderType);

参数 : 这个函数的作用根据着色器类型 , 着色器的类型有两种 , GLES20.GL_VERTEX_SHADER 顶点着色器 , GLES20.GL_FRAGMENT_SHADER 片元着色器



返回值 : 该方法返回的是着色器的引用



(2)加载着色器源代码

GLES20.glShaderSource(shader, source);

参数 : shader是着色器的引用 , 是glCreateShader()方法的返回值 ;  source是着色器脚本的字符串形式 .

返回值 : 该方法没有返回值

这样就相当于将代码添加到了着色器中, 注意此时着色器还不能使用 , 还要编译之后才能使用.

(3)编译着色器

GLES20.glCompileShader(shader);

参数 : shader是着色器的引用

返回值 : 该方法没有返回值类型

执行这个方法的前提是 , 该着色器已经加载了着色器脚本字符串, 否则会编译错误

(4)获取着色器编译情况

int complied[] = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, complied, 0);

参数 :

shader : 着色器引用 , 这个着色器已经加载了着色脚本字符串以及经过了编译 ;

pname : GLES20.GL_COMPILE_STATUS : 获取信息类型代码 : 我们要获取编译情况 , 这里是编译状态的代码

params[] : compile : 存放结果数组

index : 存放结果索引 , 将编译成功的脚本数放在数组的哪个索引下

返回值 : 该方法没有返回值

(5)删除着色器

GLES20.glDeleteShader(shader);

参数 : shader 是着色器的引用

返回值 : 该方法没有返回值

如果着色器编译没有通过 , 那么就删除这个着色器


上一篇:通过数据流处理-微信小程序生成临时二维码


下一篇:C# 关于调用微信接口的代码