#if HAVE_URP_12_OR_NEWER || HAVE_URP_10_OR_NEWER
using System;
using UnityEngine;
using UnityEngine.Rendering;
#if UNITY_2023_3_OR_NEWER
using UnityEngine.Rendering.RenderGraphModule;
#endif
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.Universal.Internal;
namespace UnityGLTF
{
#if HAVE_URP_12_OR_NEWER
[DisallowMultipleRendererFeature("Opaque Texture (Rough Refractions)")]
#endif
public class RoughRefractionFeature : ScriptableRendererFeature
{
private const string CAMERA_OPAQUE_TEXTURENAME = "_CameraOpaqueTexture";
#if !UNITY_2022_3_OR_NEWER
[SerializeField]
#endif
private Downsampling downsampling = Downsampling.None;
class CustomRenderPass : CopyColorPass
{
public Downsampling m_DownsamplingMethod;
#if UNITY_2022_3_OR_NEWER
public RTHandle m_destination;
public RTHandle m_source;
#else
public RenderTargetHandle destination;
#endif
public CustomRenderPass(RenderPassEvent evt) : base(evt,
CoreUtils.CreateEngineMaterial(Shader.Find("Hidden/Universal Render Pipeline/Sampling")),
CoreUtils.CreateEngineMaterial(Shader.Find("Hidden/Universal Render Pipeline/Blit")))
{ }
#if UNITY_2022_3_OR_NEWER
#pragma warning disable 672
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
#pragma warning restore 672
{
if (renderingData.cameraData.isPreviewCamera)
return;
if (m_source == null || m_destination == null || !m_source.rt || !m_destination.rt)
return;
#pragma warning disable 672
#pragma warning disable 618
base.Execute(context, ref renderingData);
#pragma warning restore 672
#pragma warning restore 618
}
public void Setup(RTHandle source, Downsampling downsampling)
{
this.m_source = source;
this.m_DownsamplingMethod = downsampling;
}
public void Dispose()
{
m_destination?.Release();
}
#else
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
if (renderingData.cameraData.isPreviewCamera)
return;
Setup(renderingData.cameraData.renderer.cameraColorTarget, destination, m_DownsamplingMethod);
#pragma warning disable 672
#pragma warning disable 618
base.Execute(context, ref renderingData);
#pragma warning restore 672
#pragma warning restore 618
}
public new void Setup(RenderTargetIdentifier source, RenderTargetHandle destination, Downsampling downsampling)
{
base.Setup(source, destination, downsampling);
this.destination = destination;
this.m_DownsamplingMethod = downsampling;
}
#endif
#pragma warning disable 672
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
#pragma warning restore 672
{
var desc = renderingData.cameraData.cameraTargetDescriptor;
desc.useMipMap = true;
desc.autoGenerateMips = true;
renderingData.cameraData.cameraTargetDescriptor = desc;
// base.OnCameraSetup(cmd, ref renderingData);
RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
descriptor.msaaSamples = 1;
descriptor.depthBufferBits = 0;
if (m_DownsamplingMethod == Downsampling._2xBilinear)
{
descriptor.width /= 2;
descriptor.height /= 2;
}
else if (m_DownsamplingMethod == Downsampling._4xBox || m_DownsamplingMethod == Downsampling._4xBilinear)
{
descriptor.width /= 4;
descriptor.height /= 4;
}
#if UNITY_2022_3_OR_NEWER
#if UNITY_6000_0_OR_NEWER
RenderingUtils.ReAllocateHandleIfNeeded(ref m_destination, descriptor, FilterMode.Trilinear, TextureWrapMode.Clamp, name: CAMERA_OPAQUE_TEXTURENAME);
#else
RenderingUtils.ReAllocateIfNeeded(ref m_destination, descriptor, FilterMode.Trilinear, TextureWrapMode.Clamp, name: CAMERA_OPAQUE_TEXTURENAME);
#endif
base.Setup(m_source, m_destination, this.m_DownsamplingMethod);
cmd.SetGlobalTexture(m_destination.name, m_destination.nameID);
#else
cmd.GetTemporaryRT(destination.id, descriptor, FilterMode.Trilinear);
#endif
}
}
private CustomRenderPass m_RoughRefractionPassNonRG;
#if UNITY_2023_3_OR_NEWER
private bool usingRenderGraph = false;
#endif
#if !UNITY_2022_3_OR_NEWER
RenderTargetHandle m_OpaqueColor;
#endif
///
public override void Create()
{
#if UNITY_2023_3_OR_NEWER
var renderGraphSettings = GraphicsSettings.GetRenderPipelineSettings();
usingRenderGraph = !renderGraphSettings.enableRenderCompatibilityMode;
if (!usingRenderGraph)
{
#endif
#if UNITY_2022_3_OR_NEWER
if (m_RoughRefractionPassNonRG == null)
{
m_RoughRefractionPassNonRG = new CustomRenderPass(RenderPassEvent.AfterRenderingSkybox);
}
#else
m_OpaqueColor.Init(CAMERA_OPAQUE_TEXTURENAME);
#endif
#if UNITY_2023_3_OR_NEWER
}
else
{
if (m_RoughRefractionPassRG == null)
{
m_RoughRefractionPassRG = new RoughRefractionPassRG();
m_RoughRefractionPassRG.renderPassEvent = RenderPassEvent.AfterRenderingSkybox;
}
}
#endif
}
// 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 (renderingData.cameraData.cameraType != CameraType.Game && renderingData.cameraData.cameraType != CameraType.SceneView)
return;
#if UNITY_2022_3_OR_NEWER
if (m_RoughRefractionPassNonRG != null)
{
renderer.EnqueuePass(m_RoughRefractionPassNonRG);
}
#if UNITY_2023_3_OR_NEWER
else
if (usingRenderGraph && m_RoughRefractionPassRG != null)
{
renderer.EnqueuePass(m_RoughRefractionPassRG);
}
#endif
#else
if (m_RoughRefractionPassNonRG == null)
{
m_RoughRefractionPassNonRG = new CustomRenderPass(RenderPassEvent.AfterRenderingSkybox);
}
#if UNITY_2022_3_OR_NEWER
var identifier = new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
m_RoughRefractionPassNonRG.Setup(identifier, m_OpaqueColor, downsampling);
#else
m_RoughRefractionPassNonRG.Setup(renderer.cameraColorTarget, m_OpaqueColor, downsampling);
#endif
renderer.EnqueuePass(m_RoughRefractionPassNonRG);
#endif
}
#if UNITY_2022_3_OR_NEWER
public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
{
#pragma warning disable 618
m_RoughRefractionPassNonRG.Setup(renderer.cameraColorTargetHandle, downsampling);
#pragma warning restore 618
}
public void OnDestroy()
{
m_RoughRefractionPassNonRG?.Dispose();
}
#endif
#if UNITY_2023_3_OR_NEWER
private RoughRefractionPassRG m_RoughRefractionPassRG;
// ######### RenderGraph Version #########
class RoughRefractionPassRG : ScriptableRenderPass
{
// This class stores the data that the render pass needs. The RecordRenderGraph method populates the data and the render graph passes it as a parameter to the rendering function.
class PassData
{
internal TextureHandle activeColorTexture;
internal TextureHandle destinationTexture;
}
// Rendering function that generates the rendering commands for the render pass.
// The RecordRenderGraph method instructs the render graph to use it with the SetRenderFunc method.
static void ExecutePass(PassData data, RasterGraphContext context)
{
var rtHandle = (RTHandle) data.activeColorTexture;
// The implicit conversion seems to mess up when calling RenderToCubemap() programmatically,
// so we need to do the conversion ourselves and check validity
if (rtHandle.rt || rtHandle.externalTexture)
Blitter.BlitTexture(context.cmd, rtHandle, new Vector4(1, 1, 0, 0), 0, false);
}
// This method adds and configures one or more render passes in the render graph.
// This process includes declaring their inputs and outputs, but does not include adding commands to command buffers.
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
string passName = "Rough Refraction Pass";
// Add a raster render pass to the render graph. The PassData type parameter determines the type of the passData out variable
using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData))
{
// UniversalResourceData contains all the texture handles used by URP, including the active color and depth textures of the camera
UniversalResourceData resourceData = frameData.Get();
// Populate passData with the data needed by the rendering function of the render pass
// Use the camera’s active color texture as the source texture for the copy
passData.activeColorTexture = resourceData.activeColorTexture;
UniversalCameraData cameraData = frameData.Get();
TextureDesc rgDesc = new TextureDesc(cameraData.cameraTargetDescriptor.width, cameraData.cameraTargetDescriptor.height);
rgDesc.name = "_CameraOpaqueTexture";
rgDesc.dimension = cameraData.cameraTargetDescriptor.dimension;
rgDesc.clearBuffer = false;
rgDesc.autoGenerateMips = true;
rgDesc.useMipMap = true;
rgDesc.msaaSamples = MSAASamples.None;
rgDesc.filterMode = FilterMode.Bilinear;
rgDesc.wrapMode = TextureWrapMode.Clamp;
rgDesc.bindTextureMS = cameraData.cameraTargetDescriptor.bindMS;
rgDesc.colorFormat = cameraData.cameraTargetDescriptor.graphicsFormat;
rgDesc.depthBufferBits = 0;
rgDesc.isShadowMap = false;
rgDesc.vrUsage = cameraData.cameraTargetDescriptor.vrUsage;
//TextureHandle destination = UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc, "_CameraOpaqueTexture", false);
passData.destinationTexture = renderGraph.CreateTexture(rgDesc);;
builder.UseTexture(passData.activeColorTexture);
builder.SetRenderAttachment(passData.destinationTexture, 0, AccessFlags.Write);
builder.SetGlobalTextureAfterPass(passData.destinationTexture, Shader.PropertyToID("_CameraOpaqueTexture"));
builder.SetRenderFunc((RoughRefractionFeature.RoughRefractionPassRG.PassData data, RasterGraphContext context) => ExecutePass(data, context));
}
}
}
#endif
}
}
#endif