第一章
GLSurfaceView的职责包括处理OpenGL中的初始化操作,配置显示设备(display)以及在后台线程中渲染。渲染是在显示设备中一个称为surface的区域完成的,这个区域也称为视口(viewport)。
第二章
在OpenGL中只能通过点,直线和三角形来构建复杂的图形。
- JNI
- 把Java堆分配到本地内存堆 Java API中有个特殊的类集合可以把java数据复制到本地内存中,本地内存可以被本地环境读取并且不会被垃圾回收器回收。 (TODO:了解如何回收这些本地内存)
- 顶点着色器(vertex shader):生成每个顶点的位置,针对每个顶点执行一次。一旦最终位置确定,OpenGL就会将这些顶点组装成点,直线和三角形。
- 片段着色器(fragment shader):为每个顶点组装成点,直线和三角形的片段生成最终的颜色,针对每个片段都会执行一次。 一旦最后的颜色生成了,OpenGL会将它们显示到一块称为frame buffer的内存块中,Android进而将其显示在屏幕上。
第三章
使用着色器
- 创建着色器对象
glCreateShader()将创建一个新的着色器对象。并返回一个整形值作为OpenGL对象的引用。当需要使用该对象时,只需要把这个整型值传递给OpenGL即可获得该对象。
- 上传着色器代码
glShaderSource()将告诉OpenGL将创建的着色器对象和传入的shader代码关联起来。
- 编译着色器代码
glCompileShader()将告诉OpenGL编译上传的着色器代码。
- 查询编译状态
int[] compileStatus = new int[1];
glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatus, 0);
复制代码
- 获取编译状态的Log
glGetShaderInfoLog()。
- 编译失败则删除着色器对象
if (compileStatus[0] == 0) {
glDeleteShader(shaderObjectId);
return 0;
}
复制代码
- 拼接着色器 OpenGL就是将顶点着色器和片段着色器拼接起来变成单个对象的程序。
int glProgramObjectId = glCreateProgram();
if (glProgramObjectId == 0) {
return 0;
}
glAttachShader(glProgramObjectId, vertexShaderId);
glAttachShader(glProgramObjectId, fragmentShaderId);
复制代码
- 链接着色器
glLinkProgram(glProgramObjectId);
int[] linkStatus = new int[1];
glGetProgramiv(glProgramObjectId, GL_LINK_STATUS, linkStatus, 0);
Log.d(TAG, "linkProgram: " + glGetProgramInfoLog(glProgramObjectId));
复制代码
- 编译失败则删除链接对象
if (linkStatus[0] == 0) {
glDeleteProgram(glProgramObjectId);
return 0;
}
复制代码
- 验证链接程序对象
public static boolean validateProgram(int programObjectId) {
glValidateProgram(programObjectId);
int[] validateStatus = new int[1];
glGetProgramiv(programObjectId, GL_VALIDATE_STATUS, validateStatus, 0);
Log.d(TAG, "validateProgram: " + glGetProgramInfoLog(programObjectId));
return validateStatus[0] != 0;
}
复制代码
-
使用链接程序对象
glUseProgram(mProgram);
-
定位uniform变量的位置
当OpenGL将着色器链接成一个程序的时候,实际上用了不同的位置编号把着色器中的uniform变量都关联起来,我们需要用这些位置编号给着色器发送信息。我们需要在链接成功之后查找uniform变量的位置。即使uniform变量变量同名,但是在不同的链接对象中也不同。
private static String U_COLOR = "u_Color";
private int uColorLocation;
uColorLocation = glGetUniformLocation(mProgram, U_COLOR);
复制代码
上面程序将着色器中的u_Color变量的位置信息设置给了uColorLocation变量。
- 定位attribute变量位置
与使用位uniform变量一样,要操作attribute变量之前需要获得它在链接程序中的位置。
private static String A_POSITION = "a_Position";
private int aPositionLocation;
aPositionLocation = glGetAttribLocation(mProgram, A_POSITION);
复制代码
上面程序将着色器中的a_Position变量的位置信息设置给了aPositionLocation变量。
- 关联变量与顶点数据
在找到对应变量的位置之后就需要给变量设置数据源。
mVertexData.position(0);//从开辟的内存的首位读取
//关联a_Position变量的数据源为mVertexData
glVertexAttribPointer(aPositionLocation, POSITION_COMPOMENT_COUNT, GL_FLOAT, false, 0 ,mVertexData);
复制代码
- 使变量的赋值生效
glEnableVertexAttribArray(aPositionLocation);
绘制着色器
//给uColorLocation对应的变量设置颜色
glUniform4f(uColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
//根据给定的形状和指定的绘制位置进行绘制
glDrawArrays(GL_TRIANGLES, 0, 6);
复制代码
坐标的映射
OpenGL会将坐标映射到[-1,1]之间:
第四章
第五章
正交投影能够使物体不管在远处或者近处都看起来相同。可以用于将虚拟坐标变换回归一化设备坐标,实际上定义了三维坐标中的一部分,这个区域内的内容会显示在屏幕上,区域外的内容则不会显示。
平移矩阵
orthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)
第六章
从着色器到屏幕的坐标变换
剪裁空间
透视除法
视口转换
透视投影
视锥体
对宽高比和视野进行调整
通用的投影矩阵
实用模型矩阵移动物体
旋转操作
旋转方向
右手握拳伸出大拇指沿着正轴方向,四指的方向就是正角度。
旋转矩阵
- 绕X旋转的矩阵
- 绕Y旋转的矩阵
- 绕Z旋转的矩阵
第七章
纹理
加载纹理
- 创建纹理对象
int[] textureObjectIds = new int[1];
glGenTextures(1, textureObjectIds, 0);//创建一个纹理对象,并将生成对象的Id保存在textureObjectIds
if (textureObjectIds[0] == 0) {
return 0;
}
复制代码
- 加载位图数据并绑定纹理
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;//需要原始的图像信息,不要压缩
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);//解码
if (bitmap == null) {
glDeleteTextures(1, textureObjectIds, 0);//解码失败,删除纹理对象
return 0;
}
glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);//将生成的纹理对象作为二维纹理处理
复制代码
- 过滤纹理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
复制代码
texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);//读入bitmap位图数据并复制绑定到当前纹理对象
bitmap.recycle();
glGenerateMipmap(GL_TEXTURE_2D);//生成MIP贴图
glBindTexture(GL_TEXTURE_2D, 0);//解绑纹理
复制代码
第八章
把一个物体放到屏幕上的三种矩阵
第九章
第十二章
创建顶点缓冲区对象,然后通过glBufferData()方法将数据传送到缓冲区对象。
public static native void glBufferData(
int target,
int size,
java.nio.Buffer data,
int usage
);
复制代码