GAMES101笔记(一)

预备知识:线性代数、高等数学

 

目录

一、变换

1.矩阵变换

 2.视图变换

二、光栅化

1 屏幕像素的表示

2.光栅化算法

DDA数值微分算法

中点Bresenham算法

 三角形光栅化算法

3.抗锯齿

4.Z-Buffer算法

 三、着色

1.漫反射

2.高光

 3.着色方法

图形渲染管线


一、变换

1.矩阵变换

2D变换

缩放

拉伸

旋转

 变换都可写成矩阵形式

 

 对于2D有

2D_point=(x,y,1)^T

2D_vector=(x,y,0)^T

 对于3D有

3D_point=(x,y,z,1)^T

3D_vector=(x,y,z,0)^T

 3D齐次坐标表示

 2.视图变换

 将虚拟世界中以(x,y,z)为坐标的物体变换到 以一个个像素位置(x,y) 来表示的屏幕坐标系之中(2维)

模型变换:旋转,平移,缩放

摄像机变换:

相机或眼睛位置 (eye postion) e
观察方向 (gaze postion) g
视点正上方向 (view-up vector ) t

投影变换

正交投影:坐标的相对位置都不会改变,全部转换到一个\left [ -1,1 \right ]^{3}的空间之中


透视投影:透视投影就是最类似人眼所看东西的方式,遵循近大远小


 

 

 先压缩后正交投影,变换矩阵为:

最后将将这个被压缩过的空间,重新正交投影成标准小立方体,故定义透视投影变换:

 

补充:视图变换
模型变换(modeling tranformation):将一个物体自身进行变换(缩放、旋转、位移)
视角变换(view tranformation):根据眼睛来判断物体的相对位置
投影变换(projection tranformation):将三维空间内的物体投影至标准二维平面([-1,1]^2)之上
视口变换(viewport transformation):将处于标准平面映射到屏幕分辨率范围之内,即[-1,1]^2→\rightarrow→[0,width]*[0,height], 其中width和height指屏幕分辨率大小

 

 旋转变换:

 

视口变换:

 

games101 作业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.
    Eigen::Matrix4f tran;
    float angle = rotation_angle / 180.0 * MY_PI;
    tran << cos(angle), -1 * sin(angle), 0, 0,
        sin(angle), cos(angle), 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1;
    model = tran * model;

    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();
    Eigen::Matrix4f per2orth;
    per2orth << zNear, 0, 0, 0,
        0, zNear, 0, 0,
        0, 0, zNear + zFar, -zNear * zFar,
        0, 0, 1, 0;
    float angle = eye_fov * MY_PI / 180.0;
    float t = zNear * tan(angle / 2.0);
    float b = -t;
    float r = t * aspect_ratio;
    float l = -r;

    Eigen::Matrix4f orth;
    orth << 2.0 / (r - l), 0, 0, 0,
        0, 2.0 / (t - b), 0, 0,
        0, 0, 2 / (zNear - zFar), 0,
        0, 0, 0, 1;
    Eigen::Matrix4f trans;
    trans << 1, 0, 0, -(r + l) / 2.0,
        0, 1, 0, -(t + b) / 2.0,
        0, 0, 1, -(zNear + zFar) / 2.0,
        0, 0, 0, 1;
    projection = projection * orth * trans * per2orth;

    // TODO: Implement this function
    // Create the projection matrix for the given parameters.
    // Then return it.


    return projection;
}

二、光栅化

光栅化的目的就是将想要展现的物体给真正现实到屏幕上的过程

1 屏幕像素的表示

 屏幕中的每一个像素点我们都用整数坐标进行表示,最大最小值与分辨率相对应,考虑到每个像素都有一定的面积,我们定义(x+0.5,y+0.5)为该(x,y)像素的中心,如图中黑圈所示。

像素:

1)是一个一个的小的方块.

2)每个方块内的颜色是完全一致的,像素就是最小的单位了,像素内部不会再发生变化。

