最近阅读了基于模型的体积云.的相关博客,做个总结吧。大体的思路比较简单,根据模型自身的mesh,在把顶点向法线方向外扩。多次绘制mesh,每次多扩一点距离。根据扩散次数,进行clip。优点是性能消耗低,可以任意塑形,缺点是为了clip掉边缘的一些面片,采用了一个简单的抖动来修改clip的参数。边界处效果仍然不好。。
一:多次绘制
在脚本端,设置material所需的参数。
for (int i = 0; i < DrawCount; ++i)
{
offsets[i] = (GetOffset(i));
alphaClips[i] = (GetAlphaClip(i));
matrices[i] =(transform.localToWorldMatrix);
}
propertyBlock.SetFloatArray("_VertOffset", offsets);
propertyBlock.SetFloatArray("_AlphaClip", alphaClips);
Graphics.DrawMeshInstanced(cloudMesh, 0, cloudMaterial, matrices, DrawCount, propertyBlock);
在shader中,需要进行如下操作
#pragma multi_compile_instancing
UNITY_VERTEX_INPUT_INSTANCE_ID // appdata & v2f
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float, _VertOffset)
UNITY_DEFINE_INSTANCED_PROP(float, _AlphaClip)
UNITY_INSTANCING_BUFFER_END(Props)
//在顶点着色器中
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v,o);
//在片元着色器中
UNITY_SETUP_INSTANCE_ID(i);
//访问属性
UNITY_ACCESS_INSTANCED_PROP(Props, _AlphaClip);
在勾选gpu instancing后,可以看到只有一个draw call,而这次draw call中我们对同一个mesh绘制了数十次。
二:透明云层
在shader中,设置为透明队列。同时开启深度写入。
在脚本中,设置相机的颜色缓冲和zbuffer
private void OnPreRender() {
_Camera.SetTargetBuffers(ColorBuffer.colorBuffer, ZBuffer.depthBuffer);
}
初始化时,通过CommandBuffer,设置相机在BeforeForwardAlpha时,复制颜色和深度缓冲。在AfterForwardAlpha时,再次复制颜色和深度缓冲。在OnPostRender时,调用mixShader,根据深度对颜色进行lerp。
因为在处理颜色时,需要一些经验参数。。我比较懒就没仔细搞。。还是恬不知耻的放个图吧。。