Unity后期渲染指定的物体
在后期渲染过程中,难免会遇到需要对指定物体进行后期渲染,下面事我参考HightlightingEffect插件整理的针对特定物体做后期的渲染方式。基本思路:
- 创建一个相机ACamera通过Layer来渲染指定Layer的物体,主相机这对这些物体就不需要渲染.
- 创建一个RenderTexture去取ACamera通过引擎渲染管线输出的RenderTexture 。
- 在主相机的后期处理函数中(这里我选择了主相机下挂载脚本中的 void OnRenderImage(RenderTexture source, RenderTexture destination)函数)。
- 主相机通过引擎渲染管线道得到的source和ACamera 输出的RenderTexture做相应的颜色处理后输出到屏幕.
Unity引擎的脚本生命流程
参考脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TargetObjectsBloom : MonoBehaviour
{
[SerializeField]
RawImage rawImage;//将StencilRTT图片通过这个映射到UI上
public Camera refCam;
[SerializeField]
private Camera shaderCamera;
[SerializeField]
private RenderTexture stencilBuffer = null;
public int stencilZBufferDepth = 0;
public int _downsampleFactor = 4;
// Blur iterations
public int iterations = 2;
// Blur minimal spread
public float blurMinSpread = 0.65f;
// Blur spread per iteration
public float blurSpread = 0.25f;
// Blurring intensity for the blur material
public float _blurIntensity = 0.3f;
// Blur Shader
private static Shader _blurShader;
private static Shader blurShader
{
get
{
if (_blurShader == null)
{
_blurShader = Shader.Find("Hidden/Highlighted/Blur");
}
return _blurShader;
}
}
// Blur Material
private static Material _blurMaterial = null;
private static Material blurMaterial
{
get
{
if (_blurMaterial == null)
{
_blurMaterial = new Material(blurShader);
_blurMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return _blurMaterial;
}
}
// Compositing Shader
private static Shader _compShader;
private static Shader compShader
{
get
{
if (_compShader == null)
{
_compShader = Shader.Find("Hidden/Highlighted/Composite");
}
return _compShader;
}
}
// Compositing Material
private static Material _compMaterial = null;
private static Material compMaterial
{
get
{
if (_compMaterial == null)
{
_compMaterial = new Material(compShader);
_compMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return _compMaterial;
}
}
// Camera for rendering stencil buffer GameObject
private GameObject shaderCameraGO = null;
// Start is called before the first frame update
void Start()
{
//shaderCamera = GetComponent<Camera>();
if (!shaderCameraGO)
{
shaderCameraGO = new GameObject("HighlightingCamera", typeof(Camera));
shaderCameraGO.GetComponent<Camera>().enabled = false;
shaderCameraGO.hideFlags = HideFlags.HideAndDontSave;
}
if (!shaderCamera)
{
shaderCamera = shaderCameraGO.GetComponent<Camera>();
}
if (shaderCamera != null)
{
shaderCamera.CopyFrom(refCam);
//shaderCamera.projectionMatrix = refCam.projectionMatrix; // Uncomment this line if you have problems using Highlighting System with custom projection matrix on your camera
shaderCamera.cullingMask = (1 << LayerMask.NameToLayer("BB"));//如果自己设置了可以不用写
shaderCamera.rect = new Rect(0f, 0f, 1f, 1f);
shaderCamera.renderingPath = RenderingPath.VertexLit;
shaderCamera.allowHDR = false;
shaderCamera.useOcclusionCulling = false;
shaderCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
shaderCamera.clearFlags = CameraClearFlags.SolidColor;
//清除前一帧的RTT
if (stencilBuffer != null)
{
RenderTexture.ReleaseTemporary(stencilBuffer);
stencilBuffer = null;
}
stencilBuffer = RenderTexture.GetTemporary((int)GetComponent<Camera>().pixelWidth, (int)GetComponent<Camera>().pixelHeight, stencilZBufferDepth, RenderTextureFormat.ARGB32);
shaderCamera.targetTexture = stencilBuffer;
if (rawImage != null)
{
rawImage.texture = stencilBuffer;
}
}
}
void OnPreRender()
{
//清除前一帧的RTT
if (stencilBuffer != null)
{
RenderTexture.ReleaseTemporary(stencilBuffer);
stencilBuffer = null;
}
stencilBuffer = RenderTexture.GetTemporary((int)GetComponent<Camera>().pixelWidth, (int)GetComponent<Camera>().pixelHeight, stencilZBufferDepth, RenderTextureFormat.ARGB32);
shaderCamera.targetTexture = stencilBuffer;
if (rawImage != null)
{
rawImage.texture = stencilBuffer;
}
shaderCamera.Render();
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (stencilBuffer == null)
{
// Simply transfer framebuffer to destination
Graphics.Blit(source, destination);
return;
}
// Create two buffers for blurring the image
int width = source.width / _downsampleFactor;
int height = source.height / _downsampleFactor;
RenderTexture buffer = RenderTexture.GetTemporary(width, height, stencilZBufferDepth, RenderTextureFormat.ARGB32);
RenderTexture buffer2 = RenderTexture.GetTemporary(width, height, stencilZBufferDepth, RenderTextureFormat.ARGB32);
// Copy stencil buffer to the 4x4 smaller texture
DownSample4x(stencilBuffer, buffer);
// Blur the small texture
bool oddEven = true;
for (int i = 0; i < iterations; i++)
{
if (oddEven)
{
FourTapCone(buffer, buffer2, i);
}
else
{
FourTapCone(buffer2, buffer, i);
}
oddEven = !oddEven;
}
// Compose
compMaterial.SetTexture("_StencilTex", stencilBuffer);
compMaterial.SetTexture("_BlurTex", oddEven ? buffer : buffer2);
Graphics.Blit(source, destination, compMaterial);
//Graphics.Blit(source, destination, compMaterial);
// Cleanup
RenderTexture.ReleaseTemporary(buffer);
RenderTexture.ReleaseTemporary(buffer2);
if (stencilBuffer != null)
{
RenderTexture.ReleaseTemporary(stencilBuffer);
stencilBuffer = null;
}
}
// Performs one blur iteration
public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration)
{
float off = blurMinSpread + iteration * blurSpread;
blurMaterial.SetFloat("_OffsetScale", off);
Graphics.Blit(source, dest, blurMaterial);
}
// Downsamples source texture
private void DownSample4x(RenderTexture source, RenderTexture dest)
{
float off = 1.0f;
blurMaterial.SetFloat("_OffsetScale", off);
Graphics.Blit(source, dest, blurMaterial);
}
}