// Copyright (C) 2019-2021 Alexander Bogarsukov. All rights reserved.
// See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.Universal;
using UnityEngine.XR;
namespace UnityFx.Outline.URP
{
internal class OutlinePass : ScriptableRenderPass
{
//private const string _profilerTag = "OutlinePass";
//private static readonly ProfilingSampler _profilingSampler = new ProfilingSampler(_profilerTag);
private readonly OutlineFeature _feature;
private readonly List<OutlineRenderObject> _renderObjects = new List<OutlineRenderObject>();
private readonly List<ShaderTagId> _shaderTagIdList = new List<ShaderTagId>();
private ScriptableRenderer _renderer;
public OutlinePass(OutlineFeature feature, string[] shaderTags)
{
_feature = feature;
if (shaderTags != null && shaderTags.Length > 0)
{
foreach (var passName in shaderTags)
{
_shaderTagIdList.Add(new ShaderTagId(passName));
}
}
else
{
_shaderTagIdList.Add(new ShaderTagId("UniversalForward"));
_shaderTagIdList.Add(new ShaderTagId("LightweightForward"));
_shaderTagIdList.Add(new ShaderTagId("SRPDefaultUnlit"));
}
}
public void Setup(ScriptableRenderer renderer)
{
_renderer = renderer;
}
public class PassData {
public string featureName;
public OutlineResources outlineResources;
public IOutlineSettings outlineSettings;
public int outlineLayerMask;
public uint outlineRenderingLayerMask;
public OutlineLayerCollection outlineLayers;
public List<OutlineRenderObject> renderObjects;
public List<ShaderTagId> shaderTagIdList;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
IRasterRenderGraphBuilder builder = renderGraph.AddRasterRenderPass("Outline Pass", out PassData passData);
passData.featureName = _feature.FeatureName;
passData.outlineResources = _feature.OutlineResources;
passData.outlineSettings = _feature.OutlineSettings;
passData.outlineLayerMask = _feature.OutlineLayerMask;
passData.outlineRenderingLayerMask = _feature.OutlineRenderingLayerMask;
passData.outlineLayers = _feature.OutlineLayers;
passData.renderObjects = _renderObjects;
passData.shaderTagIdList = _shaderTagIdList;
builder.SetRenderFunc<PassData>(ExecuteRender);
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
}
public static void ExecuteRender(PassData passData, RasterGraphContext context)
{
var outlineResources = passData.outlineResources;
var outlineSettings = passData.outlineSettings;
var camData = renderingData.cameraData;
if (passData.outlineLayerMask != 0)
{
var cmd = CommandBufferPool.Get(passData.featureName);
var filteringSettings = new FilteringSettings(RenderQueueRange.all, passData.outlineLayerMask, passData.outlineRenderingLayerMask);
var renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
var sortingCriteria = camData.defaultOpaqueSortFlags;
var drawingSettings = CreateDrawingSettings(passData.shaderTagIdList, ref renderingData, sortingCriteria);
var depthTexture = new RenderTargetIdentifier("_CameraDepthTexture");
drawingSettings.enableDynamicBatching = true;
drawingSettings.overrideMaterial = outlineResources.RenderMaterial;
if (outlineSettings.IsAlphaTestingEnabled())
{
drawingSettings.overrideMaterialPassIndex = OutlineResources.RenderShaderAlphaTestPassId;
cmd.SetGlobalFloat(outlineResources.AlphaCutoffId, outlineSettings.OutlineAlphaCutoff);
}
else
{
drawingSettings.overrideMaterialPassIndex = OutlineResources.RenderShaderDefaultPassId;
}
using (var renderer = new OutlineRenderer(cmd, outlineResources, _renderer.cameraColorTargetHandle, depthTexture/*_renderer.cameraDepth*/, camData.cameraTargetDescriptor))
{
renderer.RenderObjectClear(outlineSettings.OutlineRenderMode);
context.ExecuteCommandBuffer(cmd);
RendererListParams rParams = new RendererListParams(renderingData.cullResults, drawingSettings, filteringSettings);
RendererList rList = context.CreateRendererList(ref rParams);
//context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings, ref renderStateBlock);
cmd.DrawRendererList(rList);
cmd.Clear();
renderer.RenderOutline(outlineSettings);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
if (passData.outlineLayers)
{
var cmd = CommandBufferPool.Get(OutlineResources.EffectName);
var depthTexture = new RenderTargetIdentifier("_CameraDepthTexture");
using (var renderer = new OutlineRenderer(cmd, outlineResources, _renderer.cameraColorTargetHandle, depthTexture /*_renderer.cameraDepth*/, camData.cameraTargetDescriptor))
{
passData.renderObjects.Clear();
passData.outlineLayers.GetRenderObjects(passData.renderObjects);
renderer.Render(passData.renderObjects);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
}
}
}