(一)unity自带的着色器源码剖析之——————UnityShaderVariables.cginc文件

unityShaderVariables.cginc文件中包含大量的工具宏和函数,如变换操作用的矩阵、与摄像机相关的函数、与光照和阴影相关的函数,以及与雾效果相关的函数等。下面依次分析这些工具函数和宏。

 

一、进行变换操作用的矩阵

1.1 判断 USING_DIRECTIONAL_LIGHT宏是否定义并分析与立体渲染相关的宏

代码段如下,从第3行开始,14行结束:

#ifndef UNITY_SHADER_VARIABLES_INCLUDED
#define UNITY_SHADER_VARIABLES_INCLUDED

#include "HLSLSupport.cginc"

#if defined (DIRECTIONAL_COOKIE) || defined (DIRECTIONAL)
#define USING_DIRECTIONAL_LIGHT
#endif
//           是否启用了单程立体渲染              判断立体多例化支持宏是否启用
#if defined(UNITY_SINGLE_PASS_STEREO) || defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
#define USING_STEREO_MATRICES
#endif

在上面代码中,首先根据单程立体渲染(single pass stereo rendering)相关的预处理宏UNITY_SINGLE_PASS_STEREO、立体多例化渲染(stereo instancing rendering)预处理宏UNITY_STEREO_INSTANCING_ENABLED、多视角立体渲染(multi-view stereo rendering)预处理宏UNITY_STEREO_MULTIVIEW_ENABLED的启用情况决定宏USING_STEREO_MATRICES是否开启。如果上面三个宏有任意一个是开启的,那么宏USING_STEREO_MATRICES即开启,表示要使用与立体渲染相关的矩阵。

立体多例化渲染的预处理宏UNITY_STEREO_INSTANCING_ENABLED是否启用,在HLSLSupport.cginc文件中有定义。这个宏根据另外的预处理宏的设置决定启用与否。立体多例化渲染技术的核心思想是一次向渲染管道上提交两份待渲染的几何体数据,减少绘制调用(draw call)的次数,提升渲染性能。

单程立体渲染是一种高效的支持VR效果的方式,用于PC或者PlayStation4平台上的VR应用。这种技术同时把要显示在左右眼的图像打包渲染进一张可渲染纹理中,这也意味着整个场景只需要渲染一次即可。否则就需要左右眼各渲染一次。此技术将大幅度地提升渲染性能。要使用单程立体渲染,选择Edit | Project Settings | Player选项,在PlayerSetting面板中选择Other Setting选项选中Virtual Reality Supported复选框,然后选中Single-Pass Stereo Rendering复选框便可。设置完毕后,宏UNITY_SINGLE_PASS_STEREO将会被启用。

1.2 和立体渲染相关的一系列矩阵 1

下面代码用于定义一系列与立体渲染相关的矩阵:

#if defined(USING_STEREO_MATRICES)
    #define glstate_matrix_projection unity_StereoMatrixP[unity_StereoEyeIndex]
    #define unity_MatrixV unity_StereoMatrixV[unity_StereoEyeIndex]
    #define unity_MatrixInvV unity_StereoMatrixInvV[unity_StereoEyeIndex]
    #define unity_MatrixVP unity_StereoMatrixVP[unity_StereoEyeIndex]

    #define unity_CameraProjection unity_StereoCameraProjection[unity_StereoEyeIndex]
    #define unity_CameraInvProjection unity_StereoCameraInvProjection[unity_StereoEyeIndex]
    #define unity_WorldToCamera unity_StereoWorldToCamera[unity_StereoEyeIndex]
    #define unity_CameraToWorld unity_StereoCameraToWorld[unity_StereoEyeIndex]
    #define _WorldSpaceCameraPos unity_StereoWorldSpaceCameraPos[unity_StereoEyeIndex]
#endif

在上面的代码段中,出现了带有unity_Stereo前缀命名数组变量,如unity_StereoMatrixV等,以及用来索引数组的索引值变量unity_StereoEyeIndex,然后用一个#define把带有"unity_Stereo"的变量名替换成unity_前缀即可。

