本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的githubgit
若是有什么说的不正确的请批评指正github
流水线机制,拆分小段,前面的工序不用等后面的工序,流水线机制在计算机世界中常用,好比:TCP缓存
渲染管线函数
应用阶段(开发者控制)、几何阶段(决定图元)、光栅化阶段(决定像素)性能
顶点着色器:实现顶点的空间变换,坐标变换(模型空间转换到齐次裁减空间)、逐顶点光照、计算顶点颜色学习
曲面细分着色器:细分图元,图元就是:点、线、面等渲染所需的几何信息测试
几何着色器:执行逐个图元的着色操做,或者用于产生更多的图元spa
片元着色器:逐片元的着色操做,修改颜色、深度缓冲、进行混合插件
三角形设置:由定点信息计算出边的信息3d
三角形遍历:计算是否在三角形内,使用与三条边叉乘的方法判断在边的左边或者右边,遍历3条边的方式按照顺时针或者逆时针,对应点在
计算三角形内的数据:
计算颜色:插值计算
决定是否丢弃片元
合并颜色,颜色缓冲区,此次获得的结果和存储的结果进行合并
数据加载到显存(显卡的内存,图像缓冲、深度缓冲)
设置渲染状态
调用DrawCall
一个命令队列,cpu给命令、gpu拿命令
drawcall就是一种命令,GPU的渲染速度很快,性能瓶颈主要是在CPU传递命令这方面
减小drawcall的方法有不少,其中Batching批处理是很经常使用的方法,思路就是把小的drawcall合并成大的drawcall,适用于静态的物体
用于编写着色器的语言,主要是顶点着色器和片元着色器须要编写
摘取乐乐女神的指导
通常用CG/HLSL代码写: CG代码和DX9的HLSL代码几乎同样,要在CGPROGRAM中写,CGPROGRAM要使用上面的Property的数据就要声明和上面Property同样名字同样类型的变量,若是不想在多个Pass里声明,则能够在Pass前的CGINCLUDE ... ENDCG之间声明变量,这样的Property是多Pass共用的
Properties{ _Color("Color Tint", Color) = (1, 1, 1, 1) } SubShader{ Pass{ ... fixed4 _Color; ... } }
命个名和shader在面板中的目录
Shader "Custom/MyShader" //名字
Properties
属性,会出如今材质面板中
Properties{ Name("display name",PropertyType) = DefaultValue //....... }
Name:属性的名字
display name:显示的名字
PropertyType:类型
ps:shader里改过了Property在C#脚本里并不能得到更改后的信息,只能得到预设的信息,GPU像CPU传数据使用Compute Shader
数据类型
2D、Cube、3D是三种纹理类型,默认值是一个字符串+{},字符串是内置的纹理名称
SubShader
unity扫描全部的SubShader块找到可以在目标平台上运行的SubShader,若是找不到就使用Fallback提供的Unity Shader
SubShader { [Tags]//标签 [RenderSetup]//状态 Pass{ }//完整的渲染流程 //Other Pass }
显卡状态,在Pass里写的,剔除、深度、混合
怎么样以及什么时候渲染该对象,渲染队列最重要
Pass
表示渲染流程,一个Pass表示经过管线一次,能够写顶点着色器和片元着色器
UsePass可使用其余Unity Shader的Pass,以提高复用性(用法:指明路径,而且Pass要有Name)
LightMode在有光照信息时读取光源的信息使用,主要是肯定光源位置等
Shader "Unlit/Chapter5SimpleShader" { SubShader { //选择不声明任何材质属性 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag//编译指令 //哪一个函数包括了顶点着色器的代码 //哪一个函数包括了片元着色器的代码 #include "UnityCG.cginc"//调库,你的unity目录\Editor\Data\CGIncludes struct a2v { float4 vertex :POSITION; float3 normal:NORMAL; float4 texcoord:TEXCOORD0; }; float4 vert(a2v v) :SV_POSITION{ return UnityObjectToClipPos(v.vertex); }//接受顶点坐标(POSITION)返回了顶点在裁剪坐标的位置(SV_POSITION) float4 frag() : SV_Target{ return fixed4(1.0,1.0,0.0,1.0); }//SV_Target告诉渲染器把用户的输出颜色存储到一个渲染目标中,这里是帧缓存 ENDCG } } }
POSITION、NORMAL、TEXTCOORD0等都称为语义semantic,在结构体里的表示把提取到的信息当成一个什么对待,输出语义表示输出的结果是做为何对待
POSITION顶点位置,在模型空间,NORMAL顶点法向量,也是模型空间,TEXTCOORD0表示纹理坐标,按理说纹理坐标只要uv,2维就能够了,可是有时好比天空盒的纹理须要用到3维的信息,一张纹理图有时前两维给一些信息,后两维又给一张图的uv信息
vert里的输出语义没有也能够,能够选择输出结构体
struct a2v { float4 vertex : POSITION; float2 texcoord0 : TEXCOORD0; }; ... v2f vert(a2v i) { v2f o; o.pos = UnityObjectToClipPos(i.vertex); o.uv = i.texcoord0; return o; } ...
在frag里的SV_Target表示屏幕上的像素(帧缓冲),还能够输出SV_Depth来覆盖深度缓冲区,不过官方说吃性能
一、假彩色图像,把数据做为颜色输出到屏幕上而后用取色器查看的数值调试法。
没办法,渲染管线里的数据不是想拿就拿的,让你随便拿了管线不至关于开了个洞,像素都漏了
二、帧缓冲区调试,Frame Debugger
三、VS插件ShaderLab补全,体验通常,甚至不想开
GPU结构决定它不擅长处理选择、循环等结构的程序,分支下的代码、分支的层数要尽量少由于他会下降GPU的并行处理操做,条件变量最好是常数
太多了,很差写,基础知识看看乐乐老师的书吧0.0
各类空间关系一开始搞不太懂也没事,后面能够在实践中慢慢理解
这块乐乐老师的书上讲的牛的点变换推导很详细
模型空间:也叫对象空间、局部空间
世界空间:绝对位置,一个Transform没有父节点他的位置就是绝对位置
观察空间:摄像机空间,模型空间的特例
裁剪空间:clip space 裁剪矩阵,有一个视锥体决定摄像机能够看到的空间
屏幕空间
unity坐标旋向性