Fixed function shader从字面意思理解,就是固定功能的渲染着色器 这种Shader功能有限,但速度却是最快的 但是能够在基本上所有的硬件平台上执行

案例1:固定着色

Shader"Unlit/firstFixedShader"
{
SubShader
{
 pass
 {
 color(1,1,1,1)
 }
 }
}

截屏2021-11-22 下午4.16.29.png

Properties

使用Properties,提供外部的Shader属性参数配置

案例

Shader"Unlit/firstFixedShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 }
 SubShader
 {
 pass
 {
 //color(1,0,0,1)
 color[_Color]
 }
 }
}

() 小括号是固定的值 [ ]中括号是属性的值 所以填入color[_Color] 就可以把属性_Color给color 从而达到着色效果

Material材质

案例1:漫反射光照Shader

Shader "Unlit/firstFixedShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 }

 SubShader
 {
 pass
 { 
 material
 {
 diffuse[_Color]
 }
 lighting on //off
 }
 }
}

截屏2021-11-22 下午4.42.32.png

material是一个功能块 diffuse是漫反射 diffuse[_Color]设置漫反射颜色 lighting on 开启光照,这样才能让Shader接受光照,从而实现漫反射效果

案例2:加入环境光

Shader "Unlit/firstFixedShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 }

 SubShader
 {
 pass
 { 
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 }
 lighting on //off
 }
 }
}

截屏2021-11-22 下午4.49.39.png

红色部分就是环境光影响的部分

红色部分就是环境光影响的部分 ambient 是环境光 在真实世界当中,一个物体会受到其环境光的影响 所以我们可以在Shader中加入环境光的效果,来模拟真实世界 创建一个属性**_Ambient** 为环境光传入属性ambient[_Ambient] 环境光Alpha通道,不会对环境光有任何影响

案例3:高光

Shader "Unlit/firstFixedShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 }

 SubShader
 {
 pass
 { 
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]//高光
 }
 lighting on //off
 separatespecular on //高光计算 要使用specular功能,必须开启
 }
 }
}

如果不SeparateSpecular On,那么是不会计算高光的。 如果SeparateSpecular On,计算高光,但是高光是单独计算的。即计算漫反射环境光(但不包括高光)等相加起来得到的光照,跟纹理混合。混合之后的颜色再加上我们单独计算的高光,这样得到最终的颜色。要起作用,必须Lighting On

截屏2021-11-22 下午5.04.54.png

截屏2021-11-22 下午5.05.05.png

真实世界中物体收到光照影响,会有高光部分 在固定渲染管线的Shader中 可以使用specular高光功能 来添加材质的高光着色 **specular[Color]**

案例3:shininess调整高光集中度

Shader "Unlit/firstFixedShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 _Shiness("Shininess",range(0,1))=1
 }

 SubShader
 {
 pass
 {
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]//高光
 shininess[_Shiness]//高光集中度
 }
 lighting on //off
 separatespecular on //要使用specular功能,必须开启
 }
 }
}

截屏2021-11-22 下午5.12.30.png

截屏2021-11-22 下午5.14.00.png

shininess可以控制高光的集中度 shininess需要传入一个浮点值 所以外部定义属性的时候 可以将类型设置成float 或者是range

案例4:Emission自发光

Shader "Unlit/firstFixedShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 _Shiness("Shininess",range(0,1))=1
 _Emission("Emission",color)=(0.5,0.5,0.5,1)
 }

 SubShader
 {
 pass
 {
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]
 shininess[_Shiness]
 emission[_Emission]//自发光
 }
 lighting on //off
 separatespecular on //要使用specular功能,必须开启
 }
 }
}

Emission控制从表面发出的光的颜色和强度。当你在场景中使用Emission材质时,它以可见光源的形式出现。自发光。 Emission材质通常是用在GameObjects需要从内部亮了起来,如监视器上的屏幕,如汽车在夜间行驶时闪亮的仪表盘,或是再漆黑地方闪亮着怪物的眼睛。 在计算机中,会根据自发光颜色深度来处理自发光的效果 如果自发光颜色为纯白色,那渲染的材质就是非常亮

截屏2021-11-22 下午5.27.33.png

截屏2021-11-22 下午5.25.59.png

可以减少颜色深度,提高真实感

截屏2021-11-22 下午5.28.49.png

截屏2021-11-22 下午5.28.17.png

纯黑色的话就,看不到自发光效果

截屏2021-11-22 下午5.29.45.png

截屏2021-11-22 下午5.29.32.png

Lighting

在Pass中 lighting on//可以启用光照 启动的是定点光照

SetTexture

在绘制材质过程中,有些时候,我们想要绘制指定的贴图纹理 在ShaderLab中,固定渲染着色器里可以使用settexture指令进行贴图绘制

案例1:绘制纹理