1.3 和立体渲染相关的一系列矩阵 2

带有unity_Stereo前缀的变量和unity_StereoEyeIndex也定义在UnityShaderVariables.cginc文件中,如以下代码所示。

#if defined(USING_STEREO_MATRICES)
GLOBAL_CBUFFER_START(UnityStereoGlobals)
    float4x4 unity_StereoMatrixP[2];   //每个眼镜的投影矩阵
    float4x4 unity_StereoMatrixV[2]; //左、右眼的观察矩阵
    float4x4 unity_StereoMatrixInvV[2];//左、右眼的观察矩阵的逆矩阵
    float4x4 unity_StereoMatrixVP[2]; //左、右眼的观察矩阵与投影矩阵的乘积

    float4x4 unity_StereoCameraProjection[2];  //摄像机的投影矩阵
    float4x4 unity_StereoCameraInvProjection[2]; //摄像机的投影矩阵的逆矩阵
    float4x4 unity_StereoWorldToCamera[2];   //从世界空间变换到摄像机观察空间的矩阵
    float4x4 unity_StereoCameraToWorld[2];  //从摄像机观察空间变换到世界空间的矩阵

    float3 unity_StereoWorldSpaceCameraPos[2]; //摄像机在世界空间中的坐标值
	//进行单程立体渲染时,和普通渲染不同,并不是直接把渲染效果写入对应屏幕的颜色缓冲区,而是把渲染结果写入对应于
	//左右眼的两个图像(image)中,然后把两个图像合并到一张可渲染纹理中再显示。
	//变量unity_StereoScaleOffset维护了把两个图像合并进一张纹理中要用到的平铺值(tiling)和偏移值(offset)
    float4 unity_StereoScaleOffset[2];
GLOBAL_CBUFFER_END
#endif

#if defined(USING_STEREO_MATRICES) && defined(UNITY_STEREO_MULTIVIEW_ENABLED)
GLOBAL_CBUFFER_START(UnityStereoEyeIndices)
    float4 unity_StereoEyeIndices[2];
GLOBAL_CBUFFER_END
#endif
//如果启用了多视角立体渲染,unity_StereoEyeIndex的值就是UNITY_VIEWID
//而UNITY_VIEWID的值就是gl_viewID值(HLSLSupport.cginc文件中定义)
#if defined(UNITY_STEREO_MULTIVIEW_ENABLED) && defined(SHADER_STAGE_VERTEX)
//把立体渲染的左右眼索引值变量定义别名为UNITY_VIEWID
    #define unity_StereoEyeIndex UNITY_VIEWID
    UNITY_DECLARE_MULTIVIEW(2);
//如果启用了立体多实例化渲染,定义一个静态的当前使用的眼镜索引
//此值在编译期间要明确指定,运行时不可改变
#elif defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
    static uint unity_StereoEyeIndex;
//如果启用的是单程立体渲染,把索引值定义为int类型,并且是作为一个着色器常用缓冲区中定义的变量,也即可以由CPU在运行期传递
//具体的数值去改变当前使用的眼睛索引
#elif defined(UNITY_SINGLE_PASS_STEREO)
    GLOBAL_CBUFFER_START(UnityStereoEyeIndex)
        int unity_StereoEyeIndex;
    GLOBAL_CBUFFER_END
#endif

依据不同的编译条件,unity_StereoEyeIndex的定义方式也有所不同,如上面代码所示。此变量表征了当时使用的左右眼索引。

 

1.4 UNITY_DECLARE_MULTIVIEW宏的定义

代码中的UNITY_DECLARE_MULTIVIEW在HLSLSupport.cginc文件中定义,展开如下。

第262行:

#define UNITY_DECLARE_MULTIVIEW(number_of_views) GLOBAL_CBUFFER_START(OVR_multiview) uint gl_ViewID; uint numViews_##number_of_views; GLOBAL_CBUFFER_END

1.5 一系列用来进行变换操作的矩阵

在前面代码段中,如果启用了unity_MatrixInV等一系列变量,就相当于使用了unity_StereoMatrixInvV[unity_StereoEyeIndex]等变量;如果没有启用,那又是什么呢,代码如下所示:

