Unity ShaderLab整理

预备知识

  • 模型文件存储结构(包含了顶点位置以及面的组成信息)


    模型文件

渲染过程

渲染管线的知识,很有必要去冯乐乐的书里看一下,在第9页( 2.3 GPU 流水线 )


渲染流水线

不同的渲染管线会有不同的差异,但是大体还是类似,要经过以上的一些步骤。
流水线中,我简化了重点去理解:

  • 首先CPU把顶点数据传递给Shader的顶点着色器(在Unity中就是通过Mesh Renderer组件),开始一次DrawCall。
  • GPU在几何阶段把三维的坐标通过自己定义的顶点函数,按照给定的规则映射到二维的屏幕坐标中。
  • 于是屏幕上就出现了很多个点,但是还没有连成闭合的区域,所以在三角形遍历的时候,就是通过插值的方式在各个点包围的三角形内部填充其他点的信息。
  • 片元着色器把三角形中的每个点给拿过来,通过自定义的规则,为每个像素填充颜色。
  • 填完颜色后,放入缓存,等待后续的测试,例如混合测试。(比如透明物体背后还有一个物体,那么两个物体的颜色怎么混合)。
  • 最后输出屏幕。

可以用以下简化的图来表示,其中Vertex Processor和Pixel Processor中间还有重要的插值的一步,因为顶点的个数是远少于像素的个数的,那么这个输入输出该怎么对应?
如果像素有多少个,至少顶点也要有多少个吧,所以多余的顶点的信息(包括位置,顶点法线,颜色等等)就是通过原本的顶点插值计算出来的。

渲染过程简化
  • Shader是图形可编程方案的程序片段

  • 渲染管线是一种计算机从数据到最终图形程序的形象描述

  • 材质是商品,Shader是方法,贴图是材料

  • 图形语言包括:
    OpenGL的GLSL
    DirectX的HLSL
    NVIDIA的CG

  • GPU采用并行计算,因此在顶点处理程序中,所有顶点信息可以同时计算,并且耗费相同时间。

  • 渲染管线最终认识的还是Vertex ShaderFragment Shader,Unity发明的Surface Shader只是对这两种Shader的包装。

  • Vertex Shader中,包含顶点坐标转换顶点色顶点法线的计算等工作,例如把模型文件中的点的信息转换成屏幕上的坐标信息等。

  • 渲染的过程中,一些Unity的全局光照设置、主摄像机等等信息都会作为全局变量,供Shader的使用。

  • 每一个像素格都会根据顶点着色器Fragment Shader中的方法计算出结果


ShaderLab 的基本结构

  • ShaderLab语言是对HLSL、CG等语言的封装。更准确的说,HLSL、CG等语言是以内嵌的方式存在于ShaderLab语言中的。所以当遇到内嵌的代码段的时候,其中的语法和其外面包裹着的ShaderLab的语法是不一样的。
shader "name"{
    [Properties]
    SubShaders
    [Fallback]
}
ShaderLab

以下的规则仅仅指ShaderLab的语法,不代表其中内嵌的CG、HLSL的语法。

  • ShaderLab中不区分大小写
  • ShaderLab中不需要分号
  • ShaderLab中必须至少要有一个SubShader
  • 由于硬件不同,因此可以有多个SubShader,如果第一个SubShader不支持该硬件,那么就会顺序执行第二个SubShader
  • 如果所有的SubShader都不能执行,那么在Fallback中就会执行最后处理,通常在这里的处理用的都是Unity内建的一些通用的基础Shader
Unity内置基础Shader举例

先从连连开ShaderForge开始

  • 这里的连连看插件用的是Shader Forge,但是现在已经不更新了,最后更新是在2018的版本中,但是也可以用。
  • Shader Forge最后生成的Shader代码没有Shader Graph那么多,稍微方便一点,所以先用这个。

用ShaderForge实现兰伯特光照

兰伯特光照是最基础的漫反射模型,其效果如下

Lambert光照模型

在兰伯特光照中,很明显,朝向光的点最亮(灰度为1),背向光的点最暗(灰度为0),中间则介于0~1之间。
通过光的反方向lDir某个点的朝向(该点法向量)nDir的接近程度,就可以得知该点是否面朝光
刚好,数学上的点乘Dot刚好可以用于表示两个向量方向的接近程度,数值越大,两者方向越接近。(两个向量前提都经过了归一化处理)
点乘的定义是:a·b = |a||b|cosθ
当某点面朝光时,θ = 0,那么cosθ = 1。最后点乘结果也是等于1。
模型上的每个点都进行一次 灰度值 = a·b 的运算,就可以得到整个模型经过漫反射之后的外观。

