天天看点

Shader预处理宏、内置状态变量、多版本编译等

预定义shader预处理宏:

  Target platform:

  Surface shader pass indicators:

内置全局状态变量:

  内置的矩阵:

  内置的向量:

  光照相关的:

  变量:

  内置光照参数:

  对于不同的Rendering Path和Pass Tag,可以使用的光照参数是不一样的。(当然所有参数你都可以在shader中使用,但并不能保证其一定会存储有效的值)。

  Forward rendering(ForwardBase和PorwardAdd标记的pass)支持的变量:

  说明:

  (1)_LightColor0在ForwardBass里面表示:主光,一定是Pixel(Important)、Directional光源,没有的话则改值不可用;

  (2)_LightColor0在ForwardAdd里面表示:当前执行的ForwardAdd的pixel光;

  _WorldSpaceLightPos0的意义和_LightColor类似,也是在Base里表示主光,Add里表示像素光。

  (3)unity_LightColor是距离物体最近的4个point光,也就是说同一个场景中每个物体的这4个光不一样,注意这4个point光的选择非常有意思;

    (a)当shader中没有ForwardAdd Pass的时候,unity_LightColor记录了4盏vertex point光源,无视pixel光;

    (b)当shader中包含ForwardAdd Pass的时候,unity_LightColor记录了4盏point光源,pixel比vertex优先。

  (4)如果场景中有多个pixel光,则对每一个物体,所有的非主光的pixel光都会执行一遍ForwardAdd Pass,按照强度大小、平行光优先的顺序来执行;

  (5)不要在ForwardAdd Pass里面使用unity4LightPosX/Y/Z等数据,因为它们就是给ForwardBase Pass使用的,而且如果其中有pixel光,它们本身就会对ForwardAdd执行一遍;

  (6)可以使用Shade4PointLights函数在ForwardBase中计算Vertex光源的照明。

  Deferred shading:

  Vertex-lit rendering(Vertex标记的pass):

  顶点光照可以使用最多8盏光源,这些光源按照亮度排序,按顺序存储在一下这些数据结构中,如果光源数量少于8,那么多出来的都将黑色:

  (1)_LightColor0表示unity_LightColor[0]

  (2)unity_LightPosition是MV空间中的位置

  (3)逐顶点光照函数float4 ShadeVertexLights(float4 vertex, float3 normal)

  注意:

  (1)_LightColor0变量不代表某个具体含义,它在不同的Render Path和Pass里面是有不同的意义的

  (2)ShaderLab里面的内置变量是不会及时清理的,这是Unity处于性能方面的考虑,因为在CPU和GPU之间频繁传递数据是很耗资源的

  Fog和Ambient环境光信息:

使用multi_compile编译Shader的多个版本:

  有时候我们希望保留一个shader的大多数实现,而只是做一些细节的修改,此时我们就可以通过该方式来生成shader的多个版本,然后在代码中控制使用哪个版本。

  命令:

  #pragma multi_compile FANCY_STUFF_OFF FANCY_STUFF_ON

  控制:

  Material.EnableKeyword(keyword: string)/DisableKeyword(keyword: string)

  Shader.EnableKeyword(keyword: string)/DisableKeyword(keyword: string)

  在shader中根据定义好的关键字处理具体显示方案:

  注意不要在shader中大量使用此命令,因为关键字的个数是有上限的,而多条multi_complie会交叉匹配产生很多种结果。

GLSL shader编程

  在Shader中,除了Cg/HLSL以外,GLSL(OpenGL Shading Languate)也可以直接使用。

  一般不建议使用GLSL,除非你确定你的目标平台只有Max OS X或兼容OpenGL ES 2.0的移动设备。

  Unity默认都会将Cg/HLSL交叉编译出优化过得GLSL,以此来支持多平台。在desktop平台下可以通过打开#pragma glsl选项来支持。

平台特性相关的渲染差异:

  Unity封装了大多数的平台问题,但有些时候还是需要自己处理一下的。

  纹理坐标:

  Direct3D里面是左上角为原点;

  OpenGL和OpenGL ES是左下角为原点。

  多数时候都ok,除了在Render To Texture时。但是在RTT时,Unity对于D3D平台会自动将渲染的贴图上下翻转一下,以此隐藏了各平台的差异。

  D3D平台下,有一种情况不需要Unity自动翻转渲染贴图,那就是使用Image Effects和Anti-Aliasing时,因为直接渲染到Screen了,

  需要手动处理的情况:但同时使用screen texture和RenderTexture时,有可能会得到不一致的坐标朝向,此时就需要在shader里面通过代码处理了:

  AlphaTest:

  在OpenGL ES 2.0和Direct3D 11中,没有alpha testing的固定函数。所以在编写programmable shader时,建议在pixel shader中使用CG/HLSL clip()函数来替代。

  D3D 11 shader编译器比较挑剔:

  D3D 9和OpenGL使用NVIDIA的Cg来编译shader,但D3D 11使用微软的HLSL来编译,此时就会产生一些差异化。

  OpenGL ES 2.0只支持部分GLSL原生的东西,所以Unity实现了一些内置的参数,让其以OpenGL的方式工作,但是也有一些参数是没有的。

CSDN博客:http://blog.csdn.net/candycat1992/article/details/47284289

继续阅读