学习资料
OpenGL中的坐标变换、矩阵变换
OpenGL跟DX左右手法则相反。 DX为左手坐标系,矩阵乘法使用的是左乘;OpenGL为右手坐标系,矩阵乘法使用的是右乘。
如果强行使用OpenGL做矩阵左乘运算,因为GLSL运算符重载的存在,OGL中的向量右乘矩阵;如果是用向量左乘矩阵,那么向量会变为行式向量,矩阵不变,所以进行运算需要谨慎,最好查询CG或HLSL的说明文档。
OpenGL性能优化
消除条件逻辑: 有时候条件逻辑是必须得,但尽量最小化它。在着色器中使用像 step() 函数这样的变通方法可以帮助你避免一些昂贵的条件逻辑。
减少依赖纹理的读取: 在片段着色器中取样时,如果纹理坐标不是直接以 varying 的方式传递进来,而是在片段着色器中进行计算时,就会发生依赖纹理的读取。依赖纹理的读取不能使用普通的纹理读取的缓存优化,会导致读取更慢。例如,如果你想从附近的像素取样,而不是计算和片段着色器中相邻像素的偏差,最好在顶点着色器中进行计算,然后把结果以 varying 的方式传入片段着色器。在 Brad Larson的文章中关于索贝尔边缘检测的部分有一个这方面的例子。
让你的计算尽量简单: 如果你在避免一个昂贵的操作情况下可以获得一个近似的足够精度的值,你应该这样做。昂贵的计算包括调用三角函数 (像
sin()
,cos()
, 和tan()
)。如果可以的话,把工作转移到顶点着色器: 之前讲的关于依赖纹理的读取就是把纹理坐标计算转移到顶点着色器的很有意义的一种情况。如果一个计算在图片上会有相同的结果,或者线性的变化,看看能不能把计算移到顶点着色器进行。顶点着色器对每个顶点运行一次,片段着色器在每个像素上运行一次,所以在前者上的计算会比后者少很多。
在移动设备上使用合适的精度 在特定的移动设备上,在向量上使用低精度的值会变得更快。在这些设备上,两个 lowp vec4 相加的操作可以在一个时钟周期内完成,而两个 highp vec4 相加则需要四个时钟周期。但是在桌面 GPU 和最近的移动 GPU 上,这变得不再那么重要,因为它们对低精度值的优化不同。
Mipmap
想象一下,假设我们有一个包含着上千物体的大房间,每个物体上都有纹理。有些物体会很远,但其纹理会拥有与近处物体同样高的分辨率。由于远处的物体可能只产生很少的片段,OpenGL从高分辨率纹理中为这些片段获取正确的颜色值就很困难,因为它需要对一个跨过纹理很大部分的片段只拾取一个纹理颜色。在小物体上这会产生不真实的感觉,更不用说对它们使用高分辨率纹理浪费内存的问题了。
OpenGL使用一种叫做多级渐远纹理
(Mipmap)的概念来解决这个问题,它简单来说就是一系列的纹理图像,后一个纹理图像是前一个的二分之一。多级渐远纹理背后的理念很简单:距观察者的距离超过一定的阈值,OpenGL会使用不同的多级渐远纹理,即最适合物体的距离的那个。由于距离远,解析度不高也不会被用户注意到。同时,多级渐远纹理另一加分之处是它的性能非常好。让我们看一下多级渐远纹理是什么样子的:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
一个常见的错误是,将放大过滤的选项设置为多级渐远纹理过滤选项之一。这样没有任何效果,因为多级渐远纹理主要是使用在纹理被缩小(GL_TEXTURE_MIN_FILTER
)的情况下的:纹理放大不会使用多级渐远纹理,为放大过滤设置多级渐远纹理的选项会产生一个GL_INVALID_ENUM错误代码。
OpenGL ES 共享上下文实现多线程渲染
存在多个OpenGL上下文时,纹理、shader、Buffer(VBO)等资源(包含数据,存储在可共享访问的内存区域内)是可以设置为OpenGL线程间共享,但Frame Buffer Object(FBO)、Vertex Array Object(VAO)等container objects(container objects 主要是用于存放regular objects,以及用于组织regular objects的额外信息)不可共享
多重采样抗锯齿(MSAA:MultiSampling Anti-Aliasing)
Gama校正
Gamma也叫灰度系数,每种显示设备都有自己的Gamma值,都不相同,有一个公式:设备输出亮度 = 电压的Gamma次幂,任何设备Gamma基本上都不会等于1,等于1是一种理想的线性状态,这种理想状态是:如果电压和亮度都是在0到1的区间,那么多少电压就等于多少亮度。对于CRT,Gamma通常为2.2,因而,输出亮度 = 输入电压的2.2次幂,你可以从本节第二张图中看到Gamma2.2实际显示出来的总会比预期暗,相反Gamma0.45就会比理想预期亮,如果你讲Gamma0.45叠加到Gamma2.2的显示设备上,便会对偏暗的显示效果做到校正,这个简单的思路就是本节的核心
Shader调试:
- 查看gpu的情况:
可以使用Xcode自带的Instruments
(metal system trace)
GPU分析工具RenderDoc使用
Shader编辑
KodeLife
实时调试渲染shader工具glslViewer
非常方便的 VSCODE 的 SHADER 插件 —— SHADER TOY
thebookofshaders编辑器逆向Shader
iOS逆向抖音学习滤镜
逆向工具MonkeyDev,
然后是分析工具Hopper,
log工具NSLogger
Shader
- gl-transition
转场动画
glFlush和glFinish区别
glFlush:将GL命令队列中的命令发送给显卡并清空命令队列,发送完立即返回;一般用在glDrawArrays之后,确保texture已经渲染到FBO中。
glFinish:将GL命令队列中的命令发送给显卡并清空命令队列,显卡完成这些命令(也就是画完了)后返回。