从29行开始,40行结束:

#define UNITY_MATRIX_P glstate_matrix_projection
#define UNITY_MATRIX_V unity_MatrixV
#define UNITY_MATRIX_I_V unity_MatrixInvV
#define UNITY_MATRIX_VP unity_MatrixVP
#define UNITY_MATRIX_M unity_ObjectToWorld

#define UNITY_LIGHTMODEL_AMBIENT (glstate_lightmodel_ambient * 2)

1.6 每一帧由客户端引擎传递进来的逐帧数据

如果没有启用,在HLSL/Cg语言中,unity_MatrixV等变量就直接定义为float4X4 类型的变量,如以下代码所示:

从第214行开始,231行结束:


CBUFFER_START(UnityPerFrame)

    fixed4 glstate_lightmodel_ambient;
    fixed4 unity_AmbientSky;
    fixed4 unity_AmbientEquator;
    fixed4 unity_AmbientGround;
    fixed4 unity_IndirectSpecColor;
	//如果没有使用立体渲染矩阵,unity_MatrixV等矩阵就是一个float4x4 类型的矩阵
#if !defined(USING_STEREO_MATRICES)
    float4x4 glstate_matrix_projection;
    float4x4 unity_MatrixV;         //当前摄像机所对应的观察矩阵(view matrix)
    float4x4 unity_MatrixInvV;
    float4x4 unity_MatrixVP;
    int unity_StereoEyeIndex;
#endif

    fixed4 unity_ShadowColor;
CBUFFER_END

1.7 GLSL中各种变换操作用的矩阵

如果使用GLSL,那么在GLSLsupport.glslinc文件中定义为mat4类型的uniform变量,如以下代码所示:

从第15行开始,20行结束:

uniform mat4 unity_ObjectToWorld;
uniform mat4 unity_WorldToObject;
uniform mat4 unity_MatrixVP;
uniform mat4 unity_MatrixV;
uniform mat4 unity_MatrixInvV;
uniform mat4 glstate_matrix_projection;

在编码实践中,通常会单独使用UNITY_MATRIX_V的单独行来进行操作,如UNITY_MATRIX_V[0]等操作方式。UNITY_MATRIX_V[0]表示当前摄像机在世界坐标系下的朝右(right)方向向量,UNITY_MATRIX_V[1]表示在世界坐标系下的朝上(up)方向向量,UNITY_MATRIX_V[2]则表示在世界坐标系下的朝前方向向量。

二、和摄像机相关的常量缓冲区

2.1 常量缓冲区 UnityPerCamera的定义

从45行开始,第85行结束:

//Unity3D内建的,用来传递给每个摄像机的参数组
//这些参数由引擎从C#层代码传递给着色器

CBUFFER_START(UnityPerCamera)
    // Time (t = time since current level load) values from Unity
	//从载入当前的scene开始算起流逝的时间值,单位是s。其x、y、z、w分量分别对应为1/20流逝时间值、流逝时间值、2倍流逝时间值、三倍流逝时间值
    float4 _Time; // (t/20, t, t*2, t*3)
    //_Time值的正弦值,其x、y、z、w分别对应于1/8的当前流逝时间值的正弦值、1/4的当前流逝时间值的正弦值、1/2的当前流逝时间值的正弦值、当前流逝时间值的正弦值
    float4 _SinTime; // sin(t/8), sin(t/4), sin(t/2), sin(t)
	 //_Time值的余弦值,其x、y、z、w分别对应于1/8的当前流逝时间值的余弦值、1/4的当前流逝时间值的余弦值、1/2的当前流逝时间值的余弦值、当前流逝时间值的余弦值
    float4 _CosTime; // cos(t/8), cos(t/4), cos(t/2), cos(t)
	//本帧到上一帧过去的时间间隔
    float4 unity_DeltaTime; // dt, 1/dt, smoothdt, 1/smoothdt
	//如果没有定义开启单线程立体渲染,没有开启立体多实例化渲染,就由引擎C#层代码传递一个表征当前摄像机在世界空间中的坐标值
