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(UN