通过上面的描述,我们首先需要获取两个重要的量,一个是全局光照的方向IDir,一个是几何体上的某点的法向量nDir。打开ShaderForge,空白处右键:

光向量数据

法向量数据

这两个数据一个在Lighting下,是全局的,一个在Geometry Data下。


ShaderForge节点

对它们进行点乘,点乘节点位于向量运算Vector Operations里。


点乘

连接节点

点击左上角Compile Shader就可以将ShaderForge中的连接编译成shader代码。

选中创建的shader右键create->material,创建材质。


创建材质

将材质赋予游戏物体,得到最后效果。


最终样貌

Fixed Function Shader( 了解 )

参考文章:
https://blog.csdn.net/weixin_30699831/article/details/95653586

固定命令的Shader,可以在所有硬件平台上运行,但是功能有限。

固定渲染管线中,主要包含以下代码块:


image.png
Shader "Custom/s01"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _Ambient("Ambient",Color) = (0.3,0.3,0.3,0.3)
        _Specular("Specular",Color) = (1,1,1,1)
        _Shininess("Shininess",Float) = 0.3
        _Emission("Emission",Color) = (1,1,1,1)
    }
    SubShader
    {
        Pass{
            Material{
                Diffuse[_Color]
                Ambient[_Ambient]
                Specular[_Specular]
                Shininess[_Shininess]
                Emission[_Emission]
            }
            Lighting on
            SeparateSpecular on
        }
    }
}

CG语法

  • 写在CGPROGRAM和ENDCG包裹的片段中,但是这两个关键字是ShaderLab的语法,不是CG的语法。
  • CG语言区分大小写
  • 通过#pragma vertex 顶点函数名声明顶点着色器
  • 通过#pragma fragment 片元函数名声明片元(像素)着色器
  • 通过#include "库函数名.cginc"声明外部引用的库
数据类型
  • float4:4维向量,分量分别是xyzw。每个分量的占32bit,精确到小数点后6位。
  • half4: 4维向量,每个分量占16bit,表示范围为[-60000,60000],精确到小数点后3位。
  • fixed4:4维向量,分量分别是rgba。每个分量占11bit。表示范围为[-2,2],精度为1/256
    使用分量的时候,可以通过.x/.y/.z/.w/.xy/.xz等等,甚至还可以.xxyy。
    例如以下的赋值方式都合法的:
float4 pos;
float3 temp = pos.xyz;
temp = pos.yzz;
temp = float3(pos.yz,1);

不可以将低维向高维转换,因为缺失了高维的数据。
例如: float3(1,0,0) --x--> float4(1,0,0,?)
可以将高维向低维转换,会直接舍弃高维数据。
例如: float4(1,0,0,1) --√-->float3(1,0,0)

  • 坐标位置通常会用float4表示,由于float4类型的位置可以方便矩阵变换。所以需要将原本float3类型的位置信息扩散到齐次坐标空间。并且分量w可以用于表示该坐标是一个点,还是一个向量。
    点,用float4表示,就是float4(x,y,z,1)。
    向量,用float4表示,就是float4(x,y,z,0)。
  • 颜色通常会用fixed4来表示,因为颜色的表示不需要那么大的精度
  • 齐次坐标空间:将一个原本是n维的向量用一个n+1维向量来表示
各种语义的意义和范围
  1. Unity中Renderer组件传递给顶点着色器的关联语义
    POSITION : 模型空间(相对于模型自身)的顶点坐标,float4类型。分量xyz可用于表示的范围为[-0.5,0.5],分量w的取值为0或1,0代表点,1代表向量。
    NORMAL : 顶点法线,float3类型
    TANGENT :顶点切线,float4类型
    TEXCOORDn :第n套纹理坐标,float2或float4类型
    COLOR : 顶点颜色,fixed4或float4类型

  2. 顶点着色器输出数据的语义
    SV_POSITION :剪裁空间(屏幕空间)下的坐标。左下角为原点(0,0) 横轴的范围是(0,屏幕宽度) 纵轴的范围是(0,屏幕高度)。结构体中必须包含一个用该语义修饰的变量。
    COLOR0 : 通常用于输出第一组顶点颜色,但不是必需的
    COLOR1 : 通常用于输出第二组顶点颜色,但不是必需的
    TEXCOORD0~TEXCOORD7 : 通常用于输出纹理坐标,但不是必需的

  3. 片元着色器输出数据的语义
    SV_TARGET : 最终输出屏幕的颜色值,fixed4或float4类型。有时候这个语义可以写成COLOR,但是由于SV_TARGET在各个平台上都容易被识别,所以还是选用这个。

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

推荐阅读更多精彩内容