接到一个需求,将屏幕里除指定物件之外的东西都灰度化,指定物件显示正常颜色。
因为现在场景、人物还有光效可能用各种shader,所以灰度化放在后处理实现。
现在需要将指定物件排除在后处理之外,想到的办法是后处理之后再将彩色物体再渲染一遍。
再画一遍目前试过的方法
1、对于彩色物体新建CommandBuffer,m_commandBuffer.ClearRenderTarget(true, false, Color.clear)清空深度后新建DrawRenderer指令,在CameraEvent.AfterImageEffects绘制,取消功能时移除。
2、对于彩色物体新建CommandBuffer,在后处理OnRenderImage函数中,在灰度后处理之后先清空深度GL.Clear(true, false, Color.clear);在用指令绘制Graphics.ExecuteCommandBuffer(cmdb);
3、在后处理OnRenderImage函数中,后处理之后,清空深度,先用renderer.material.SetPass(0);再用Graphics.DrawMeshNow(mesh.mesh, renderer.localToWorldMatrix)指令绘制.
注意:
1、在OnRenderImage中绘制的深度已经不适用,不清空的话会出现被遮挡的现象。
2、光照信息unity_LightmapST,_LightColor0,_WorldSpaceLightPos0会保留最后一个绘制的参数,绘制彩色物体的时候会沿用最后一个带有光照信息的灰度物体的光照信息,所以颜色会出错。目前解决办法:对于unity_LightmapST,在CommandBuffer建立时用m_commandBuffer.SetGlobalVector("unity_LightmapST", render.lightmapScaleOffset)记录和回复。对于光照颜色和位置,将彩色物体绘制顺序调到最后render.material.renderQueue = 4999;则在后处理时会沿用此光照信息,但此方法限制所有彩色物体必须用的一样的光照位置和光照颜色。
3、KeyWord也会继承后面的,LIGHTMAP_ON影响比较大,m_commandBuffer.EnableShaderKeyword记录下来单独加上去。
存在问题:
清空深度之后彩色物体会始终绘制在灰色物体前面。在后处理过程中绘制彩色物体是得到的深度信息已经不是已绘制物体的深度信息(好像是统一的一个值?)。可能的方案:
1、将depthBuffer取到某个Texture中。目前深度信息好像用Camera.DepthMode也只能供shader读取),用shader绘制到纹理上,再将纹理设置为RenderTexture.depthBuffer?
2、在后处理前,彩色物体绘制的时候,将考虑深度的物件绘制到纹理上。目前绘制到Camera上是有遮挡的,但是将RenderTexture设置为Graphics.SetRenderTarget的RenderTarget的时候,其他物体的深度就没了。最后还需要在后处理的时候将前面绘制好的纹理合并到后处理之后的纹理中。