forked from Cyanilux/URP_BlitRenderFeature
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Blit.cs
191 lines (157 loc) · 8.6 KB
/
Blit.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
/*
* Blit Renderer Feature https://github.com/Cyanilux/URP_BlitRenderFeature
* ------------------------------------------------------------------------------------------------------------------------
* Based on the Blit from the UniversalRenderingExamples
* https://github.com/Unity-Technologies/UniversalRenderingExamples/tree/master/Assets/Scripts/Runtime/RenderPasses
*
* Extended to allow for :
* - Specific access to selecting a source and destination (via current camera's color / texture id / render texture object
* - Automatic switching to using _AfterPostProcessTexture for After Rendering event, in order to correctly handle the blit after post processing is applied
* - Setting a _InverseView matrix (cameraToWorldMatrix), for shaders that might need it to handle calculations from screen space to world.
* e.g. reconstruct world pos from depth : https://twitter.com/Cyanilux/status/1269353975058501636
* ------------------------------------------------------------------------------------------------------------------------
* @Cyanilux
*/
public class Blit : ScriptableRendererFeature {
public class BlitPass : ScriptableRenderPass {
public Material blitMaterial = null;
public FilterMode filterMode { get; set; }
private BlitSettings settings;
private RenderTargetIdentifier source { get; set; }
private RenderTargetIdentifier destination { get; set; }
RenderTargetHandle m_TemporaryColorTexture;
RenderTargetHandle m_DestinationTexture;
string m_ProfilerTag;
public BlitPass(RenderPassEvent renderPassEvent, BlitSettings settings, string tag) {
this.renderPassEvent = renderPassEvent;
this.settings = settings;
blitMaterial = settings.blitMaterial;
m_ProfilerTag = tag;
m_TemporaryColorTexture.Init("_TemporaryColorTexture");
if (settings.dstType == Target.TextureID) {
m_DestinationTexture.Init(settings.dstTextureId);
}
}
public void Setup(RenderTargetIdentifier source, RenderTargetIdentifier destination) {
this.source = source;
this.destination = destination;
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
RenderTextureDescriptor opaqueDesc = renderingData.cameraData.cameraTargetDescriptor;
opaqueDesc.depthBufferBits = 0;
if (settings.setInverseViewMatrix) {
Shader.SetGlobalMatrix("_InverseView", renderingData.cameraData.camera.cameraToWorldMatrix);
}
if (settings.dstType == Target.TextureID) {
cmd.GetTemporaryRT(m_DestinationTexture.id, opaqueDesc, filterMode);
}
//Debug.Log($"src = {source}, dst = {destination} ");
// Can't read and write to same color target, use a TemporaryRT
if (source == destination || (settings.srcType == settings.dstType && settings.srcType == Target.CameraColor)) {
cmd.GetTemporaryRT(m_TemporaryColorTexture.id, opaqueDesc, filterMode);
Blit(cmd, source, m_TemporaryColorTexture.Identifier(), blitMaterial, settings.blitMaterialPassIndex);
Blit(cmd, m_TemporaryColorTexture.Identifier(), destination);
} else {
Blit(cmd, source, destination, blitMaterial, settings.blitMaterialPassIndex);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public override void FrameCleanup(CommandBuffer cmd) {
if (settings.dstType == Target.TextureID) {
cmd.ReleaseTemporaryRT(m_DestinationTexture.id);
}
if (source == destination || (settings.srcType == settings.dstType && settings.srcType == Target.CameraColor)) {
cmd.ReleaseTemporaryRT(m_TemporaryColorTexture.id);
}
}
}
[System.Serializable]
public class BlitSettings {
public RenderPassEvent Event = RenderPassEvent.AfterRenderingOpaques;
public Material blitMaterial = null;
public int blitMaterialPassIndex = 0;
public bool setInverseViewMatrix = false;
public Target srcType = Target.CameraColor;
public string srcTextureId = "_CameraColorTexture";
public RenderTexture srcTextureObject;
public Target dstType = Target.CameraColor;
public string dstTextureId = "_BlitPassTexture";
public RenderTexture dstTextureObject;
}
public enum Target {
CameraColor,
TextureID,
RenderTextureObject
}
public BlitSettings settings = new BlitSettings();
BlitPass blitPass;
private RenderTargetIdentifier srcIdentifier, dstIdentifier;
public override void Create() {
var passIndex = settings.blitMaterial != null ? settings.blitMaterial.passCount - 1 : 1;
settings.blitMaterialPassIndex = Mathf.Clamp(settings.blitMaterialPassIndex, -1, passIndex);
blitPass = new BlitPass(settings.Event, settings, name);
if (settings.Event == RenderPassEvent.AfterRenderingPostProcessing) {
Debug.LogWarning("Note that the \"After Rendering Post Processing\"'s Color target doesn't seem to work? (or might work, but doesn't contain the post processing) :( -- Use \"After Rendering\" instead!");
}
UpdateSrcIdentifier();
UpdateDstIdentifier();
}
private void UpdateSrcIdentifier() {
srcIdentifier = UpdateIdentifier(settings.srcType, settings.srcTextureId, settings.srcTextureObject);
}
private void UpdateDstIdentifier() {
dstIdentifier = UpdateIdentifier(settings.dstType, settings.dstTextureId, settings.dstTextureObject);
}
private RenderTargetIdentifier UpdateIdentifier(Target type, string s, RenderTexture obj) {
if (type == Target.RenderTextureObject) {
return obj;
} else if (type == Target.TextureID) {
//RenderTargetHandle m_RTHandle = new RenderTargetHandle();
//m_RTHandle.Init(s);
//return m_RTHandle.Identifier();
return s;
}
return new RenderTargetIdentifier();
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
if (settings.blitMaterial == null) {
Debug.LogWarningFormat("Missing Blit Material. {0} blit pass will not execute. Check for missing reference in the assigned renderer.", GetType().Name);
return;
}
if (settings.Event == RenderPassEvent.AfterRenderingPostProcessing) {
} else if (settings.Event == RenderPassEvent.AfterRendering && renderingData.postProcessingEnabled) {
// If event is AfterRendering, and src/dst is using CameraColor, switch to _AfterPostProcessTexture instead.
if (settings.srcType == Target.CameraColor) {
settings.srcType = Target.TextureID;
settings.srcTextureId = "_AfterPostProcessTexture";
UpdateSrcIdentifier();
}
if (settings.dstType == Target.CameraColor) {
settings.dstType = Target.TextureID;
settings.dstTextureId = "_AfterPostProcessTexture";
UpdateDstIdentifier();
}
} else {
// If src/dst is using _AfterPostProcessTexture, switch back to CameraColor
if (settings.srcType == Target.TextureID && settings.srcTextureId == "_AfterPostProcessTexture") {
settings.srcType = Target.CameraColor;
settings.srcTextureId = "";
UpdateSrcIdentifier();
}
if (settings.dstType == Target.TextureID && settings.dstTextureId == "_AfterPostProcessTexture") {
settings.dstType = Target.CameraColor;
settings.dstTextureId = "";
UpdateDstIdentifier();
}
}
var src = (settings.srcType == Target.CameraColor) ? renderer.cameraColorTarget : srcIdentifier;
var dest = (settings.dstType == Target.CameraColor) ? renderer.cameraColorTarget : dstIdentifier;
blitPass.Setup(src, dest);
renderer.EnqueuePass(blitPass);
}
}