文章目录
- 第一章
- 第二章 线性代数
-
- 向量
-
- 单位向量:
- 向量相加:
- 笛卡尔坐标系:
- 向 量乘法:
-
- 点乘
- 叉乘
- 标准正交基orthonormal
- 矩阵
-
- 矩阵乘法
- 性质:
- 矩阵转移:
- 单位矩阵和逆矩阵
- 用于向量
- 第三章 Transform
-
- 缩放
- 切变shear
- 旋转矩阵
- 线性变换
- 平移
-
- 齐次坐标
- 仿射变换Affine Transformation
- 第四章 Transform Cont
-
- 3D旋转
- viewing transformation观测变换
- projection transformation
-
- orthographic projection
- perspective projection
- viewport transformation
-
- 屏幕Screen
- 补充H1
-
- 第五章Rasterization(Triangle)光栅-三角形
-
- 三角形
- 光栅化
- 第六章Rasterization(Antialiasing,z-buffering)反向走样和深度缓冲
-
- 走样
- 滤波
- 反走样
- Multi Sample Antialiasing (MSAA)
- 其他
- Z-buffering
- 补充H2
- 第七章、九章Shading1
-
- Shading
- (Blinn-Phong Reflectance Model)冯氏光照模型
-
- Diffuse Lambertian Shading漫反射着色
- Specular Term (Blinn-Phong)
- Ambient Term
- Reflectance Model
- Shading Frequencies
-
- 逐面(Flat shading)
- 逐顶点(Gouraud shading)
- 逐像素(Phong shading)
- 计算法线
- Graphics(Real-time Rendering) Pipeline
- 纹理映射 Texture Mapping
-
- 三角形内值:重心坐标(Barycentric Coordinates)
- 纹理映射
- 纹理放大
- 纹理过滤
- MipMap
- 各向异性过滤 Anisotropic Filtering
- 纹理应用
-
- 环境贴图
- bump/normal Map 凹凸/法线贴图
- Displacement mapping位移贴图
- AO贴图
- 3D纹理
- Shadow Mapping
- 补充H3
- 十、十一、十二章Geometry几何
-
- 曲线
-
- Bezier Curves 贝塞尔曲线
- Spline 样条
- 曲面
-
- 贝塞尔曲面
- 几何操作
-
- 曲面细分
- 曲面简化
- 补充H4
- 十三、十四、十五、十六章 Ray Tracing 光追
-
- 光线投射
- Recursive(Whitted-Style) Ray Tracing
-
- Ray-Surface Intersection
- 补充H5
- Accelerating Ray-Surface Intersection
-
- AABB
- Uniform grids
- Spatial Partitions
- Object Partitions & Bounding Volume Hierarchy(BVH)
- 补充H6(SAH)
- Basic radiometry 辐射度量学
-
- Radiant Energy and Flux(Power)
- Radiant Intensity
- Irradiance
- Radiance
- Bidirectional Reflectance Distribution Function(BRDF)双向反射分布函数
- The Rendering Equation 渲染公式
- Monte Carlo Path Tracy 跟踪蒙特卡洛路径
-
- Monte Carlo Integration蒙特卡洛积分
- Path Tracing
- H7补充
- 第十七章 Materials and Appearances
-
- 反射
- 折射
- Fresnel Reflection / Term 菲涅尔项
- Microfacet Material 微表面材质
- Isotropic/Anisotropic Materials(BRDFs) 各向同性/各向异性材料
- BRDF的性质
- 第十八章 Advance Topics In Rendering
-
- Advanced Light Transport
-
- Bidirectional Path Tracing(BDPT)双向路径追踪
- Metropolis Light Transport(MLT)
- Photon Mapping 光子映射
- Vertex Connection and Merging (VCM)
- Instant Radiosity
- Advanced Appearance Modeling 表面模型
-
- Non-Surface Models
-
- Fog
- Hair
- Fur
- Granular Material 颗粒材质
- Surface Models
-
- Subsurface Scattering 次表面散射
- Cloth
- Detial
- Procedural Appearance 程序化生成表面
- 第十九章 Cameras,Lenses and Light Fields 相机,透镜和光场
-
- Camera
-
- FOV
- Exposure
- Lens
-
- Ray Tracing Ideal Thin Lenses
- Depth of Field景深
- Light Fields/Lumigraph
-
- Plenoptic Function
- Light Field Camera
- 第二十章 Color and Perception 颜色和感知
-
- Metamerism同色异谱
- Color Matching Function颜色匹配函数
- Color Space色彩空间
- 第二十章 Animation
-
- Keyframe Animation
- Physical Simulation
-
- Mass Spring System质点弹簧系统
- Particle Systems
- Forward Kinematics 正向运动学
- Inverse Kinematics 逆向运动学
- Rigging 绑定
- The Production Pipeline
- 第二十一章 Animation(cont)
-
- Single Particle Simulation
-
- Euler's Method
-
- Explicit Euler's Method 显式欧拉方法
- Midpoint Method
- img
- Adaptive Step Size 自适应步长
- Implicit methods 隐式欧拉方法
- Runge-Kutta Families
- Position-Based / Verlet Integration
- Rigid Body Simulation
- Fluid Simulation
- 结语
第一章
Rasterization 光栅化
将三维空间的几何形体显示在屏幕空间上
实时显示(高于30fps,低于则是离线)
课程主页:https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html
计算机图形学与混合现实在线平台GAMES: http://games-cn.org
http://games-cn.org/forums/topic/allhw/,作业链接地址
虎书https://pan.baidu.com/s/1WSwD7HJv1QBEXBCo2ZMENg 提取:n2rx
第二章 线性代数
向量
单位向量:
向量相加:
笛卡尔坐标系:
向 量乘法:
点乘
点乘dot ,向量点乘得到一个数,点乘可以得到两个向量之间的夹角
作用:1.找到两个向量之间的余弦夹角 2.一个向量投影到另一个向量上的长度
分解向量,可以用来计算这个b向量是靠近两边哪一个向量
3.判断两个向量的前后或者距离
a和b点乘是正数,方向比较一致,a和c点乘是负数,方向差不多相反,如果依据中线对称,则点乘为0,则以此来判断向量的前后关系。
还可以用来判断两个向量的距离
,重合为1,然后逐渐远离,由1到0,再远离直到完全相反,由0到-1。可以用于镜面反射,从出射光方向看过去会非常亮,入射光则不然,金属高光同理
叉乘
右手螺旋定则,叉乘方向为手指指向a旋转到b时大拇指的方向,不满足交换律
,如果从b旋转到a,则叉乘结果朝下
如果一个坐标系,那就称这个坐标系是右手系
,注意UE是左手系
一个向量叉乘他自己等于0的向量,注意叉乘一定得到的是向量
作用:1.判定左和右, 2.判定内与外
上图,得到的向量是正的,所以b在a的左侧,反之则在右侧
对于点P,AP在AB左侧,BP在BC左侧,CP在CA左侧,所以P点位于三边的同一侧,P点在三角形内,不全为同一侧则在三角形外
对于在边上concer case的情况,自己决定内外
标准正交基orthonormal
矩阵
m x n的矩阵是指 m行n列
矩阵乘法
两个矩阵如果想要相乘必须要满足:(m x p)(p x n) = (m x n)
矩阵a和b相乘时先得出矩阵c的大小m x n,第i 行j列元素为a的第i行点乘b的第j列
性质:
1.不满足交换律
,AB和BA在一般情况下不相等、
2.具有分配律和结合律,
3.将一个向量看作是m x 1的列矩阵
矩阵乘法作用例子:2D相对y轴镜面反射
矩阵的转置:
转置公式:
单位矩阵和逆矩阵
用于向量
第三章 Transform
缩放
切变shear
旋转矩阵
在数学上,如果一个矩阵的逆等于它的转置,则将这个矩阵称为正交矩阵
所以
线性变换
上面三种变换均为线性变换,可以总结为
平移
齐次坐标
这里平移使用普通的线性变换已经不能满足,需要额外加上一个矩阵才能达到目的。就引入了齐次坐标以将平移写成一个矩阵乘以一个向量的形式。
2D 点 =
2D向量= 之所以2d向量的w分量是0,是因为向量代表方向,具有平移不变性
,当这个2d向量进行平移以后,与原来的向量并没有区别,这个0是为保护这个性质(向量平移或者加上一个向量它还是向量,加一个点w值为1就变成了点)。
仿射变换Affine Transformation
仿射变换=线性变换+平移
注意做变换一定是先做线性变换,再平移
使用齐次坐标就是:
仿射变换最后一行都是001
变换矩阵都是左乘
这里先旋转再平移
第四章 Transform Cont
3D旋转
对于旋转有:
称之为欧拉角
viewing transformation观测变换
变换顺序:简称MVP变换
- model transformation
- view(这里其实是camera) transformation
- projection transformation
针对一个相机,需要:1.位置 2.相机朝向 3.相机的向上方向
;去标定相机的状态
通常情况下,将相机置于标准位置,坐标0,0,0,朝向-z,向上方向为y,右手系
projection transformation
orthographic projection
将视锥体(立方体)先平移到0,0,0原点,再缩放成[-1,1]的标准立方体
注意这里摄像机看向的是-z轴,所以其实f(远平面)是小于n(近平面)的(所以OpenGL投影坐标是左手系)
这里缩放矩阵中2/r-l是因为要把边长缩放到-1到1,乘以这个系数因子以缩放到长度为2。
perspective projection
透视投影
考虑到透视投影的矩阵直接写出有难度,可将平截头体frustum的远端向内压缩,形成红色部分的立方体,之后再进行正交投影即可,注意压缩前后n不变,同时中心点蓝色点也是不变的。
将这个压缩操作的矩阵称为
来看这个平截头体的侧视图:
寻找n平面上的点与f平面上的点的对应关系,依据相似三角形得出:
viewport transformation
假定l=-r,b=-t
,红线夹角为fovY,宽高比aspect ratio = width/height
由上图,通过fovY和aspect即可得到相应的lrbt
屏幕Screen
什么是屏幕:
- 像素的数组
- 数组大小称为分辨率(1080p,p指的是逐行扫描)
- 是一种典型的光栅化显示
- 光栅化就是在屏幕上进行绘制的过程
补充H1
罗德里格旋转公式
贴一下H1的代码:
float get_degree(float angle)
{
return (angle / 180) * std::acos(-1);
}
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
// TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
float rotation_degree = get_degree(rotation_angle);
float aa = std::cos(rotation_degree);
float bb = std::sin(rotation_degree);
model << aa, -bb, 0, 0, bb, aa, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1;
return model;
}
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
float zNear, float zFar)
{
// Students will implement this function
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
float t = zNear * std::tan(get_degree(eye_fov / 2));
float r = t * aspect_ratio;
float b = -t;
float l = -r;
float halfz = (zNear + zFar) / 2;
Eigen::Matrix4f TO;
TO << 1, 0, 0, -(l + r),
0, 1, 0, -(t + b),
0, 0, 1, -halfz,
0, 0, 0, 1;
Eigen::Matrix4f SO;
SO << 2 / (r - l) ,0 ,0, 0,
0, 2 / (t - b), 0, 0,
0, 0, 2/(zNear - zFar),0,
0, 0, 0, 1;
Eigen::Matrix4f Persp;
Persp << zNear, 0, 0, 0,
0, -zNear, 0, 0, //这里为负是为解决左手系三角形显示是倒着的问题
0, 0, zNear + zFar, -zNear * zFar,
0, 0, 1, 0;
projection = SO * TO *Persp ;
// TODO: Implement this function
// Create the projection matrix for the given parameters.
// Then return it.
return projection;
}
Eigen::Matrix4f get_rotation(Vector3f axis, float angle)
{
float rotation_degree = get_degree(angle);
Eigen::Matrix4f rotation = Eigen::Matrix4f::Identity();
//std::cout<< rotation <<std::endl;
Eigen::Matrix4f times;
float x = axis[0];
float y = axis[1];
float z = axis[2];
times << 0, -z, y, 0,
z, 0, -x, 0,
-y, x, 0, 0,
0, 0, 0, 1;
Vector4f taxis = {
x, y, z, 1};
rotation = std::cos(rotation_degree) * rotation + (1 -std::cos(rotation_degree))*taxis*taxis.transpose()
+ std::sin(rotation_degree) * times;
return rotation;
}
第五章Rasterization(Triangle)光栅化-三角形
三角形
为什么是三角形:
- 最简单的多边形
- 可以将其他多边形拆解成三角形
性质:
- 一个三角形一定是一个平面
- 一个三角形可以利用叉乘很明确的定义内外
- 三角形可以依据三个顶点在三角形内部进行插值计算
光栅化
采样:采样就是将一个函数离散化的过程
通过将三角形作为限定条件,对像素中心进行采样,显示中心在三角形内的像素点,从而实现光栅化
(注意对中心点在三角形边上的情况,自定义处理即可)
注意这里是将屏幕上所有像素点都进行了采样,考虑到一个三角形只在一部分范围内存在,使用一个axis along bounding box (AABB)进行包围,并在其中进行采样,可以减少采样成本
第二种优化方法是考虑只处理从边界最左侧到最右侧内的像素点
第六章Rasterization(Antialiasing,z-buffering)反走样和深度缓冲
走样
在计算机图形学中的采样瑕疵sampling artifacts
- jaggies 锯齿-空间中的采样
- moire 摩尔纹-图片降采样
- wagon wheel effect-车轮效应-对时间的采样
本质是:相对来说信号变换过快(频率过高)而采样速度太慢
可以看见,随着信号频率的增加,两次采样之间的变化越多,已逐渐无法通过逆傅里叶变换用两次采样的数据恢复成原有的信号。如下图,恢复出来的信号(黑线)与实际的完全不同了。将黑色线与白色线看作两个函数,会发现采样得到的结果完全相同。
走样:相同的采样方法采样两种不同频率的函数得到完全相同的结果,这种情况就称为走样
如何反走样:在采样前进行一次模糊Blurring(Pre-Filtering滤波)
、
滤波
将左图做一个傅里叶变换就可以得到右图,图中红线方向频率由低变高,而白色部分代表信号(这个信号可以看成两个相邻像素点之间的差异,差异越明显,频率越高,反之,频率越低),可以看出来左图大部分是低频信号。
做一个高通滤波,去掉图中的低频信号,只留下高频信号(即相邻的像素变化差异较大,这种像素一般是边缘部分),做一个逆傅里叶变换,可以得到大概的轮廓图。
做一个低通滤波,去掉图中的高频信号,即去掉边缘细节,只保留低频信息,则整个图像变得模糊,因为失去了边缘和细节部分。
图像可以通过傅里叶变换进行时域到频域的转换,通过逆傅里叶变换进行频域到时域的转换。时域上的卷积等于频域上的乘积,可以看见上图,做一个3x3的卷积核卷积,最后结果类似于低通滤波,只留下了低频信号。
靠。。。这部分有点复杂。。。
采样可以理解为对原始频谱在频域上的重复
稀疏采样的情况下,两次频谱之间重复之间会有部分重合,从而导致走样。
简单理解下:
–对于一个给定的三角形,采样用的像素点越小,需要采样的像素就越多,采样密度就越大,越不容易走样,而采样的像素过大,采样密度就过小,导致了走样。
–所以对于同一张图片,在不同分辨率的屏幕上,高分辨率的屏幕采样密度更大,更不容易走样
反走样
两种减少走样的方法:
- 提高采样率:即增加频域上两个频谱之间的距离,这样在稀疏采样时频谱之间更不容易重叠。实际上就是提高画面分辨率,但开销很高
- 反走样:使用低通滤波去掉高频信号,相当于减少频域上频谱的宽度(见下图),这样在稀疏采样时也不容易重叠。所以要先滤波再采样,反之则不行
反走样的实际应用:使用一个1x1的卷积核对单个像素进行卷积(或者说滤波、平均)
(上图中,黑色部分为在三角形内部的部分,将这部分与这个像素剩下的部分进行平均)
Multi Sample Antialiasing (MSAA)
MSAA在一个像素点设置多个采样点,通过这多个采样点去近似计算一个像素内在三角形内部的比例。
上图是进行2x2MSAA的示意图,对每个在三角形内部和边缘的像素内进行2x2=4次采样,蓝框中的那个像素点,像素比例即为75%
所以MSAA并没有提高分辨率,实际上做的是采样前进行模糊的那一部分工作。
注意和SSAA区别,SSAA在每一个像素内部采样点维护了深度和色值,这个像素色值就是内部采样点的加权平均,等于是一个像素四次shading
而MSAA像素内部只维护深度值,并依据像素内采样点在三角形的比例对像素色值加权,只做一次shading
FXAA只是一个后处理技术,对原图绘制完成后,通过算法识别边缘,然后以像素级别进行混合;
https://blog.csdn.net/weixin_40273050/article/details/121886452
其他
Fast Approximate AA (FXAA)快速近似抗锯齿
与采样无关,在图像层面上进行的抗锯齿,是一种后处理
Temporal AA(TAA)
复用上一帧的信息
DLSS(Deep Learning Super Sampling)
Games101中提及的光栅化是三角形光栅化,直线光栅化没讲,DDA和中点Bresenham也不复杂,先挖个坑后续再看
Z-buffering
为每一个采样的像素点存储一个当前最小的(最近的)z值
需要额外的buffer去存储这个深度值
–frame buffer存储颜色值
–depth buffer存储深度值
(注意我们这里规定,z值永远为正,且z越小,离摄像机越近,越大就越远,且初始化时z值为无限大)
伪代码:针对每一个被光栅化的三角形的其内的一个采样点,记录最小的z值
所以z-buffer永远维护的当前最近的像素的深度信息。
z-buffer计算的时间复杂度:我们只需要遍历场景中的每一个三角形,对其中的采样像素点记录最小z值,所以对于n个三角形,复杂度为O(n)
通过GPU硬件进行计算
注意在使用MASS时,z-buffer就不单纯是针对像素进行,而是针对其中的每个采样点进行
带宽会急剧增加,这是个人觉得为啥延迟渲染不适用MSAA的原因
补充H2
H2 作业 光栅化
- 创建三角形的 2 维 bounding box。
- 遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中 心的屏幕空间坐标来检查中心点是否在三角形内。
- 如果在内部,则将其位置处的插值深度值 (interpolated depth value) 与深度 缓冲区 (depth buffer) 中的相应值进行比较。
- 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区 (depth buffer)。
static bool insideTriangle(float x, float y, const Vector3f* _v)
{
// TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
Vector3f P = {
x, y, 1};
Vector3f AB, BC, CA, AP, BP, CP;
AB = _v[1] - _v[0];
BC = _v[2] - _v[1];
CA = _v[0] - _v[2];
AP = P - _v[0];
BP = P - _v[1];
CP = P - _v[2];
auto r0 = AB.cross(AP);
auto r1 = BC.cross(BP);
auto r2 = CA.cross(AP);
return (r0[2] > 0 && r1[2] > 0 && r2[2] > 0) ||
(r0[2] < 0 && r1[2] < 0 && r2[2] < 0);
}
void rst::rasterizer::rasterize_triangle(const Triangle& t) { auto v = t.toVector4(); // TODO : Find out the bounding box of current triangle. Eigen::Vector4f v1[] = { Vector4f(t.v[0][0], t.v[0][1], t.v[0][2], 1.0), Vector4f(t.v[1][0], t.v[1][1], t.v[1][2], 1.0), Vector4f(t.v[2][0], t.v[2][1], t.v[2][2], 1.0) }; float tmaxX, tminX, tmaxY, tminY; tmaxX = tminX = v1[0][0]; tmaxY = tminY = v1[0][1]; for (int i = 1; i < 3; i++) { if (v1[i][0] > tmaxX) { tmaxX = v1[i][0]; } if (v1[i][0] < tminX) { tminX = v1[i][0]; } if (v1[i][1] > tmaxY) { tmaxY = v1[i][1]; } if (v1[i][1] < tminY) { tminY = v1[i][1]; } } int maxX = std::ceil(tmaxX); int maxY = std::ceil(tmaxY); int minX = std::floor(tminX); int minY = std::floor(tminY); Eigen::Vector3f v2[] = { { v1[0][0], v1[0][1], 1}, { v1[1][0], v1[1][1], 1}, { v1[2][0], v1[2][1], 1} }; for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { if (insideTriangle(x, y, v2)) { /* code */ auto[alpha, beta, gamma] = computeBarycentric2D(x 标签:
物体阻挡光线传感器7ty传感器5kn力值传感器n13cp光纤传感器fn7325力传感器fn3060力传感器