Android OpenGL学习笔记
OpenGL ES 2.0 for Android 学习笔记。
不过发现OpenGL不靠笔记,全靠内力,所以后期复杂的内容就记不过来了。
Getting Started
现代GPU更新了算法,每帧清屏重新绘制比在上一帧基础上修改要更效率、更可靠。
SurfaceView
是个Surface
,屏幕上单独挖了个洞来高效率显示;TextureView
是个View
,继承了SurfaceView
的功能且可以当成View
来操作,代价是性能牺牲。
GLSurfaceView.Renderer
中的代码会在子线程执行。主线程到子线程:GLSurfaceView.queueEvent
。
1 | glSurfaceView.setEGLContextClientVersion(2) |
1 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { |
Defining Vertices and Shaders
Vertex, Vertices: 点。包含位置、颜色等信息。
用多个三角形去近似任意图形。描述时使用逆时针(倒带)方向可以优化性能。
使用ByteBuffer.allocateDirect
定义不被垃圾回收影响的Native Memory。
1 | private val vertexData: FloatBuffer = ByteBuffer |
Shader: 渲染管线单元。
Shader使用GLSL(OpenGL’s shading language)
Vertex Shader
每个点运行一次,得到最后的点。OpenGL生成点、线和三角形。
坐标为(-1, 1), (-1, 1)。
1 | // Simple Vertex Shader |
vec4
: x, y, z, w 坐标
attribute
: 添加颜色信息,自带默认值(0, 0, 0, 1)。
默认有着最高精度highp
(见Fragment Shader精度介绍)。
Fragment Shader
计算得到上述生成的点、线和三角形中每个像素点的颜色。Fragment相当于Pixel。
1 | // Simple Fragment Shader |
precision mediump float;
: 定义所有浮点数的精度。在lowp
, mediump
, highp
中选择。
无默认精度(未定义的行为?),必须手动定义。
2023年1月13日更新:如果FragmentShader不定义精度,有的手机上会无法显示。
最高精度旨在某些实现中未支持。
int
的默认精度是mediump
。
uniform
: 保持不变直至手动修改。无默认值,需要手动指定。
vec4
: 这里是颜色RGBA
。
Compiling Shaders and Drawing to the Screen
在
onSurfaceCreated
中获得两种Shader的String。编译两种Shader,得到对应的shaderObjectId(int)。
- OpenGL内部并不抛异常,只是返回特定的值或通过
glGetError
读取。
- OpenGL内部并不抛异常,只是返回特定的值或通过
把Shaders合成为Program,得到programObjectId。
检测Program状态。
使用Program。
获取变量Attribute和Uniform的Location值。
设置变量值
方法有很多,一些是:
glVertexAttribPointer
+glEnableVertexAttribArray
设置Attribute值。glUniform4f
设置Uniform值。
绘制
glDrawArrays
Adding Color and Shade
GL_TRIANGLE_FAN
: 一次画四个三角形。
1 | // New Vertex Shader |
varying
: 在一条线或三角形中,渐变颜色后,交给Fragment Shader。
1 | // New Fragment Shader |
这样就不用手动设置Fragment Shader颜色了。
Adjusting to the Screen’s Aspect Ratio
线性代数、矩阵相乘!
1 | 1 0 0 translateX x x + translateX |
1 | // New Vertex Shader |
使用Matrix.orthoM
根据屏幕比例,缩放长边,使内容显示在中心的正方形中。
Entering the Third Dimension
坐标处理流程:
Clip Space
在
Vertex Shader
中的gl_Position
首先被裁剪到[-w, w]的范围中。此时的坐标也被称为Homogenous Coordinates。
Perspective Division
x, y, z = x / w, y / w, z / w
w代表距离。距离越大,结果越小,结果越靠近原点,越像消失点。
此阶段结束后,所有坐标都在[-1, 1]。多个Homogenous Coordinates会对应一个Normalized device coordinates。
w不为1时,(x, y, z)并不是实际坐标,(x / w, y / w, z / w)才是。
Viewport Transformation
和显示区域长宽相乘得到最终坐标Window coordinates。
给坐标增加各种矩阵,实现3D模拟。
Adding Detail with Textures
之后书中的内容就复杂起来,记笔记也变得难了起来。