游戏图形学入门知识整理

分享和整理一些觉得不错的教程和理解

在此感谢各位老师!

教程:
线性代数基础:https://www.bilibili.com/video/BV1ib411t7YR?p=1
GAMES101-现代计算机图形学入门-闫令琪:https://www.bilibili.com/video/BV1X7411F744
GAMES202-高质量实时渲染-闫令琪:https://www.bilibili.com/video/BV1YK4y1T7yY
华中科技大学-计算机图形学-万琳:https://www.bilibili.com/video/BV1Zj411f7S3?p=13&spm_id_from=pageDriver
论坛:
计算机图形学与混合现实研讨会
博客:
冯乐乐(Shader入门精要)http://candycat1992.github.io/

GPU渲染管线的工作过程

image.png

几何阶段

空间变换:模型空间(左手)→世界空间(左手)→观察空间(右手)
image.png
投影准备:观察空间→观察空间(投影变换)→观察空间(裁剪空间)

经过以上变换,此时物体处在裁剪空间,
★下图需要注意,每个教材的解释略有不同,下图直接就齐次除法变成规范化的了
实际上这里只是为真正是投影(齐次除法)做准备,此时裁剪面依然是梯形四棱锥形态
目的:
1.为后面真正投影做准备,赋予W特殊意义。
2.对X,Y,Z缩放,W作为范围值,便于裁剪。
裁剪空间之前,W=0表示矢量方向,W=1表示点,投影变换之后,W的意义改变了,如下
投影变换对X,Y,Z分量进行缩放,W分量变成-z,如X,Y,Z在W范围内[-w,w],说明该顶点在裁剪空间内
Unity下,观察空间为右手坐标系,列矩阵右乘,投影变换后Z分量范围为[-w,w]
DirectX,投影变换后Z为[0,w]
进入裁剪空间后,右手坐标系,转为左手坐标系,离摄像机越远Z值越大


image.png
屏幕映射:规范化的观察空间(裁剪)→屏幕空间(真正的投影)

齐次除法=透视除法=归一化的设备坐标NDC(OpenGL)=W分量除以X,Y,Z分量
裁剪空间→NDC(经过齐次除法后,变换到一个立方体内)
立方体X,Y,Z分量的范围是[1,-1](OpenGL)
DirectX中Z分量是[0,1]
Unity=OpenGL
Unity中屏幕空间左下角是[0,0],右上角是[pixelWidth,pixelHeight]
由于当前的X,Y都是[1,-1],所以屏幕映射就是一个缩放的过程
此时Z分量经过齐次除法,也就是除W,得到的数值直接存进了深度缓冲区,这步是自动的,当然也可手动
W分量的意义主要是充当分母来得到NDC

image.png

以上就是从模型空间变换到屏幕坐标的过程

光栅化阶段

image.png
下面说下关于屏幕坐标的问题

视口空间坐标公式如下


image.png

上面公式的思想就是,首先对裁剪空间下的坐标进行齐次除法,得到范围在[ − 1, 1] 的 NDC,然后再将其映射到范围在[ 0, 1] 的视口空间下的坐标。
ComputScreenPos 用法


image.png

image.png

Unity中先在顶点着色器里将其映射到范围[ 0, W] ,然后再片段着色器中自己手动齐次除法变为[ 0, 1] 。

z和w值就是裁剪空间下的值。
详情请看ComputScreenPos ,其定义位于UnityCG.cginc中

更新:2022/8/8
CPU部分:
Unity内置管线 Build-in
调用Render()→
剔除:视锥剔除、遮挡剔除、层级剔除→
渲染顺序:按距离、渲染队列→
打包数据、参数,调用Shader:SetPassCall(渲染状态,剔除,混合模式等),DrawCall(模型数据)→
(顶点坐标,法线,UV,切线,顶点色,索引列表)
(世界变换矩阵,视角VP矩阵,fov)
(shader,材质参数,灯光信息)

GPU部分:(顶点处理→图元装配及光栅化→片元处理→输出合并→Framebuffer)
Shader处理(GPU渲染管线)→
帧缓冲区→
后处理→
再次Shader处理(GPU渲染管线)→
最终结果显示到屏幕

顶点Shader:(MVP)
模型空间→(Model Matrix)→世界空间→(View Space)→相机空间→(Projection Matrix)→裁剪空间
经过投影矩阵变换(将三维物体投影到2D平面上)


image.png

硬件操作阶段(图元装配及光栅化阶段):
裁剪空间→(裁剪操作)→


image.png

(透视除法)→NDC标准化设备坐标(Z值保留,就是光栅化后片元 深度值)→背面剔除


image.png

(视口转换,将-1,1转换到比如1920*1080的屏幕区间)→屏幕坐标→
image.png

图元装配(将点连线成面)→光栅化(填充颜色像素)→片元

片元数据(color,depth)→Alpha测试→模板测试StencilTest→深度测试DepthTest→混合Blending→帧缓冲区(colorbuffer,depthbuffer,stencilbuffer)

什么视Early-Z?
————————————————
版权声明:本文为CSDN博主「白筱风」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/whitebreeze/article/details/118688150

image.png

在以下几种情况中,Ealry-Z会不生效

开启Alpha Test 或 clip/discard 等手动丢弃片元操作
手动修改GPU插值得到的深度
开启Alpha Blend
关闭深度测试Depth Test
注:前两点情况原理类似,由于手动进行了片元的丢弃,会导致深度测试筛选出的片元也可能会被舍弃;第三点是由于开启了Alpha Blend一般会关闭深度写入,所以也不会生效;第四点关闭深度测试自然不会生效


image.png

image.png

有大量OverDraw的场景中使用Z-prepass可以很好的减小消耗
如渲染头发:
第一个pass用于生成Z Buffer:开启透明度测试仅通过不透明的测试,并关闭背面剔除,开启深度写入,关闭颜色缓冲区写入,只返回透明度值
之后的3个PASS与之前类似:第一个是渲染不透明物体,并剔除背面,设置深度测试为等于,关闭深度写入
第二个渲染背面,剔除正面,并关闭深度写入,深度测试为小于
第三个渲染正面,剔除背面,并开启深度写入,深度测试同上
DepthPrePass示范:

Pass {
            Tags{"LightMode"="DepthPrePass"}
            ZWrite On
            ColorMask 0
            Cull Off
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            struct Attributes
            {
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD0;
                float4 color : COLOR;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 pos : SV_POSITION;
                float2 uv:TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };
            Varyings vert (Attributes input)
            {
                Varyings output = (Varyings)0;
                float3 worldPos = WaveVertex(input.vertex, input.texcoord.xy, input.color, _WaveSpeed, _GrassWaveIntensity);
                output.pos = TransformWorldToHClip(worldPos);
                output.uv = TRANSFORM_TEX(input.texcoord.xy, _MainTex);
                return output;
            }
            float4 frag (Varyings input) : SV_Target
            {
                float4 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv)*_Color;
                float4 col = albedo * _Color;
                clip(col.a - _Cutoff);
                return 0;
            }
            ENDHLSL
        }
常用数学知识

Sin:对边比斜边
Cos:邻边比斜边
Tan:对边比临边。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容