分享和整理一些觉得不错的教程和理解
在此感谢各位老师!
教程:
线性代数基础: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渲染管线的工作过程
几何阶段
空间变换:模型空间(左手)→世界空间(左手)→观察空间(右手)
投影准备:观察空间→观察空间(投影变换)→观察空间(裁剪空间)
经过以上变换,此时物体处在裁剪空间,
★下图需要注意,每个教材的解释略有不同,下图直接就齐次除法变成规范化的了
实际上这里只是为真正是投影(齐次除法)做准备,此时裁剪面依然是梯形四棱锥形态
目的:
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值越大
屏幕映射:规范化的观察空间(裁剪)→屏幕空间(真正的投影)
齐次除法=透视除法=归一化的设备坐标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
以上就是从模型空间变换到屏幕坐标的过程
光栅化阶段
下面说下关于屏幕坐标的问题
视口空间坐标公式如下
上面公式的思想就是,首先对裁剪空间下的坐标进行齐次除法,得到范围在[ − 1, 1] 的 NDC,然后再将其映射到范围在[ 0, 1] 的视口空间下的坐标。
ComputScreenPos 用法
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平面上)
硬件操作阶段(图元装配及光栅化阶段):
裁剪空间→(裁剪操作)→
(透视除法)→NDC标准化设备坐标(Z值保留,就是光栅化后片元 深度值)→背面剔除
(视口转换,将-1,1转换到比如1920*1080的屏幕区间)→屏幕坐标→
图元装配(将点连线成面)→光栅化(填充颜色像素)→片元
片元数据(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
在以下几种情况中,Ealry-Z会不生效
开启Alpha Test 或 clip/discard 等手动丢弃片元操作
手动修改GPU插值得到的深度
开启Alpha Blend
关闭深度测试Depth Test
注:前两点情况原理类似,由于手动进行了片元的丢弃,会导致深度测试筛选出的片元也可能会被舍弃;第三点是由于开启了Alpha Blend一般会关闭深度写入,所以也不会生效;第四点关闭深度测试自然不会生效
有大量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:对边比临边。