《Unity Shader入门精要》笔记(二) 光照初体验

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/BDalasja/article/details/79100976

第五章 开始Unity Shader学习之旅

  1. Shader的属性是用来干嘛的?如何定义?Pass中如何使用这个属性?

    属性主要是在Unity的编辑器面板显示、修改用的。定义参考UntiyShader官方文档
    pass中想要使用这个属性,需要定义一个同名变量。shader中属性变量一般以下划线开始,例如fixed4 _Color;

  2. 指定顶点、片元着色器函数

    着色器代码在CGPROGRAM 和 ENDCG之间,使用CG/HLSL语言书写。 MSDN HLSL参考

        CGPROGRAM 
        #pragma vertex vert
        #pragma fragment frag
        ...
        ENDCG
  3. UNITY_MATRIX_MVP用来干嘛? mul函数?SV_POSITION又是什么东西? SV_Target呢?

    UNITY_MATRIX_MVP是内建矩阵,是从模型空间到投影空间的转换矩阵。对于每个模型来说Unity会自动计算好几个常用的矩阵,以便使用,也减少重复计算。
    mul函数就是操作矩阵跟向量、矩阵的函数。MV 操作就是就由mul完成。所以mul(UNITY_MATRIX_MVP, v)就是坐标转换了。
    SV_POSITION 是标明目标值是顶点投影到屏幕的最终位置,一个Pass里面应该只能指定一个
    SV_Target也是一个语义(semantics),这个是用来标识最终屏幕颜色的。
    关于语义,参考UnityShader语义介绍 以及 MSDN语义介绍文档
    DX10以后SV开头的系统数值语义,通常有特殊含义 ,如SV_POSITION标识目标值包含了可用于光栅化的变换后的坐标。

  4. 着色器为什么能做到顶点参数自定义?自定义结构体内容是如何被填充的?

    Unity根据结构体中字段的语义标识来填充,能够接受的数据都是预定义好的。

  5. 顶点着色器能接受那些参数?自定义结构体如何定义?

    参考UnityShader顶点着色器能输入哪些数据

    • POSITION 顶点坐标, typically a float3 or float4.
    • NORMAL 法线, typically a float3.
    • TEXCOORD0 第一个uv坐标, typically float2, float3 or float4.
    • TEXCOORD1, TEXCOORD2 and TEXCOORD3 are the 2nd, 3rd and 4th UV coordinates, respectively.
    • TANGENT 切线 (used for normal mapping), typically a float4.
    • COLOR is the per-vertex color, typically a float4.
    // POSITION将被填充模型顶点坐标; NORMAL指定的字段将被填充法线
    struct a2v {
            float4 pos : POSITION;   
            float3 normal : NORMAL;
        };
  6. 顶点着色器与片元着色器之间如何通信?

    顶点着色器函数返回值若不是单独SV_POSITION则可以被传递给片元着色器。
    TEXCOORD1很多时候用来存储的值不是uv坐标,而是一些计算需要的值,用来传递给片元着色器。 数据的传递和存储不拘一格,包括后面的法线、切线、高度贴图

  7. 要熟悉Unity提供的内置文件和变量,使用时#include "UnityCG.cginc"来包含目标文件中的函数变量。 参考UnityShader内建文件 以及 UnityShader中的内建函数。熟悉使用,不要重复造轮子。

  8. 如何调试Shader结果?

    使用假色彩输出图像,同前面说的那样, 纹理,或者说颜色空间是着色器最好的数据存储方式,一切都是颜色。所以把要调试的数值转换成颜色输出来,就是最简单的调试方法了。
    Windows上 VS2012的Graphics Debugger 参考UnityShader使用Windows上的VS2012调试
    Unity自带的FrameDebug,只能简单看每一步pass的结果。

  9. 小心平台引起的语法差异

  10. float half fixed类型的区别?

    简单来说颜色类型的都使用fixed3 fixed4就没错了,half跟float现在基本没啥区别了。
    参考UnityShader数据类型 以及 MSDN HLSL数据类型

  11. 小心使用分支与循环语句

    • 分支判断语句中使用的条件变量最好是常数。
    • 每个分支中包含的操作指令数尽可能少
    • 分支的嵌套层数尽可能少