#if !defined(USING_STEREO_MATRICES)
    float3 _WorldSpaceCameraPos;
#endif

    // x = 1 or -1 (-1 if projection is flipped)
    // y = near plane
    // z = far plane
    // w = 1/far plane
	//投影矩阵相关的参数,x为1或者-1,y为近截平面值,z为远截平面值,w为远截平面值的倒数
    float4 _ProjectionParams;

    // x = width
    // y = height
    // z = 1 + 1.0/width
    // w = 1 + 1.0/height
	//视口相关的参数,x为视口宽度,y为视口高度,z为1加上视口宽度的倒数,w为1加上视口高度的倒数
    float4 _ScreenParams;

    // Values used to linearize the Z buffer (http://www.humus.name/temp/Linearize%20depth.txt)
    // x = 1-far/near
    // y = far/near
    // z = x/far
    // w = y/far
    // or in case of a reversed depth buffer (UNITY_REVERSED_Z is 1)
    // x = -1+far/near
    // y = 1
    // z = x/far
    // w = 1/far
	//用来线性化Z buffer
	//x分量为1减去视截体远截面值与视椎近截面值的商,y分量为视截体远截面值与视椎近截面值的商,z分量为x分量除以视截体
	//远截面值,w分量为y分量除以视截体远截面值
    float4 _ZBufferParams;

    // x = orthographic camera's width
    // y = orthographic camera's height
    // z = unused
    // w = 1.0 if camera is ortho, 0.0 if perspective

	//x分量为正交投影摄像机的宽度,y分量为正交投影摄像机的高度
	//z分量未使用,w分量当摄像机为正交投影时为1,透视投影为0
    float4 unity_OrthoParams;
#if defined(STEREO_CUBEMAP_RENDER_ON)
    //x-component is the half stereo separation value, which a positive for right eye and negative for left eye. The y,z,w components are unused.
    float4 unity_HalfStereoSeparation;
#endif
CBUFFER_END

2.2常量缓冲区UnityPerCameraRare的定义

通过以下代码定义常量缓冲区UnityPerCameraRare。

从第88行开始,100行结束:

CBUFFER_START(UnityPerCameraRare)
    //当前摄像机视截体(view frustum)的6个截平面的平面表达式。这些平面表达式在世界坐标系下描述。
	//每个平面表达式用方程ax+by+cz+d=0表达。float4中的分量x、y、z、w依次存储了系数a、b、z、d。
	//6个平面依次是左、右、下、上、近、远裁剪平面
    float4 unity_CameraWorldClipPlanes[6];

    //如果不使用立体渲染,各种矩阵变量就是一个单变量而不是两个变量的数组
#if !defined(USING_STEREO_MATRICES)
    // Projection matrices of the camera. Note that this might be different from projection matrix
    // that is set right now, e.g. while rendering shadows the matrices below are still the projection
    // of original camera.

    //当前摄像机的投影矩阵
    float4x4 unity_CameraProjection;
	//当前摄像机的投影矩阵的逆矩阵
    float4x4 unity_CameraInvProjection;
	//当前摄像机的观察矩阵
    float4x4 unity_WorldToCamera;
	//当前摄像机的观察矩阵的逆矩阵
    float4x4 unity_CameraToWorld;
#endif
CBUFFER_END

三、与光照相关的工具函数和内置光源

3.1 变量_WorldSpaceLightPos0的定义

如下,从第106行开始,112行结束:

CBUFFER_START(UnityLighting)
    //如果定义了有向平行光
    #ifdef USING_DIRECTIONAL_LIGHT
	//分量x、y、z存储的是有向平行光的方向向量
    half4 _WorldSpaceLightPos0;
    #else   
	//如果不是有向平行光,那么分量x、y、z存储的是光源在世界空间中的位置坐标
    float4 _WorldSpaceLightPos0;
    #endif

UnityCG.cginc和UnityCG.glslinc文件中的定义UnityWorldSpaceLightDir函数就使用了_WorldSpaceLightPos0变量,计算出某点到光源的连线方向向量。

3.2 4个非重要点光源的位置、衰减值和照射范围

