在Unity3D shader中使用光照贴图数据【翻译】


请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com

原文地址

在Unity3D中创建一个用来接收光照图数据的shader要比你所想象的要难,这个shader的代码在这里。下面是做这个工作时的要特别注意的三个小贴士:

1 surface shader是无效(不能用来接收光照图数据)的

要接收光照图数据,首先要确定的是不能使用U3D独有的表面着色器,而是要直接用Cg代码写顶点和片元着色器。即使U3D的ShaderLab语言看起来和标准的Cg语言语法不大一样,但它还是能正常工作。这是因为在U3D里面,surface shader最终还是会展开成Cg代码编写的顶点和片元着色器。而当这些ShaderLab代码被展开的时候,一些必要的光照图变量便不易察觉地自动地“为你而设置了”。因为这个原因,当你试图去访问这些这些变量时,尤其是在代码展开阶段(expansion step),你会得到一个“未定义这些变量”的编译错误。当最后的编译shader代码的时候,你会得到一个“重复定义这些变量”的错误。

2 U3D的内置变量unity_LightmapST是一个不合法的变量名字

另一个细节则是你必须使用正确的变量。这些变量是U3D引擎用来传递光照贴图数据的。它们是:

sampler2D unity_Lightmap;
float4 unity_LightmapST;

第二个变量用来管理光照贴图图集数据(lightmaps atlas data)。它的名字很重要,原因是它的命名规则是不正确的!(译注:Unity3D的bug?)在一般情况下,带有_ST后缀名的变量,将会由Unity根据该变量所绑定的shader property的图集,自动地传递赋值(populate)过去。现在这个变量漏了下划线了,因为一个非常有用的用来进行变换操作的宏,导致这个遗漏成了一个大问题。该宏是在UntiyCG.cginc文件中定义的TRANSFORM_TEX。代码如下:

#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)

如代码所示,在这个宏里面,变量名是需要加下划线的,所以必须仿照这个宏的定义,去手写一遍,代码如下:

o.uv1 = i.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;

UnityCG.cginc文件包含了大量的便于开发的函数,完成这个工作需要用到里面的函数,所以需要在代码中包含这个文件,如下:

#include "UnityCG.cginc"

3 使用Unity3D提供的光照图解码函数

最后一个重要的步骤便是对光照贴图数据进行正确的解码。在不同的平台上解码方式有所不同,但U3D已经在UnityCG.cginc文件中提供了DecodeLightmap函数完成这功能,代码如下:

// Decodes lightmaps:
// doubleLDR encoded on GLES
// RGBM encoded with range [0;8] on other platforms using surface shaders
inline fixed3 DecodeLightmap(fixed4 color)
{
#if defined(SHADER_API_GLES) && defined(SHADER_API_MOBILE)
    return 2.0 * color.rgb;
#else
    return (8.0 * color.a) * color.rgb;
#endif
}

这个函数将在片元着色器中,对传递进来的光照贴图颜色数据,即参数color,依据不同的目标平台,进行转换,并且输出一个带有四个分量的颜色值。

返回首页