问题
- 希望使用WebGL透明背景。
- 希望在其他html元素上渲染WebGL内容,并且通过WebGL内容中的透明部分展示 其他html元素。
原因
WebGL画布默认不透明,因为透明度信息没有写入帧缓存中,也就是说当渲染WebGL画布时,它会重写页面下的所有元素。
解决方案
解决方法是重写glClear的实现来跳过Unity清除alpha帧缓存的步骤,把原有的alpha值保留下来,这样就可以实现WebGL的透明。
实现这些,我们需要跟随以下步骤:
- 在资源文件夹下创建一个".jslib"文件,这是一个带有".jslib"扩展的空文本文件,比如可以命名为"TransparentBackground.jslib"。
- 复制并且粘贴以下代码到你创建的文件中:
var LibraryGLClear = {
glClear: function(mask)
{
if (mask == 0x00004000)
{
var v = GLctx.getParameter(GLctx.COLOR_WRITEMASK);
if (!v[0] && !v[1] && !v[2] && v[3])
// We are trying to clear alpha only -- skip.
return;
}
GLctx.clear(mask);
}
};
mergeInto(LibraryManager.library, LibraryGLClear);
- 当你创建工程时,上述代码可以用来代替内置的LibraryGLClear方法。
至此您已经成功创建一个透明的画布,可以看到网站页面后面的内容。
下一步是让着色器把透明度信息写到帧缓存中。需要确认已经使用了"ColorMask RGBA",如果使用表面着色器,Unity可能只使用RGB, 这时候我们需要:
- 在工程视图中选择表面着色器资源。
- 点击"Show generated code"按钮,Unity会打开表面着色器的代码块。
- 复制并保存着色器代码到工程文件的一个新着色器中。
- 把所有ColorMask RGB的实例修改为ColorMask RGBA。
另一个可能发生的问题是alpha通道中写入的三角形可能会重叠。这时,如果背景中物体的alpha值为不透明的话,会被新的alpha值所替换 。这会让原本不透明的物体变成透明物体。为了便于理解,我们可以想象一下渲染一棵由很多通过alpha blend树叶组成的树。其中一些树叶位于另一些树叶前面。由于最后一批树叶会在帧缓存中写入alpha信息,导致背景中其他树叶的alpha信息被替换,从而导致本来应该为不透明的区域显示为透明。
为了避免不透明的像素成为透明,可以将着色器中的阿尔法值设置为源fragment和目标fragment之间的最大值(使用了混合操作),代码如下:
Blend SrcAlpha OneMinusSrcAlpha, One One
BlendOp Add, Max
更多信息
http://docs.unity3d.com/Manual/SL-Pass.html
http://docs.unity3d.com/Manual/SL-Blend.html
http://forum.unity3d.com/threads/webgl-transparent-background.284699/