实现特效,尤为是一些后处理特效,常常须要将各物体的shader替换为另外一套shader进行渲染到纹理,再后再进行合成或以某种叠加方式叠加到最后的画面上去。html
再复杂一点儿的,可能不一样的物体所用的替换shader还不同。ide
unity中Camera.RenderWithShader可实现这个功能。函数
下面是官方文档原话:ui
Some rendering effects require rendering a scene with a different set of shaders. For example, good edge detection would need a texture with scene normals, so it could detect edges where surface orientations differ. Other effects might need a texture with scene depth, and so on. To achieve this, it is possible to render the scene with replaced shaders of all objects.this
Shader replacement is done from scripting using Camera.RenderWithShader or Camera.SetReplacementShader functions. Both functions take a shader and a replacementTag.spa
It works like this: the camera renders the scene as it normally would. the objects still use their materials, but the actual shader that ends up being used is changed:.net
So if all shaders would have, for example, a “RenderType” tag with values like “Opaque”, “Transparent”, “Background”, “Overlay”, you could write a replacement shader that only renders solid objects by using one subshader with RenderType=Solid tag. The other tag types would not be found in the replacement shader, so the objects would be not rendered. Or you could write several subshaders for different “RenderType” tag values. Incidentally, all built-in Unity shaders have a “RenderType” tag set.3d
其中最须要理解的是replacementTag,上面文档详细叙述了replacementTag的逻辑,为了好理解,下面换种说法从新解释一遍:orm
*假设脚本中调用 GetComponent<Camera>().RenderWithShader(Shader.Find("shaderX"), ""),则此摄像机本次渲染的全部物体都会使用shaderX进行渲染。htm
*假设脚中中调用 GetComponent<Camera>().RenderWithShader(Shader.Find("shaderX"), "myReplacementTag"),则对于本次要渲染的每一个物体object(i),假设object(i)自己的shader是shader(i),若是shader(i)的全部subShader都不带"myReplacementTag"标签,则object(i)不渲染;若是shader(i)中的subShader(j)带有"myReplacementTag"标签,设此标签为"myReplacementTag"="A",则unity会去shaderX中找"myReplacementTag"="A"的subShader,若是找到了,则用shaderX的此subShader替换object(i)的原有shader;不然object(i)不渲染。
须要指出的是,"myReplacementTag"应该老是用"RenderType",缘由是unity内置的全部shader都带有RenderType标签。
举两个例子:
例1,将全部的不透明物体shader替换为另外一种shader进行渲染:
写一个shaderX,让其中包含一个带"RenderType"="Opaque"标签的subShader,
调用GetComponent<Camera>().RenderWithShader(Shader.Find("shaderX"), "RenderType");
例2,将全部不透明物体shader替换为一种subShader进行渲染,同时将全部透明物体shader替换为另外一种shader进行渲染:
写一个shaderX,让其中包含一个带“RenderType”="Opaque"标签的subShader,再写一个带"RenderType"="Transparent"标签的subShader,
调用GetComponent<Camera>().RenderWithShader(Shader.Find("shaderX"), "RenderType");
例3,将全部“RenderType”=“myRenderType”的物体的shader替换为另外一种shader进行渲染:
写一个shaderX,让其中包含一个带"RenderType"="myRenderType"标签的subShader,
调用GetComponent<Camera>().RenderWithShader(Shader.Find("shaderX"), "RenderType");
另外,关于Camera.RenderWithShader与Camera.SetReplacementShader的区别:
Camera.RenderWithShader只是本次渲染使用替换的shader;Camera.SetReplacementShader是自调用起之后都使用替换的shader进行渲染,直到手动调用Camera.ResetReplacementShader为止,恢复为用自己的shader进行渲染。参考;http://m.blog.csdn.net/blog/QUAN2008HAPPY/39380463
另外在Camera.RenderWithShader的官方文档中写道:
This is used for special effects, e.g. rendering screenspace normal buffer of the whole scene, heat vision and so on. To make use of this feature, usually you create a camera and disable it. Then call RenderWithShader on it.
也就是说,在使用RenderWithShader实现特效时一般应该将调用RenderWithShader这个函数的相机设为disable,即:GetComponent<Camera>().enabled = false,或者也能够直接在Inspector中将Camera组件前的对勾去掉,是同样的效果