Created
December 3, 2021 23:01
-
-
Save aefreedman/09f0375f1c10e2e2ed012250de63701d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Calico post processing with stencil mask | |
// https://twitter.com/CalicoGame/status/1121221295536951296 | |
using System; | |
using UnityEngine; | |
using UnityEngine.Rendering; | |
[ExecuteInEditMode, ImageEffectAllowedInSceneView] | |
public class ScreenMaterialCommandBuffer : MonoBehaviour | |
{ | |
public enum Mode | |
{ | |
Stencil, | |
RenderTexture | |
} | |
public Mode RenderMode; | |
public DepthTextureMode DepthMode = DepthTextureMode.None; | |
//AfterForwardAlpha will work for most effects | |
public CameraEvent RenderOrder = CameraEvent.AfterForwardAlpha; | |
public Material EffectMaterial; | |
private CameraEvent _cameraEvent; | |
private CommandBuffer _commandBuffer; | |
// [SerializeField] | |
private string GlobalRenderTextureName = "_MappedNoise"; | |
private int _globalRenderTextureName; | |
private Camera _camera; | |
private Camera Camera | |
{ | |
get | |
{ | |
if (_camera == null) | |
_camera = GetComponent<Camera>(); | |
return _camera; | |
} | |
} | |
//Update settings when edited | |
private void OnValidate() | |
{ | |
_globalRenderTextureName = Shader.PropertyToID(GlobalRenderTextureName); | |
Camera.depthTextureMode = DepthMode; | |
if (RenderOrder != _cameraEvent && _commandBuffer != null) | |
{ | |
Camera.RemoveCommandBuffer(_cameraEvent, _commandBuffer); | |
Camera.AddCommandBuffer(RenderOrder, _commandBuffer); | |
_cameraEvent = RenderOrder; | |
} | |
else if (RenderOrder != _cameraEvent && EffectMaterial != null) | |
{ | |
OnEnable(); | |
} | |
} | |
private void BlitMaterialToRenderTexture() | |
{ | |
if (_commandBuffer != null || EffectMaterial == null) | |
return; | |
var _previousTarget = BuiltinRenderTextureType.CurrentActive; | |
_commandBuffer = new CommandBuffer { name = "Blit Material to Render Texture" }; | |
var downsampler = (int) Mathf.Pow(2, 1); | |
var tempRenderTexture = Shader.PropertyToID("_tempRenderTex"); | |
_commandBuffer.GetTemporaryRT(tempRenderTexture, _camera.pixelWidth / downsampler, _camera.pixelHeight / downsampler, 0); | |
_commandBuffer.SetRenderTarget(tempRenderTexture); | |
_commandBuffer.ClearRenderTarget(true, true, Color.clear, 1f); | |
// _commandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, tempRenderTexture); | |
// _commandBuffer.SetGlobalTexture("_MainTex", tempRenderTexture); | |
_commandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, tempRenderTexture, EffectMaterial); | |
_commandBuffer.SetGlobalTexture(GlobalRenderTextureName, tempRenderTexture); | |
_commandBuffer.SetRenderTarget(_previousTarget); | |
// _commandBuffer.Blit(_globalRenderTex, BuiltinRenderTextureType.CameraTarget); | |
Camera.AddCommandBuffer(RenderOrder, _commandBuffer); | |
} | |
private void OnEnable() | |
{ | |
switch (RenderMode) | |
{ | |
case Mode.Stencil: | |
BlitMaterialToCameraTarget(); | |
break; | |
case Mode.RenderTexture: | |
BlitMaterialToRenderTexture(); | |
break; | |
default: | |
throw new ArgumentOutOfRangeException(); | |
} | |
} | |
private void BlitMaterialToCameraTarget() | |
{ | |
if (_commandBuffer != null || EffectMaterial == null) | |
return; | |
_commandBuffer = new CommandBuffer { name = "Blit with Replacement Material" }; | |
// 1: Get a render texture by the name defined in the inspector at screen size and clear it | |
var tempRenderTexture = Shader.PropertyToID("_tempRenderTex"); | |
_commandBuffer.GetTemporaryRT(tempRenderTexture, -1, -1, 0); | |
_commandBuffer.SetRenderTarget(tempRenderTexture, tempRenderTexture); | |
_commandBuffer.ClearRenderTarget(true, true, Color.clear); | |
// 2: Blit the camera target into the temporary render texture | |
_commandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, tempRenderTexture); | |
// 3: Active render target is now tempRenderTexture | |
// 4: Set _MainTex as the temporary render texture | |
_commandBuffer.SetGlobalTexture("_MainTex", tempRenderTexture); | |
// 5: Blit the camera target again, but this time using a replacement material | |
_commandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, BuiltinRenderTextureType.CameraTarget, EffectMaterial); | |
Camera.AddCommandBuffer(RenderOrder, _commandBuffer); | |
} | |
private void OnDisable() | |
{ | |
if (_commandBuffer == null) | |
return; | |
Camera.RemoveCommandBuffer(RenderOrder, _commandBuffer); | |
_commandBuffer = null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment