观前提示:本文章是个人笔记,只是给自己看的,我自己看得懂就行。
目录
一、CPU和GPU编程的区别
(CPU)Center Processing Unit:逻辑编程
(GPU)Graphics Processing Unit:图形处理(矩阵运算,数据公式运算,光栅化)
二、渲染管线的执行步骤
渲染管道也称为渲染流水线,就是CPU准备一些数据,然后告诉GPU渲染出一个二维的图像过程。
渲染管道的三个阶段:应用阶段,几何阶段,光栅化阶段。
1、应用阶段(CPU)
主要就是CPU将硬盘中的数据加载后,和内存进行通讯,将需要显示的数据信息(顶点数据,纹理坐标,法线信息),传递给GPU处理。
2、几何阶段(GPU)
几何阶段最重要的工作就是“变换三维顶点坐标”,变换的工作由矩阵运算完成。
空间
模型空间:3D物体的原始坐标,存储在模型中。
世界空间:物体放在场景中,才能构成整个游戏场景。
观察空间:需要以相机为原点的3维空间。
裁剪空间:物体是否在相机的渲染范围内。
屏幕空间:3D物体,投影到屏幕上。
物体最终显示:需要GPU进行一系列的矩阵运算,将模型空间下的网格顶点,转换到屏幕空间下(转换点的过程是并行)。非模型网格顶点信息中记录的点,GPU会以线性插值的方式获得并显示。
3、光栅化阶段(GPU)
使用上一个阶段(几何阶段)递过来的数据,对像素点进行染色,最终显示出来,染色过程为并行执行。
三、Shader是什么
1、定义
Shader给GPU编程的语言,代码会在GPU上并行执行(几何运算,光栅化)。
2、Unity的Shader类型
固定管线Shader:很古老显卡的编程着色器,现在很少使用,画质不好。
顶点/片元Shader:通用的着色器类型(重点学习),可编程。
表面体Shader:Unity自己创建的着色器类型,基于顶点/片元着色器二次封装实现,降低了着色器的编写难度。
3、材质球和Shader的关系
Unity中Material用来关联游戏物体和Shader着色器,所以编写Shader前,需要先建立材质球。
4、建立Shader方法
建立材质球
建立Shader文件(选择类型)
(1)表面体Shader
(2)顶点/片元Shader
(3)图片效果Shader
(4)GPU运算Shader
四、Shader的基本代码结构
Shader "test/VFColor"
{
//属性,显示在材质球选项上
Properties
{
Name("Display Name", Type) = DefaultValue
}
SubShader
{
Pass
{
//执行一次渲染效果
}
Pass
{
//再执行一次渲染效果
}
}
SubShader
{
}
FallBack “Diffuse”
}
test/VFColor决定该 Shader 在选择面板上所处的位置,很像文件的全路径。Shader "test/VFColor"将位于test→VFColor
· Properties括号中定义的属性将在材质球面板上展示,可以方便地进行调节。定义一个属性,就像在 C 语言中定义一个变量一样,只是格式稍有不同。在上面的代码中,Name 是属性的名字,Display Name 是用于展示在材质面板上的名字,Type 是属性的类型,DefaultValue 是属性的默认值。ps:其中 Name 常常以下划线开头,例如 _PropertiesName。
每个 Unity Shader 中都可以包含多个 SubShader,当 Unity 展示一个 Mesh 时,将会从这些 SubShader 中找到第一个可以运行的来运行。需要考虑到Unity在不同的平台该怎么渲染,并分别提供不同的SubShader块来帮助Unity完成渲染。
Pass通道属于SubShader,每一个SubShader可以同时存在多个Pass通道,每个SubShader内的Pass通道从上往下一次执行。
如果所有 SubShader 都无法使用时,将会尝试使用 Fallback 指定的着色器。如:
Fallback "Diffuse"
下方为顶点着色器与片元着色器写法代码示例:
Shader "test/VFColor"
{
Properties
{
_Color("Color",COLOR) = (1,1,1,1)
}
SubShader
{
Pass
{
//CG语言开始的定界符
CGPROGRAM
//通过Cg的指令,设定vert()为顶点着色器调用的函数
#pragma vertex vert
//通过Cg的指令,设定frag()为片元着色器调用的函数
#pragma fragment frag
//如果在Cg语言中,需要材质球的属性值,则需要导入
fixed4 _Color;
//GPU在集几何阶段运行的回调函数(顶点着色器)
//要做什么?将模型空间下的点转换到剪裁空间下
//传入是什么?CPU传递过来的模型空间下的点的位置,传出的是点在裁剪空
//间下的位置,传递给GPU
//POSITION语义,告诉GPU,你将模型空间下的点的位置,赋值到v变量中
//SV_POSITION语义,告诉GPU,我将计算后的裁剪空间下的点的位置,放在
//了函数的返回值中
float4 vert(float4 v:POSITION):SV_POSITION
{
//矩阵运算坐标转换
//Unity的内置矩阵UNITY_MATRIX_MVP,可以将点从模型空间下,转换
//到裁剪空间下
//返回就会吧数据传递给GPU,继续执行渲染流水线
return UnityObjectToClipPos(v);
}
//GPU在光栅化阶段运行的回调函数(片元着色器)
//要做什么?给物体上的所有顶点进行染色
//传入什么?顶点着色器经过计算后,点在裁剪空间下的位置
//传出什么?需要渲染的点的颜色
//SV_POSITION语义:告诉GPU,你将顶点着色器算出来的裁剪空间下的点的
//位置,赋值在v变量中
//SV_Target语义:告诉GPU,我当前要显示的点的颜色值是多少,你显示出来
fixed4 frag(float4 v:SV_POSITION):SV_Target
{
return _Color;
}
//CG语言结束的定界符
ENDCG
}
}
FallBack "Diffuse"
}