Unity ShaderLab整理

2021-02-06  本文已影响0人  爱吃鱼的鸡米

预备知识


渲染过程

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


渲染流水线

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

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

渲染过程简化

ShaderLab 的基本结构

shader "name"{
    [Properties]
    SubShaders
    [Fallback]
}
ShaderLab

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

Unity内置基础Shader举例

先从连连开ShaderForge开始

用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语法

数据类型
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)

各种语义的意义和范围
  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在各个平台上都容易被识别,所以还是选用这个。

上一篇下一篇

猜你喜欢

热点阅读