从第114行开始,123行结束:

  //x、y、z分量为光源的位置,w分量为光源照射范围的倒数   
    float4 _LightPositionRange; // xyz = pos, w = 1/range
    float4 _LightProjectionParams; // for point light projection: x = zfar / (znear - zfar), y = (znear * zfar) / (znear - zfar), z=shadow bias, w=shadow scale bias

	//4个光源的x、y、z坐标,注意unity_4LightPosX0中的4个分量分别存储了4个光源的x坐标,unity_4LightPosY0中的4个分量分别存储
	//了4个光源的y坐标,其余类推
    float4 unity_4LightPosX0;
    float4 unity_4LightPosY0;
    float4 unity_4LightPosZ0;
    half4 unity_4LightAtten0;    //4个光源的衰减值

上面代码定义的4个光源,是等级为非重要光源的点光源。这4个光源仅用在前向渲染路径的base pass中。

3.3 8个光源的颜色、位置、衰减值和照射方向

从124行开始,130行结束:

//8个光源的颜色
    half4 unity_LightColor[8];

	//有向光的视图空间顶点光源位置(position,1)或者(-direction,0)
	//在光源空间中用来在顶点着色器中执行顶点光照计算的光源位置点。如果光源是有向平行光,那么变量中的x、y、z分量存储着光源
	//的光照方向的反方向,w分量为0;如果光源是非有向平行光源,那么变量中的x、y、z分量存储着光源的位置坐标,w分量为1

    float4 unity_LightPosition[8]; // view-space vertex light positions (position,1), or (-direction,0) for directional lights.
    // x = cos(spotAngle/2) or -1 for non-spot
    // y = 1/cos(spotAngle/4) or 1 for non-spot
    // z = quadratic attenuation
    // w = range*range

	//对于非点光源x = cos(spotAngle/2)或1
	//对于非点光源y = 1/cos(spotAngle/4)或1
	//z = quadratic attenuation
	//w = range*range
    half4 unity_LightAtten[8];
	//8个光源的正前照射方向,这些方向向量基于观察空间,如果这些光源不是聚光灯光源,都为(0,0,1,0)
    float4 unity_SpotDirection[8]; // view-space spot light directions, or (0,0,1,0) for non-spot

在上述代码段中,变量unity_LightAtten描述了光源的衰减信息:如果光源是聚光灯光源,每一个数组元素的x分量存储着聚光灯1/2张角值的余弦值;如果不是,那么x分量值为-1。z分量存储着衰减值方程式中的二次项系数。w分量存储着光源照射范围的距离值的平方。

据unity3D技术支持工程师介绍,因为一些原因,在unity_LightAtten变量的原有代码注释中,对于y分量的描述其实是错误的。y分量的正确值应该是:聚光灯1/4张角的余弦值减去其1/2张角的余弦值。如果该差值不为0,则y为该差值的倒数,否则为1.

3.4 球谐光照使用到的参数

从第133行开始,139行结束:

 // SH lighting environment
    half4 unity_SHAr;
    half4 unity_SHAg;
    half4 unity_SHAb;
    half4 unity_SHBr;
    half4 unity_SHBg;
    half4 unity_SHBb;
    half4 unity_SHC;

3.5 和光照探针相关的参数

从第142行开始,144行结束:

    // part of Light because it can be used outside of shadow distance
    fixed4 unity_OcclusionMaskSelector;
    fixed4 unity_ProbesOcclusion;
CBUFFER_END

四、与阴影相关的着色器常量缓冲区

UnityShadows着色器常量缓冲区

从第153行开始,162行结束:

CBUFFER_START(UnityShadows)
    //用于构建层叠式阴影贴图时子视截体用到的包围球
    float4 unity_ShadowSplitSpheres[4];
    //unity_ShadowSplitSpheres中4个包围球半径的平方
    float4 unity_ShadowSplitSqRadii;
    float4 unity_LightShadowBias;
    float4 _LightSplitsNear;
    float4 _LightSplitsFar;
	//把某个坐标点从世界空间变换到阴影贴图空间,如果使用层叠式阴影贴图
	//把数组各元素就表征4个阴影贴图各自所对应的阴影贴图空间
    float4x4 unity_WorldToShadow[4];
    half4 _LightShadowData;
    float4 unity_ShadowFadeCenterAndType;
