目录:Unity Shader - 知识点目录(先占位,后续持续更新)
原文:Predefined Shader preprocessor macros
版本:2019.1
着色器预处理宏
Unity 编译 shader programs 期间的一些预处理宏。
(本篇的宏介绍随便看看就好,要想深入了解,还是直接看Unity得.cginc代码更好理解,主要看看不是宏介绍的其他内容)
目标平台
宏 | 目标平台 |
---|---|
SHADER_API_D3D11 | Direct3D 11 |
SHADER_API_GLCORE | 桌面版OpenGL “core” (GL 3/4) |
SHADER_API_GLES | OpenGL ES 2.0 |
SHADER_API_GLES3 | OpenGL ES 3.0/3.1 |
SHADER_API_METAL | iOS/Mac Metal |
SHADER_API_VULKAN | Vulkan |
SHADER_API_D3D11_9X | Universal Windows Platform(UWP平台) Direct3D 11 “feature level 9.x” |
SHADER_API_PS4 | PlayStation 4.也会定义 SHADER_API_PSSL |
SHADER_API_XBOXONE | Xbox One |
SHADER_API_MOBILE 为常用的移动平台定义(GLES,GLES3,METAL)。
另外,SHADER_TARGET_GLSL 定于在着色器语言为GLSL的平台(对 OpenGL/GLES 平台来说该宏都会定义)。
着色器目标模型
SHADER_TARGET 使用一个数值来定义编译着色器模型(与 #pragma target 指令匹配)。如,当你的编译Shader model 3.0 的着色器,对应 SHADER_TARGET 为 30。你可以使用着色器代码来判断,例如:
#if SHADER_TARGET < 30
// 比 shader model 3.0 底的版本
// 限制很大的着色器兼容处理
#else
// 硬件支持,则可以处理更好的方式
#endif
Unity 版本
UNITY_VERSION 包含了Unity版本的数值。例如,UNITY_VERSION 为 501 对应着Unity 5.0.1。着可以用于版本比较,如果你需要在编写shader是需要使用不同unity版本的内置功能。例如,一个 #if UNITY_VERSION >= 500 的预处理检测,仅能在Unity 版本是5.0.0或是更高版本才行。
着色器编译阶段
预处理宏 SHADER_STAGE_VERTEX,SHADER_STAGE_FRAGMENT,SHADER_STAGE_DOMAIN,SHADER_STAGE_HULL,SHADER_STAGE_GEOMETRY,SHADER_STAGE_COMPUTE 将会在编译每个Shader阶段时被定义。通常将像素着色器和计算着色器共享着色器代码是,会很有用,这样可以处理一个稍微不太一样的情况。
平台差异的辅助
不鼓励直接使用这些平台宏,因为它们并不总是有助于代码的未来验证。例如,如果您正在编写一个用于检查D3D11的着色器,您可能想要确保在将来,该检查将扩展到包含Vulkan。那么我们推荐使用Unity定义了的几个helper宏(在HLSLSupport.cginc中):
宏 | 使用 |
---|---|
UNITY_BRANCH | 将其添加到条件语句之前,以告诉编译器应该将其编译成实际的分支。在HLSL平台上该宏会替换为[branch]。 |
UNITY_FLATTEN | 在条件语句之前添加这个语句,告诉编译器应该将其平铺以避免实际的分支指令。在HLSL平台上该宏会替换为[flatten]。 |
UNITY_NO_SCREENSPACE_SHADOWS | 定义在不使用级联屏幕空间阴影贴图(移动平台)的平台上。 |
UNITY_NO_LINEAR_COLORSPACE | 定义在不支持线性颜色空间的平台(移动平台)上。 |
UNITY_NO_RGBM | 定义在不使用RGBM压缩光映射的平台(移动平台)上。 |
UNITY_NO_DXT5nm | 定义在不使用DXT5nm标准映射压缩(移动平台)的平台上。 |
UNITY_FRAMEBUFFER_FETCH_AVAILABLE | 定义在"framebuffer color fetch"功能可用的平台上(通常是iOS平台——OpenGL es2.0、3.0和Metal)。 |
UNITY_USE_RGBA_FOR_POINT_SHADOWS | 定义在平台上,点光源阴影贴图使用RGBA纹理编码的深度(其他平台使用单通道浮点纹理)。 |
UNITY_ATTEN_CHANNEL | 定义包含数据的光衰减纹理通道;用于逐像素照明代码。定义为“r”或“a”。 |
UNITY_HALF_TEXEL_OFFSET | 定义在要半texel偏移调整映射到像素的texel(如Direct3D 9)。 |
UNITY_UV_STARTS_AT_TOP | 总是用值1或0来定义。值为1时,代表在纹理V坐标(纹理顶部)为0。类direct3d平台使用值为1(纹理顶部为0);类opengl平台使用0值(纹理顶部为1)。 |
UNITY_MIGHT_NOT_HAVE_DEPTH_Texture | 定义平台是否可以通过手动将深度呈现到纹理中来模拟阴影映射或深度纹理。 |
UNITY_PROJ_COORD(a) | 给定一个4分量向量,它返回一个适合于投影纹理读取的纹理坐标。在大多数平台上,这将直接返回传入参数的值。 |
UNITY_NEAR_CLIP_VALUE | 定义为近切面的值。direct3d平台使用0.0,opengl平台使用-1.0。 |
UNITY_VPOS_TYPE | 定义像素位置输入(VPOS)所需的数据类型:D3D9上的float2,其他地方的float4。 |
UNITY_CAN_COMPILE_TESSELLATION | 当着色器编译器可用曲面细分着色器HLSL语法(目前只有D3D11)时定义。 |
UNITY_INITIALIZE_OUTPUT(type,name) | 将给定类型的变量名初始化为零。 |
UNITY_COMPILER_HLSL,UNITY_COMPILER_HLSL2GLSL,UNITY_COMPILER_CG | 指示使用哪个着色器编译器编译着色器——分别是:Microsoft的HLSL、HLSL到GLSL转换器和NVIDIA的Cg。有关更多细节,请参阅有关 shading Languages 的文档。如果您遇到处理编译器之间差异的非常特殊的着色器语法,并且希望为每个编译器编写不同的代码,那么可以使用这种方法。 |
UNITY_REVERSED_Z | 定义在使用反向Z缓冲区的平台。存储的Z值在范围1…0而不是0…1。 |
阴影映射宏
定义与采样阴影贴图,在不同平台差别很大。Unity有一些宏可以辅助处理:
宏 | 使用 |
---|---|
UNITY_DECLARE_SHADOWMAP(tex) | 声明一个名为“tex”的阴影贴图纹理变量。 |
UNITY_SAMPLE_SHADOW(tex,uv) | 采样阴影贴图纹理“tex”在给定的“uv”坐标下(XY分量为纹理位置,Z分量为纹理深度用于比较)。返回float作为阴影因子0到1范围。 |
UNITY_SAMPLE_SHADOW_PROJ(tex,uv) | 与上面类似,但是可以读取投影阴影映射。“uv”是一个float4,所有其他组件都除以.w进行采样。 |
注意:不是所有的显卡都支持shaodwmaps。使用 SystemInfo.SupportsRenderTextureFormat 来检测支持与否。
常量缓存宏
Direct3D 11将所有着色器变量分组到"constant buffers"(常量缓冲区)中。多数Unity内置变量都已分类号了,但对于你自己的shader变量,根据更新的预期频率,最理想的还是将它们划分到constant buffers中。
使用 CBUFFER_START(name) 和 CBUFFER_END 宏:
CBUFFER_START(MyRarelyUpdatedVariables)
float4 _SomeGlobalValue;
CBUFFER_END
纹理/采样器的宏定义
通常你使用 texture2D 在shader代码中成对定义一张纹理和采样器。然而某些平台(如:DX11),纹理和采样器都是对立的对象,且最大可采样器数量是非常有限的。Unity的一些宏定义了纹理,而没定义采样器,而采样一张纹理使用的采样器是来自另一种纹理的采样器。如果您最终遇到了采样器限制,并且您知道您的几个纹理实际上可以共享一个采样器(采样器定义纹理过滤和循环模式),那么可以使用这个功能。
宏 | 使用 |
---|---|
UNITY_DECLARE_TEX2D(name) | 声明一个纹理和采样器对。 |
UNITY_DECLARE_TEX2D_NOSAMPLER(name) | 声明一个没有采样器的纹理。 |
UNITY_DECLARE_TEX2DARRAY(name) | 声明一个纹理数组采样器变量。 |
UNITY_SAMPLE_TEX2D(name,uv) | 使用给定的纹理坐标从纹理和采样器对中采样。 |
UNITY_SAMPLE_TEX2D_SAMPLER(name,samplername,uv) | 使用来自另一个纹理的samplername采样器来采样指定name纹理。 |
UNITY_SAMPLE_TEX2DARRAY(name,uv) | 使用float3 UV从纹理数组中提取样本;坐标的z分量是数组元素索引。 |
UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod) | 直接指定mipmap级别采样纹理数组。 |
了解更多相关信息,查看文档 Sampler States。
表面着色器pass的指示器
当Surface Shader被编译后,它们将生成许多不同的处理光照的pass代码。当编译每个pass,下面的宏列表中会有其一会变定义:
宏 | 使用 |
---|---|
UNITY_PASS_FORWARDBASE | 正向渲染基础的PASS(主方向光,光照贴图,SH(球谐采样))。 |
UNITY_PASS_FORWARDADD | 前向渲染叠加的PASS(每个光源有效时都将执行一次该PASS)。 |
UNITY_PASS_DEFERRED | 延迟着色的PASS(渲染到G BUFFER)。 |
UNITY_PASS_SHADOWCASTER | 阴影投影和深度纹理渲染的PASS。 |
UNITY_PASS_PREPASSBASE | 旧版本的延迟照明的基础PASS(渲染法线和高光指数)。 |
UNITY_PASS_PREPASSFINAL | 旧版本的延迟照明最终调整色调的PASS(应用于灯光和纹理)。 |
禁止自动更新
UNITY_SHADER_NO_UPGRADE 允许你禁止Unity自动更新或修改你的shader文件。
另请参阅