有关图形学的一点点笔记。不过因为为一般会用ipad记,所以这里的就当复习用吧....
不会太详细,毕竟是笔记。
数学
齐次坐标
https://blog.csdn.net/zhuiqiuzhuoyue583/article/details/95228010
变换
平移
缩放
旋转
R的角标代表旋转轴绕任意轴(Rodrigues' rotation formula)
推导过程见https://www.qiujiawei.com/linear-algebra-14/法向量变换
视图变换
模型变换 Model
上面提到的几种变换的组合,往世界里摆物体。
local space -> world space
视图变换 View
word space -> view space
这里用的都是右手系,但opengl是左手系。可能实际会有正负号的区别。
描述相机:位置
有
由于相机和物体的相对位置不变,画面不变,所以实际大概是直接规定相机在这然后移所有物体...
移动包括一个平移一个旋转。有
其中,
对于
由于这玩意的列向量都是单位向量,还是正交的,所以是正交矩阵,转置一下就是
投影变换 Projection
view space -> clip space
把所有可见坐标变换到(-1.0, 1.0)的范围内,然后裁剪掉这部分之外的内容。
正交投影 Orthographic projection
相机离的无限远,可见范围就变成一个立方体了。
规定可见的立方体的坐标l(left), r(right), b(bottom), t(top), f(far), n(near)。根据摄像机up=y, lookat=-z来定义。
然后把这个立方体变成(-1, 1)的标准立方体。
显然先移动再缩放一下就好了。有:
透视投影 Perspective projection
摄像机是某个点,从这里投出一个四棱锥。规定四棱锥平行于底面的两个平面为zNear和zFar,渲染这个Frustum里的东西。
把左边的frustum挤压成立方体,然后使用透视投影的方法。
图是拿notability手画的所以非常丑陋
由图,根据相似三角形,有
所以有:
那一行?要用两个特殊值:zNear平面点不动,zFar平面点的z不变来解。往里一代:
最后
还有确定坐标的问题...。zFar(f)和zNear(n)是已知的,另外两个参数是摄像机的fov(一般是fovY)和宽高比aspect。
那么,
由于摄像机是固定的,又有一些奇奇怪怪的对称性,所以可以化简下:
线性插值
双线性插值:
为插出5,先插m和n,再用m和n插出5。多维的同理。
重心坐标
对于三角形ABC内的任意点,都可以用
把点和ABC分别连起来,围成三个小三角形。A正对的三角形面积记为
重心坐标插值
三角形内一点
TBN坐标系
一个local的坐标系。三个轴是Tangent, Bitangent和Normal。前两者对应贴图的uv,normal当然是法线。
可以用三角形的两条边的向量算出TB。N则是三角形本身的法向量。
公式和推导过程见https://learnopengl-cn.github.io/05%20Advanced%20Lighting/04%20Normal%20Mapping/。
Perlin noise
生成噪声的东西,公式看不懂...总之有。可以和纹理组合起来用。
光照
一些物理定义
https://zhuanlan.zhihu.com/p/389616851
漫反射 Diffuse
用于Lambert物体(粗糙的那种)。
Lambert物体符合Lambert cosine law:
符合各项同性,光从各个方向来没有区别,只和法线夹角有关系。
虎书里用的代表RGB颜色,规定
公式里的max可以换成绝对值。这么搞叫two-sided lighting,相当于镜像再放置一个光源。
环境光 Ambient
如果要保证
镜面反射或者叫高光 Specular/Phong shading
(图片的字母不太一样,e是V,少了一个I的反射R)
Blinn Phong的话,是
n越大反射光越集中。实际上是让
Blinn Phong的效果更柔和一点。
Shading
Vertex-Based Diffuse Shading
算顶点的颜色,然后重心坐标插值出三角形的颜色。
Phong Shading
重心坐标插值出三角形中所有点的法向(本质是对原来光滑曲面的近似),然后用这个法向算颜色。
Texture
提供一个Texture function(可以是函数或者查表,就是图片),和一个平面上点对texture function的对应关系,就可以贴纹理了(
2D纹理
提供一个2D坐标
需要把物体的xyz坐标map到uv上。好像不用对应的很紧密,只要像那个形状就可以往上贴(不过肯定会失真)。
平面投影
在平坦的表面上很好用,但和投影方向(一般是法线)垂直的地方就会出现那个面全部被map到texture的一个点上的情况...
球坐标
把xyz转到球坐标上,得到
地球仪用的这种。
柱坐标
先转到柱坐标再归一化。和球差不多。
Cubemaps
球坐标在两极会变形,可以用一个立方体代替(不过有在边上不连续的缺点)。
具体是把球上的点投到包着球的正方体上。
纹理坐标插值
三角形的每一个顶点存一个(u, v)。内部的某个点的uv通过插值得到。
这里的插值不能在做齐次除法(v/w)后的screen space算(重心坐标会变),需要先在screen space算出重心坐标,然后通过:
具体为什么....我猜是因为齐次除法把z搞没了少了一个维度(w在persp后其实是z)。嗯推公式也能推出来,总之不管了。
这玩意叫透视校正插值。
取纹理值的方法
插值出的uv不是整数。如果texture function是离散的,得有一个方法取值: - nearest neighbor:取最靠近的一个 - bilinear:拿周围四个双线性插值 - hermite:把bilinear用的
MipMap
解决texture太大的问题(屏幕上的一个像素对应texture的多个像素)。
本质是范围查询。对屏幕上的某个点o,找邻近两点(上和右)a, b。取mipmap level
D不是整数,所以用trilinear interpolation。在floor(D)和ceil(D)双线性插,结果再插一次。
会导致Overblur的问题。原因是每次缩放一半相当于只有宽高比为1的情况。用各项异性过滤(Anisotropic Filtering)可以解决宽高比不为1,但斜着就不行了。
纹理的应用
Environment map
天空盒,用一个球或者cubemap记录无限远处的环境光照,这样可以只通过方向查询env map上的点。
凹凸贴图 Bump map
用贴图记录表面上的相对高度,从而改变法线。
二维:
求出的法线在TBN坐标系下。
法线贴图 Normal map
更好用的Bump map(以至于前者基本没人用)。
贴图记录法线而不是高度差,直接替换即可。也在TBN下。
位移贴图 Displacement map
真正的移动顶点的位置。需要和三角形的顶点一一对应(所以顶点得足够多)。
未完待续