CBUFFER_END

unity_ShadowSplitSpheres数组用于构建层叠式阴影贴图(cascaded shadow map,CSM)。该数组中的4个元素存储了把当前视截体分割成4个子视截体后,这些子视截体的包围球(bounding sphere)。每个元素中x、y、z、w分量存储包围球的球心坐标和半径。

unity_ShadowSplitSqRadii中的4个分量依次定义unity_ShadowSplitSheres数组对应的4个包围球半径的平方。

unity_LightShadowBias的x分量为产生阴影的光源的光源偏移值乘以一个系数。这个光源偏移值对应于Light面板中的Bias属性。如果聚光灯光源,所乘的系数为1;如果是有向平行光源,所乘系数为投影矩阵的第三行第三列的值的相反数。当光源是聚光灯光源时,y分量是0;当光源是有向平行光源时,为1。z分量为解决阴影渗漏问题时,沿着物体表面法线移动的偏移值。w分量为0。

_LightSplitsNear对应于Shadows面板中的cascade split属性里面,当把视截体分割成最多4个视截体时,每个子视截体的近截平面的z值。

unity_WorldToShadow数组中的每一个元素对应于层叠式贴图中每一个子视截体所对应的阴影贴图,存储了从世界坐标变换到阴影贴图空间中的变换坐标。

_LightShadowData中x分量表示阴影的强度,即阴影有多黑,1表示全黑,0表示完全透明不黑;y分量目前暂未被使用;当z分量1除以需要渲染的阴影时,表示阴影离当前摄像机的最远距离值(shadow far distance)。w分量表示阴影摄像机的最近距离值(shadow near distance)。

五、与逐帧绘制调用相关的着色器常量缓冲区

Unity3D引擎预定义了和逐帧绘制调用相关的着色器常量UnityPerDraw。从166行开始,171行结束:

CBUFFER_START(UnityPerDraw)
    //把顶点从局部空间变换到世界空间的变换矩阵
    float4x4 unity_ObjectToWorld;
    //把顶点从世界空间变换到局部空间的变换矩阵
    float4x4 unity_WorldToObject;
    float4 unity_LODFade; // x is the fade value ranging within [0,1]. y is x quantized into 16 levels
	//该变量的w分量通常为1,当缩放变量值为负数时,常被引擎赋值为-1。
    float4 unity_WorldTransformParams; // w is usually 1.0, or -1.0 for odd-negative scale transforms
CBUFFER_END

六、与雾效果相关的常量缓冲区

Unity引擎预定了和雾效果渲染相关的着色器常量UnityFog,从236行开始,243行结束:

CBUFFER_START(UnityFog)
     //雾的颜色
    fixed4 unity_FogColor;
    // x = density / sqrt(ln(2)), useful for Exp2 mode 用于雾化因子指数平方衰减
    // y = density / ln(2), useful for Exp mode 用于雾化因子指数衰减
    // z = -1/(end-start), useful for Linear mode 用于雾化因子线性衰减
    // w = end/(end-start), useful for Linear mode 用于雾化因子线性衰减
    float4 unity_FogParams;
CBUFFER_END

雾化效果是一种可添加到最终渲染图像的简单的大气效果(atmosphere effect)。雾化效果可以提供室外场景的真实度;雾化效果随着距离观察者的距离变远而增加,可以帮助观察者确定物体的远近;靠近视截体远平面的物体就会因为浓厚的雾效果变得不可见,这样可以避免原本在视截体之外的不可见物体,因为进入视截体就突然变得可见的现象;雾化效果一般由硬件实现,所以很高效。

七、与光照贴图相关的常量缓冲区

7.1 unity_Lightmap变量的声明

从250行开始,252行结束:

// Lightmaps