Shader "Unlit/FixedTextureShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 _Shiness("Shininess",range(0,1))=1
 _Emission("Emission",color)=(0.5,0.5,0.5,1)
 _MainTex("MainTex",2D)=""
 }

 SubShader
 {
 pass
 {
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]
 shininess[_Shiness]
 emission[_Emission]
 }
 lighting on
 separatespecular on
 settexture[_MainTex]

 }
 }
}

截屏2021-11-23 下午10.46.49.png

截屏2021-11-23 下午10.47.03.png

_MainTex(“MainTex”,2D)=""//定义了一个2D纹理贴图的属性,默认值为字符串“”,默认值其实就是给纹理取一个名称,这里填写了空字符串 shaderlab不分大小写,所以属性类型写成2d或者2D都可以编译的 settexture[纹理属性] 传入纹理属性,来设置贴图

案例2:使用combine混合纹理

Shader "Unlit/FixedTextureShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 _Shiness("Shininess",range(0,1))=1
 _Emission("Emission",color)=(0.5,0.5,0.5,1)
 _MainTex("MainTex",2D)=""
 }

 SubShader
 {
 pass
 {
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]
 shininess[_Shiness]
 emission[_Emission]
 }
 lighting on
 separatespecular on
 settexture[_MainTex]
 {
 combine texture * primary double
 }
 }
 }
}

截屏2021-11-23 下午10.55.46.png

截屏2021-11-23 下午10.56.01.png

settexture[_Maintex] { //花阔号内可以设置绘制纹理时的功能命令 } combine就是一个混合纹理颜色的命令 texture就是当前设置的纹理颜色 primary是当前pass中material中设置的材质效果,和灯光还有高光反射颜色 texture*primary相当于对两个颜色进行正片叠底 也就是将两个颜色每个RGB通道的分量相乘 double 相当于将 混合的颜色再乘两倍,这样可以提高整体亮度,也可以乘4倍 quad

案例3:多张纹理贴图混合

Shader "Unlit/FixedTextureShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 _Shiness("Shininess",range(0,1))=1
 _Emission("Emission",color)=(0.5,0.5,0.5,1)
 _MainTex("MainTex",2D)=""
 _SecondTex("SecondTex",2D)=""
 }

 SubShader
 {
 pass
 {
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]
 shininess[_Shiness]
 emission[_Emission]
 }
 lighting on
 separatespecular on
 settexture[_MainTex]
 {
 combine texture * primary double
 }
 settexture[_SecondTex]
 {
 combine texture * previous double
 }
 }
 }
}

这里要注意settexture并不是无限次的 不同的显卡支持的纹理混合次数是不同的

截屏2021-11-23 下午11.20.48.png

截屏2021-11-23 下午11.21.53.png

在第二层settexture中 combine 命令混合时 是由当前纹理texture他颜色和previous颜色相乘 previous包含了上一次settexture混合的纹理颜色加上primary颜色 如果这里用primary的话 可以会导致无法获取到第一次settexture设置的纹理颜色 最终效果也就只有_SecondTex纹理的效果了

ShaderLab:Blending

Untitled

确定 GPU 如何将片元着色器的输出与渲染目标进行合并。 此命令的功能取决于混合操作,您可以使用 BlendOp 命令进行设置。请注意,虽然所有图形 API 和硬件都支持混合功能,但对某些混合操作的支持较为有限。 启用混合会禁用 GPU 上的一些优化(主要是删除隐藏的表面/Early-Z),这些优化会增加 GPU 帧时间。 渲染管线兼容性

语法

Blend Off:关闭混合(这是默认设置) Blend SrcFactor DstFactor:配置并启用混合。生成的颜色乘以SrcFactor。屏幕上已有的颜色乘以DstFactor,然后将两者相加。 Blend SrcFactor DstFactor, SrcFactorA DstFactorA:与上面相同,但使用不同的因素来混合 Alpha 通道。 BlendOp Op:不是将混合颜色添加到一起,而是对它们执行不同的操作。 BlendOp OpColor, OpAlpha: 同上,但对颜色 (RGB) 和 alpha (A) 通道使用不同的混合操作。 此外,您可以设置上渲染目标混合模式。使用多渲染目标 (MRT) 时渲染,上面的常规语法为所有渲染目标设置了相同的混合模式。以下语法可以为各个渲染目标设置不同的混合模式,其中N是渲染目标索引 (0..7)。此功能适用于大多数现代 API/GPU(DX11/12、GLCore、Metal、PS4):

  • Blend N SrcFactor DstFactor
  • Blend N SrcFactor DstFactor, SrcFactorA DstFactorA
  • BlendOp N Op
  • BlendOp N OpColor, OpAlpha

AlphaToMask On:打开 alpha-to-coverage。当使用 MSAA 时,alpha-to-coverage 会根据像素着色器结果 alpha 值按比例修改多样本覆盖掩码。这通常用于比常规 alpha 测试更少锯齿的轮廓;对植被和其他经过 alpha 测试的着色器很有用。