3)我们用256个等级0-255来表示灰度(如等级0表示是黑的,等级255表示是白的),一个像素内的颜色可以用
rgb(red,green,blue)三个值来定义,用红绿蓝的各种组合来表示每一种红色蓝色绿色的密度,例如红色是(255,0,0),白色是(255,255,255)。

4)一个像素内颜色不会发生任何差异。

屏幕空间就是以屏幕左下角为原点建立一个二维坐标系

1)用(x,y)表示像素的位置。(蓝色像素表示为(2,1)坐标来表示)

2)如果一个屏幕分辨率为width * height,那么我们定义像素下标从(0,0)到(width - 1,height - 1),
且(x,y)像素的中心在(x + 0.5, y + 0.5),如蓝色像素的中心为(2.5,1.5)。

3)屏幕范围从(0,0)到(width,height)


现在我们要将一个中心在坐标原点,棱长为2的立方体显示在长为height、宽为width的屏幕中

 具体操作要进行一次视口变换,准确地说是通过缩放平移变换,

2.光栅化算法

光栅化就是考虑如何将图像呈现在光栅显示器中.般将图像拆分成许多不同的三角形🔺进行显示。

之所以选择三角形是因为

1)三角形是最最基础的多边形。

1)三角形的三个点连接在一起,其三点一定在一个平面上。

2)三角形的内外部定义的很清楚,可以通过向量的叉积判断点是否在三角形内部。

3)三角形顶点插值的一种定义良好的方法。(用来之后求重心坐标的方法)

2)任何多边形均可以拆解成多个三角形。

DDA数值微分算法

任意两点时都可以用y = k x + b 来表示,其中k代表斜率,如果∣ k ∣ < 1 那么它的主要行进方向就是x轴,即x轴的变化要比y轴快,相反如果如果∣ k ∣ > 1那么它的主要行进方向就是y轴,即y轴的变化要比x轴快。


中点Bresenham算法

定义f ( x , y ) = y − k x − b 

此时我们取这两个橙色方格的中点,如图中圆圈符号所对应的那个点,倘若这个点在直线方程的下面,那么很明显我们应该选择右上的方格。

 三角形光栅化算法

 

 对屏幕中的每一个像素进行采样,如果这个像素点在三角形之中那么这个像素点就应该被采用

判断点在三角形内

利用叉乘判别:如图所示,我们事先知道想要光栅化的三角形的三个顶点P0,P1,P2,以及检测点Q。只要分别计算如果三者同号则代表点P在三条线段的同一边,那么必然处于三角形内部,如果不同号则代表该点一定在三角形外部。

static bool insideTriangle(int x, int y, const Vector3f* _v)
{   
    //.head(2)指这个点的前两个数值,即x,y
    Eigen::Vector2f q;
    q << x, y;
    Eigen::Vector2f a, b, c,v0_q,v1_q,v2_q;
    a = _v[1].head(2) - _v[0].head(2);
    b = _v[2].head(2) - _v[1].head(2);
    c = _v[0].head(2) - _v[2].head(2);

    v0_q = q- _v[0].head(2);
    v1_q = q- _v[1].head(2);
    v2_q = q - _v[2].head(2);

    return  a[0] * v0_q[1] - a[1] * v0_q[0] > 0 && b[0] * v1_q[1] - b[1] * v1_q[0] > 0 && c[0] * v2_q[1] - c[1] * v2_q[0]>0;

    // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
}

3.抗锯齿

我们在采样的时候的频率过低无法跟上图像的频率,导致最后结果的失真。

从简单的角度去解释这种问题出现的原因就是,我们用有限离散的像素点去逼近连续的三角形,那么自然会出现这种锯齿走样的现象,因为这种近似是不准确的。

 超采样反走样 SSAA

把原来的每个像素点进行细分,采样点越多抗锯齿效果越好,但计算负担也会随之增加

 多采样反走样 MSAA