// Main lightmap
//声明了主光照贴图,该贴图记录了直接照明下的光照信息
UNITY_DECLARE_TEX2D_HALF(unity_Lightmap);
//声明了间接照明所产生的光照信息,因为unity_LightmapInd和unity_Lightmap搭配使用所以不用另外专门声明采样器
// Directional lightmap (always used with unity_Lightmap, so can share sampler)
UNITY_DECLARE_TEX2D_NOSAMPLER_HALF(unity_LightmapInd);

7.2 UNITY_DECLARE_TEX2D_NOSAMPLER宏的定义

UNITY_DECLARE_TEX2D_NOSAMPLER宏在HLSLSupport.cginc文件中定义,依据不同的目标平台,它的定义也不同:

 #if defined(SHADER_API_D3D11) || defined(SHADER_API_XBOXONE) || defined(UNITY_COMPILER_HLSLCC) || defined(SHADER_API_PSSL) || (defined(SHADER_TARGET_SURFACE_ANALYSIS) && !defined(SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER))

    #define UNITY_DECLARE_TEX2D_NOSAMPLER(tex) Texture2D tex

#else
     #define UNITY_DECLARE_TEX2D_NOSAMPLER(tex) sampler2D tex

7.3 unity_ShadowMask变量的定义

从254行开始,261行结束:

UNITY_DECLARE_TEX2D(unity_ShadowMask);

使用Unity_DECLARE_TEX2D宏直接定义一个名为unity_ShadowMask的纹理贴图,定义一个名为samplerunity_ShadowMask的samplerState。

7.4 和全局照明光照贴图相关的变量

从264行开始,271行结束:

// Dynamic GI lightmap
UNITY_DECLARE_TEX2D(unity_DynamicLightmap);
UNITY_DECLARE_TEX2D_NOSAMPLER(unity_DynamicDirectionality);
UNITY_DECLARE_TEX2D_NOSAMPLER(unity_DynamicNormal);

CBUFFER_START(UnityLightmaps)
    //对应于静态光照贴图变量unity_Lightmap,用于tiling和offset操作。
    float4 unity_LightmapST;
    //对应于动态(实时)光照贴图变量unity_DynamicLightmap,用于tiling和offset操作
    float4 unity_DynamicLightmapST;
CBUFFER_END

7.5 与反射探针相关的着色器变量

从277行开始,290行结束:

// Reflection Probes

UNITY_DECLARE_TEXCUBE(unity_SpecCube0);
UNITY_DECLARE_TEXCUBE_NOSAMPLER(unity_SpecCube1);

CBUFFER_START(UnityReflectionProbes)
    //反射探针的作用区域立方体是一个和世界坐标系坐标轴轴对齐的包围盒
	// unity_SpecCube0_BoxMax的x、y、z分量存储了该包围盒在x、y、z轴方向上的最小边界值
	//它的值由反射探针的Box Size属性和Box Offset属性计算而来
    float4 unity_SpecCube0_BoxMax;
    // unity_SpecCube0_BoxMax的x、y、z分量存储了该包围盒在x、y、z轴方向上的最小边界值
    float4 unity_SpecCube0_BoxMin;
	//对应于Reflection组件中的探针位置,它由Transform组件的Position属性和Box Offset属性计算而来
    float4 unity_SpecCube0_ProbePosition;
	//反射探针使用的立方体贴图中包含高动态范围颜色,它允许它包含大于1的亮度值,在渲染时要将HDR值转为RGB值
    half4  unity_SpecCube0_HDR;

    float4 unity_SpecCube1_BoxMax;
    float4 unity_SpecCube1_BoxMin;
    float4 unity_SpecCube1_ProbePosition;
    half4  unity_SpecCube1_HDR;
CBUFFER_END

UNITY_DECLARE_TEXCUBE宏在HLSLSupport.cginc文件中定义,用来声明一个立方体贴图变量。并且如果当前是运行在Direct3D 11或者XBoxOne平台上,此宏还对应立方体贴图变量声明一个采样器变量。而UNITY_DECLARE_TEXCUBE_NOSAMPLER宏则是一个不声明采样器变量的版本。

 

 

你可能感兴趣的:(游戏开发,unity,Shader,unity内置着色器源码剖析,unity内置着色器源码剖析,unity,Shader,游戏开发)