-
Notifications
You must be signed in to change notification settings - Fork 2
/
ReflectionFeature.cs
166 lines (122 loc) · 6.08 KB
/
ReflectionFeature.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
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class ReflectionFeature : ScriptableRendererFeature {
class ReflectionPass : ScriptableRenderPass
{
private RenderTargetIdentifier source { get; set; }
private RenderTargetHandle destination {get; set;}
public Material reflectionMaterial = null;
RenderTargetHandle MainTexID;
RenderTargetHandle BlurID;
RenderTargetHandle ReflectID;
RenderTargetHandle MaskID;
RenderTargetHandle SourID;
FilteringSettings filter;
FilteringSettings filterDepth;
public ReflectionSettings settings;
ShaderTagId shaderTag = new ShaderTagId("UniversalForward");
public void Setup(RenderTargetIdentifier source,RenderTargetHandle destination)
{
this.source = source;
this.destination = destination;
}
public ReflectionPass(ReflectionSettings settings,Material reflectionMaterial)
{
this.settings = settings;
this.reflectionMaterial = reflectionMaterial;
SourID.Init("_SourTex");
ReflectID.Init("_ReflectTex");
MainTexID.Init("_MainTex");
MaskID.Init("_Mask");
RenderQueueRange queue = new RenderQueueRange();
queue.lowerBound = Mathf.Min(settings.QueueMin);
queue.upperBound = Mathf.Max(settings.QueueMax);
filter = new FilteringSettings(queue, settings.Reflection);
filterDepth = new FilteringSettings(queue, settings.Depth);
}
public override void Configure(CommandBuffer cmd,RenderTextureDescriptor cameraTextureDescriptor)
{
RenderTextureDescriptor desc = cameraTextureDescriptor;
cmd.GetTemporaryRT(MaskID.id, desc);
ConfigureTarget(MaskID.id);
ConfigureClear(ClearFlag.All, Color.black);
}
// Here you can implement the rendering logic.
// Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
// https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
// You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
public override void Execute(ScriptableRenderContext context,ref RenderingData renderingData)
{
//层级过滤,绘制Mask
var draw = CreateDrawingSettings(shaderTag, ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags);
draw.overrideMaterial = settings.reflectionMaterial;
draw.overrideMaterialPassIndex = 3;
context.DrawRenderers(renderingData.cullResults, ref draw, ref filter);
var drawDepth = CreateDrawingSettings(shaderTag, ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags);
drawDepth.overrideMaterial = settings.reflectionMaterial;
drawDepth.overrideMaterialPassIndex = 2;
context.DrawRenderers(renderingData.cullResults, ref drawDepth, ref filterDepth);
CommandBuffer cmd = CommandBufferPool.Get("ReflectPass");
RenderTextureDescriptor opaqueDescriptor = renderingData.cameraData.cameraTargetDescriptor;
opaqueDescriptor.depthBufferBits = 0;
//这里将原图像copy到sourceID中,后面做叠加使用
int SourID = Shader.PropertyToID("_SourTex");
cmd.GetTemporaryRT(SourID, opaqueDescriptor);
cmd.CopyTexture(source, SourID);
if (destination == RenderTargetHandle.CameraTarget)
{
// cmd.GetTemporaryRT(ReflectID.id, opaqueDescriptor, FilterMode.Point);
cmd.GetTemporaryRT(BlurID.id, opaqueDescriptor, FilterMode.Point);
cmd.GetTemporaryRT(ReflectID.id, opaqueDescriptor, FilterMode.Point);
Blit(cmd, source, ReflectID.id, reflectionMaterial, 0);
Blit(cmd, ReflectID.id, BlurID.id, reflectionMaterial, 1);
Blit(cmd, BlurID.id, ReflectID.id);
Blit(cmd, ReflectID.id, source, reflectionMaterial, 4);
}
else Blit(cmd, source, destination.Identifier());
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public override void FrameCleanup(CommandBuffer cmd)
{
if (destination == RenderTargetHandle.CameraTarget)
// cmd.ReleaseTemporaryRT(MixID.id);
cmd.ReleaseTemporaryRT(BlurID.id);
cmd.ReleaseTemporaryRT(ReflectID.id);
cmd.ReleaseTemporaryRT(SourID.id);
cmd.ReleaseTemporaryRT(MainTexID.id);
cmd.ReleaseTemporaryRT(MaskID.id);
}
}
[System.Serializable]
public class ReflectionSettings {
public Material reflectionMaterial = null;
public LayerMask Reflection;
public LayerMask Depth;
[Range(1000, 5000)] public int QueueMin = 2000;
[Range(1000, 5000)] public int QueueMax = 2500;
}
public ReflectionSettings settings = new ReflectionSettings();
ReflectionPass reflectionPass;
RenderTargetHandle reflectTexture;
public override void Create()
{
reflectionPass = new ReflectionPass(settings, settings.reflectionMaterial);
reflectionPass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
reflectTexture.Init("_MainTex");
}
// Here you can inject one or multiple render passes in the renderer.
// This method is called when setting up the renderer once per-camera.
public override void AddRenderPasses(ScriptableRenderer renderer,ref RenderingData renderingData)
{
if (settings.reflectionMaterial == null)
{
Debug.LogWarningFormat("Missing Outline Material");
return;
}
reflectionPass.Setup(renderer.cameraColorTarget, RenderTargetHandle.CameraTarget);
renderer.EnqueuePass(reflectionPass);
}
}