MSAA其实是对SSAA的一个改进

 我们依然同样会分采样点,但是只会去计算究竟有几个采样点会被三角形cover,计算颜色的时候只会利用像素中心坐标计算一次颜色(即所有的信息都会被插值到像素中心然后取计算颜色)

4.Z-Buffer算法

判断物体先后关系:选离摄像头最近的像素点显示

1. Z-Buffer算法需要为每个像素点维持一个深度数组记为zbuffer,其每个位置初始值置为无穷大(即离摄像机无穷远)。
2. 随后我们遍历每个三角形面上的每一个像素点[x,y],如果该像素点的深度值z,小于zbuffer[x,y]中的值,则更新zbuffer[x,y]值为该点深度值z,并同时更新该像素点[x,y]的颜色为该三角形面上的该点的颜色。

 

 三、着色

 物体能被我们观察,是因为人眼接收到了从物体来的光

1. 镜面反射
2. 漫反射
3. 环境光

1.漫反射

漫反射便是光从一定角度入射之后从入射点向四面八方反射,且每个不同方向反射的光的强度相等

只有当入射光线与平面垂直的时候才能完整的接受所有光的能量,而入射角度越倾斜损失的能量越大,具体来说,我们应该将光强乘上一个cos\theta=l*n,其中l是入射光方向,n为平面法线方向。
除了入射角度之外,光源与照射点的距离也应该考虑,直观来说,离得越远当然强度也就越弱

 

图中中心为一个点光源,光线均匀的向周围发射,可以想象光源发射出来的能量其实是一定的,那么在任意两个圈上接受到的能量之和一定相等。而离圆心越远,圆的面积越大,单位面积所接受能量也就越弱

模拟漫反射

 

其中kd为漫反射系数,i入射光强,n.l分别如图中所示为法线向量和入射方向,max是为了剔除夹角大于90°的光。
 

2.高光

 只有当观察方向集中在反射方向周围很近的时候才能看见反射光,因此在镜面反射中会考虑 R 与 v的夹角α

 其中ks为镜面反射系数,I为入射光强,r为光源到入射点距离,注意这里在max剔除大于90°的光之后,我们还乘了一个指数p,添加该项的原因很直接,因为离反射光越远就越不应该看见反射光,需要一个指数p加速衰减

环境光

环境光+漫反射+高光:

 3.着色方法

 Flat Shading:以每一个面作为一个着色单位

 Gouraud Shading:对每个三角形的顶点进行一次着色,将所有共享这个点的面的法线向量加起来求均值,最后再标准化就得到了该顶点的法线向量了,对于三角形内部的每一个点有:

 其中c 0 , c 1 , c 2为三角形三个顶点的颜色α,β,γ为三角形面内一点的重心坐标,c 为该点的插值之后得到的颜色。
Phong Shading:对于三角形内部的每一个点着色

补:重心坐标

图形渲染管线

顶点处理:对所有的顶点数据进行Model,View,和Projection的变换,最终得到投影到二维平面的坐标信息

三角形处理:将所有的顶点按照原几何信息,变成三角面,每个面由3个顶点组成

光栅化

片元处理

作业3

phong_fragment_shader:最基础的着色模型为Blinn-Phong反射模型。

高光+漫反射+间接光或环境光

  • 我们现在考虑光照是对任何一个点而言,假设这个点叫做shading point,那么这个点的着色结果是什么?我们定义在一个极小的范围内,它是一个平面,即与它所在的曲面相切的平面
  • 既然是平面,那么就有法线n垂直于平面
  • 同样我们还可以定义一个观测方向,我们规定从shading point到相机的方向为观测方向v
  • 同样道理,从shading point到光源的方向称为光照方向l
  • 注意,因为我们只关心这些向量的方向,所以它们都是单位向量,长度为1

 

 texture_fragment:比phong_fragment_shader多贴图

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值