扩展阅读《GPU精粹2》

第六章 Unity中的基础光照

  1. 什么是光照模型?BRDF是什么东西?环境光?自发光?漫反射,高光都是个啥?

    所谓光照模型就是对真实世界光照的一个数学建模。计算的比较细比较真的就叫BPS,常见的都是一些简化的数学模型,为了减少计算量。常见的Phong及Lambert以及Blinn-Phong模型。
    现实世界中,我们能看到一个物体,受到的各种光线的反射、折射影响太复杂,标准光照模型把光线分为4个部分:

    1. 自发光 2. 高光反射 3. 漫反射 4. 环境光
      那高光反射跟漫反射有什么区别呢?简单理解就是高光反射才是反射,漫反射应该叫散射,漫反射会把光线反射到各个方向。参考下金属的反光,就是高光了。
      环境光、自发光没啥好解释的,望文知义。
  2. 漫反射、高光如何计算?

    漫反射采用Lambert定律:反射光线的强度与表面法线和光源方向之间夹角的余弦值成正比。 好,之前的数学知识开始排上用场了。n⃗ l⃗ =|n⃗ ||l⃗ |cosθ,只要N和L都是单位向量,就妥了。正式的公式如下: Clight为光线颜色,Mdiffuse为材质反射颜色

    Cdiffuse=(ClightMdiffuse)max(0,n⃗ l⃗ );

    • 高光的计算就稍微复杂一点了,主要是跟观察方向有关。如下图:
      这里写图片描述
      r⃗ =2(n⃗ I⃗ )n⃗ I⃗ 计算得出。那么这个公式到底几个意思?怎么理解呢?r⃗ +I⃗ 的结果肯定是在n⃗ 方向上,而大小为I⃗ n⃗ 上的投影的2倍。根据前面向量点积的公式,2(n⃗ I⃗ )就是投影的2倍了。注意计算点积是r跟v。公式如下:
      cspecular=(clightmspecular)max(0,v̂ r)Mgloss
    • 另一种简化计算方法(实际是PBS中的微表面反射的简化版本),就是计算光线向量跟视线向量的中值,再与法向量点乘得到ĥ =normalize(v+I)。公式也变成了下面这样,点积部分为法向量跟ĥ 
      这里写图片描述
      cspecular=(clightmspecular)max(0,n̂ ĥ )Mgloss

      其中使用的Mgloss,是光泽度,max(0,n̂ ĥ )Mgloss这部分的取值图像大概就是这样:
      这里写图片描述
      可以理解Mgloss越大,图像越陡峭,高亮范围就越小。
      (顺便发现一个在线画数学图的网站)
  3. 逐顶点光照跟逐像素光照的区别?如何选择?

    针对每个顶点计算一次光照,当然比每个像素都计算一遍光照要节省的多。由于逐像素光照的消耗,所以使用要谨慎了。
    逐像素的效果要优于逐顶点。一般来说,最多四个光源可以使用逐像素光照,其他光源就得只使用顶点光照了。

  4. Unity光照实践要点

    • Pass中设置Tags{ "LightMode" = "ForwardBase"}
    • 引用光照的相应头文件 #include "Lighting.cginc"
    • 属性要使用,需要定义对应的变量,变量命名以下划线开头,如_DiffuseColor;
    • 内建变量熟悉 UNITY_MATRIX_MVP UNITY_LIGHTMODEL_AMBIENT _WorldSpaceLightPos0
    • 使用Fallback “Diffuse”
    • 对于平行光,_WorldSpaceLightPos0就是向量,计算光照方向时,不用再减顶点或像素位置
    • 光照在世界空间和模型空间计算有没有区别?没有。 如果嫌法线转世界空间不方便,可以简单的把光照向量转到模型空间来计算。

集中一下上面的链接:
UntiyShader官方文档
MSDN HLSL参考
HLSL内建函数列表
UnityShader语义介绍
MSDN语义介绍文档
UnityShader顶点着色器能输入哪些数据
UnityShader内建文件
UnityShader中的内建函数
UnityShader使用Windows上的VS2012调试
UnityShader数据类型
MSDN HLSL数据类型
《GPU精粹2》

展开阅读全文

没有更多推荐了,返回首页