ici_recycle_vr/Assets/LiquidVolumePro/Scripts/LiquidVolumeDepthPrePassRenderFeature.cs
Diaconescu Andrei-Alexandru 19674bfe5d Am adaugat ICI Recycle
2025-05-26 12:54:36 +03:00

191 lines
8.4 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace LiquidVolumeFX {
public class LiquidVolumeDepthPrePassRenderFeature : ScriptableRendererFeature {
static class ShaderParams {
public static int RTBackBuffer = Shader.PropertyToID("_VLBackBufferTexture");
public static int RTFrontBuffer = Shader.PropertyToID("_VLFrontBufferTexture");
public static int FlaskThickness = Shader.PropertyToID("_FlaskThickness");
public static int ForcedInvisible = Shader.PropertyToID("_LVForcedInvisible");
public const string SKW_FP_RENDER_TEXTURE = "LIQUID_VOLUME_FP_RENDER_TEXTURES";
}
enum Pass {
BackBuffer = 0,
FrontBuffer = 1
}
public readonly static List<LiquidVolume> lvBackRenderers = new List<LiquidVolume>();
public readonly static List<LiquidVolume> lvFrontRenderers = new List<LiquidVolume>();
public static void AddLiquidToBackRenderers(LiquidVolume lv) {
if (lv == null || lv.topology != TOPOLOGY.Irregular || lvBackRenderers.Contains(lv)) return;
lvBackRenderers.Add(lv);
}
public static void RemoveLiquidFromBackRenderers(LiquidVolume lv) {
if (lv == null || !lvBackRenderers.Contains(lv)) return;
lvBackRenderers.Remove(lv);
}
public static void AddLiquidToFrontRenderers(LiquidVolume lv) {
if (lv == null || lv.topology != TOPOLOGY.Irregular || lvFrontRenderers.Contains(lv)) return;
lvFrontRenderers.Add(lv);
}
public static void RemoveLiquidFromFrontRenderers(LiquidVolume lv) {
if (lv == null || !lvFrontRenderers.Contains(lv)) return;
lvFrontRenderers.Remove(lv);
}
class DepthPass : ScriptableRenderPass {
const string profilerTag = "LiquidVolumeDepthPrePass";
Material mat;
int targetId;
int passId;
List<LiquidVolume> lvRenderers;
public ScriptableRenderer renderer;
public bool interleavedRendering;
public DepthPass(Material mat, Pass pass, RenderPassEvent renderPassEvent) {
this.renderPassEvent = renderPassEvent;
this.mat = mat;
switch (pass) {
case Pass.BackBuffer:
targetId = ShaderParams.RTBackBuffer;
passId = (int)Pass.BackBuffer;
lvRenderers = lvBackRenderers;
break;
case Pass.FrontBuffer:
targetId = ShaderParams.RTFrontBuffer;
passId = (int)Pass.FrontBuffer;
lvRenderers = lvFrontRenderers;
break;
}
}
public void Setup(LiquidVolumeDepthPrePassRenderFeature feature, ScriptableRenderer renderer) {
this.renderer = renderer;
this.interleavedRendering = feature.interleavedRendering;
}
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) {
cameraTextureDescriptor.colorFormat = LiquidVolume.useFPRenderTextures ? RenderTextureFormat.RHalf : RenderTextureFormat.ARGB32;
cameraTextureDescriptor.sRGB = false;
cameraTextureDescriptor.depthBufferBits = 16;
cmd.GetTemporaryRT(targetId, cameraTextureDescriptor);
if (!interleavedRendering) {
ConfigureTarget(targetId);
}
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
if (lvRenderers == null) return;
CommandBuffer cmd = CommandBufferPool.Get(profilerTag);
cmd.Clear();
cmd.SetGlobalFloat(ShaderParams.ForcedInvisible, 0);
Camera cam = renderingData.cameraData.camera;
if (interleavedRendering) {
RenderTargetIdentifier destination = new RenderTargetIdentifier(targetId, 0, CubemapFace.Unknown, -1);
lvRenderers.ForEach((LiquidVolume lv) => {
if (lv != null && lv.isActiveAndEnabled) {
cmd.SetRenderTarget(destination);
if (LiquidVolume.useFPRenderTextures) {
cmd.ClearRenderTarget(true, true, new Color(cam.farClipPlane, 0, 0, 0), 1f);
cmd.EnableShaderKeyword(ShaderParams.SKW_FP_RENDER_TEXTURE);
} else {
cmd.ClearRenderTarget(true, true, new Color(0.9882353f, 0.4470558f, 0.75f, 0f), 1f);
cmd.DisableShaderKeyword(ShaderParams.SKW_FP_RENDER_TEXTURE);
}
cmd.SetGlobalFloat(ShaderParams.FlaskThickness, 1.0f - lv.flaskThickness);
cmd.DrawRenderer(lv.mr, mat, lv.subMeshIndex >= 0 ? lv.subMeshIndex : 0, passId);
// draw back face
cmd.SetRenderTarget(renderer.cameraColorTarget, renderer.cameraDepthTarget);
// draw liquid
cmd.DrawRenderer(lv.mr, lv.liqMat, lv.subMeshIndex >= 0 ? lv.subMeshIndex : 0, shaderPass: 1);
}
});
cmd.SetGlobalFloat(ShaderParams.ForcedInvisible, 1);
} else {
// accumulate back face depths into custom rt
if (LiquidVolume.useFPRenderTextures) {
cmd.ClearRenderTarget(true, true, new Color(cam.farClipPlane, 0, 0, 0), 1f);
cmd.EnableShaderKeyword(ShaderParams.SKW_FP_RENDER_TEXTURE);
} else {
cmd.ClearRenderTarget(true, true, new Color(0.9882353f, 0.4470558f, 0.75f, 0f), 1f);
cmd.DisableShaderKeyword(ShaderParams.SKW_FP_RENDER_TEXTURE);
}
lvRenderers.ForEach((LiquidVolume lv) => {
if (lv != null && lv.isActiveAndEnabled) {
cmd.SetGlobalFloat(ShaderParams.FlaskThickness, 1.0f - lv.flaskThickness);
cmd.DrawRenderer(lv.mr, mat, lv.subMeshIndex >= 0 ? lv.subMeshIndex : 0, passId);
}
});
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public override void FrameCleanup(CommandBuffer cmd) {
cmd.ReleaseTemporaryRT(targetId);
}
}
[SerializeField, HideInInspector]
Shader shader;
public static bool installed;
Material mat;
DepthPass backPass, frontPass;
[Tooltip("Renders each irregular liquid volume completely before rendering the next one.")]
public bool interleavedRendering;
public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingTransparents;
private void OnDestroy() {
Shader.SetGlobalFloat(ShaderParams.ForcedInvisible, 0);
CoreUtils.Destroy(mat);
}
public override void Create() {
name = "Liquid Volume Depth PrePass";
shader = Shader.Find("LiquidVolume/DepthPrePass");
if (shader == null) {
return;
}
mat = CoreUtils.CreateEngineMaterial(shader);
backPass = new DepthPass(mat, Pass.BackBuffer, renderPassEvent);
frontPass = new DepthPass(mat, Pass.FrontBuffer, renderPassEvent);
}
// This method is called when setting up the renderer once per-camera.
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
installed = true;
if (backPass != null && lvBackRenderers.Count > 0) {
backPass.Setup(this, renderer);
renderer.EnqueuePass(backPass);
}
if (frontPass != null && lvFrontRenderers.Count > 0) {
frontPass.Setup(this, renderer);
frontPass.renderer = renderer;
renderer.EnqueuePass(frontPass);
}
}
}
}