混合因子

以下所有属性对Blend命令中的 SrcFactor 和 DstFactor 均有效。Source是指计算出的颜色,Destination是屏幕上已有的颜色。如果BlendOp使用逻辑运算,则混合因子将被忽略。 混合因子列表

混合操作

Blend operations

常见混合类型 (Blend Type)

以下是最常见的混合类型的语法:

Blend SrcAlpha OneMinusSrcAlpha // 传统透明度
Blend One OneMinusSrcAlpha // 预乘透明度
Blend One One // 加法
Blend OneMinusDstColor One // 软加法
Blend DstColor Zero // 乘法
Blend DstColor SrcColor // 2x 乘法

案例4:实现材质的透明效果

截屏2021-11-23 下午11.52.46.png

当我们在渲染鼠标指的球体的时候的颜色,我们称之为源颜色 除了鼠标所指的球体以外的渲染的颜色(包括天空盒),我们称之为目标颜色 目标颜色,在我们渲染源颜色之前已经渲染过了

Shader "Unlit/FixedTextureShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 _Shiness("Shininess",range(0,1))=1
 _Emission("Emission",color)=(0.5,0.5,0.5,1)
 _MainTex("MainTex",2D)=""
 _SecondTex("SecondTex",2D)=""
 }

 SubShader
 {
 pass
 {

 Blend SrcAlpha OneMinusSrcAlpha
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]
 shininess[_Shiness]
 emission[_Emission]
 }
 lighting on
 separatespecular on
 settexture[_MainTex]
 {
 combine texture * primary double
 }
 settexture[_SecondTex]
 {
 combine texture * previous double
 }
 }
 }
}

截屏2021-11-24 上午12.05.58.png

截屏2021-11-24 上午12.06.16.png

可以看到 SrcAlpha OneMinusSrcAlpha 经过a*(1-a) 处理之后得到了传统的透明度的混合

案例5:Tags与渲染队列

管理Tags的Unity文档⬇️ https://docs.unity3d.com/Manual/SL-SubShaderTags.html

Shader "Unlit/FixedTextureShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 _Shiness("Shininess",range(0,1))=1
 _Emission("Emission",color)=(0.5,0.5,0.5,1)
 _MainTex("MainTex",2D)=""
 _SecondTex("SecondTex",2D)=""
 }

 SubShader
 {
 Tags{"Queue"="Transparent"}
 pass
 {

 Blend SrcAlpha OneMinusSrcAlpha
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]
 shininess[_Shiness]
 emission[_Emission]
 }
 lighting on
 separatespecular on
 settexture[_MainTex]
 {
 combine texture * primary double
 }
 settexture[_SecondTex]
 {
 combine texture * previous double
 }
 }
 }
}

截屏2021-11-24 上午12.10.04.png

截屏2021-11-24 上午12.10.22.png

通过标签设置渲染队列为Transparent,透明物体,加上传统Alpha的混合,就可以实现透明物体的效果,透过物体可以看到背后渲染的物体

案例6:使用纹理的Alpha通道,实现透明效果

Shader "Unlit/FixedTextureShader"
{
 Properties
 {
 _Color("Main Color",color)=(1,1,1,1)
 _Ambient("Ambient",color)=(0.3,0.3,0.3,1)
 _Specular("Specular",color)=(1,1,1,1)
 _Shiness("Shininess",range(0,1))=1
 _Emission("Emission",color)=(0.5,0.5,0.5,1)
 _MainTex("MainTex",2D)="white"{}
 _SecondTex("SecondTex",2D)=""{}
 _ConstantColor("ConstantColor",color)=(1,1,1,0.3)
 }

 SubShader
 {
 Tags{"Queue"="Transparent"}
 pass
 {

 Blend SrcAlpha OneMinusSrcAlpha
 material
 {
 diffuse[_Color]
 ambient[_Ambient]
 specular[_Specular]
 shininess[_Shiness]
 emission[_Emission]
 }
 lighting on
 separatespecular on
 settexture[_MainTex]
 {
 combine texture * primary double
 }
 settexture[_SecondTex]
 {
 constantColor[_ConstantColor]
 combine texture * previous double,texture*constant//,逗号之后取颜色的Alpha通道
 }//不同显卡有不同的最多支持混合次数
 }
 }
}

截屏2021-11-24 上午12.18.01.png

截屏2021-11-24 上午12.18.12.png

constantColor命令指定一个颜色可以用于Combine指令。 combine逗号之后的参数 表示混合的Alpha颜色 让当前纹理texture颜色*constant指定的颜色 这样可以通过外部暴露的 _ConstantColor整体调整材质透明度,并且同时可以应用材质_SecondTex的透明度 注意: 除非后面都是2D纹理的属性否则定义2D纹理属性 初始化的值要写上{} 这里因为后面是颜色属性所以要写上{} 这样编译器才不会报错