230 lines
8.9 KiB
C#
230 lines
8.9 KiB
C#
using Code.Scripts.Gameplay.Utils;
|
|
using Gameplay.Performance;
|
|
using PhxhSDK;
|
|
using UnityEngine;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.Universal;
|
|
using Constants = Framework.Constants;
|
|
|
|
public class PostOutlineRPF : ScriptableRendererFeature
|
|
{
|
|
|
|
[System.Serializable]
|
|
public class Settings
|
|
{
|
|
//渲染发生的阶段,具体信息可以在枚举类RenderPassEvent中查看
|
|
public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingSkybox;
|
|
|
|
}
|
|
|
|
class CustomRenderPass : ScriptableRenderPass
|
|
{
|
|
|
|
private Material _mat1;
|
|
private Material _mat1_1;
|
|
private Material _mat2;
|
|
private Material _mat3;
|
|
|
|
private int _SSOutlineTexureID;
|
|
private int _EdgeTexureID;
|
|
|
|
private bool _canEnable = false;
|
|
|
|
public CustomRenderPass(Settings setting)
|
|
{
|
|
}
|
|
|
|
public override void OnCameraSetup(CommandBuffer cmd,
|
|
ref RenderingData renderingData)
|
|
{
|
|
base.OnCameraSetup(cmd, ref renderingData);
|
|
_canEnable = false;
|
|
if (renderingData.cameraData.renderType != CameraRenderType.Base)
|
|
{
|
|
return;
|
|
}
|
|
if (OutlineManager.instance == null || !OutlineManager.instance.m_EnableOutline) return;
|
|
if (OutlineManager.instance.m_RenderList.Count == 0
|
|
&& OutlineManager.instance.m_RenderListEnemy.Count == 0) return;
|
|
|
|
if (!PerformanceManager.instance.data.enablePostOutline) return;
|
|
|
|
if (_mat1 == null)
|
|
{
|
|
_mat1 = Instantiate(AssetManager.Instance.GetPreLoadResult<Material>(Constants.SHADER_OUTLINE_PATH1));
|
|
_mat1_1 = Instantiate(AssetManager.Instance.GetPreLoadResult<Material>(Constants.SHADER_OUTLINE_PATH1_1));
|
|
_mat2 = Instantiate(AssetManager.Instance.GetPreLoadResult<Material>(Constants.SHADER_OUTLINE_PATH2));
|
|
_mat3 = Instantiate(AssetManager.Instance.GetPreLoadResult<Material>(Constants.SHADER_OUTLINE_PATH3));
|
|
|
|
// DebugUtil.LogError("shader name: " + _mat1.shader.name + " " + _mat2.shader.name + " " + _mat3.shader.name);
|
|
// DebugUtil.LogError("shader pass count:" + _mat1.shader.passCount + " " + _mat2.shader.passCount + " " + _mat3.shader.passCount);
|
|
// DebugUtil.LogError("shader support:" + _mat1.shader.isSupported + " " + _mat2.shader.isSupported + " " + _mat3.shader.isSupported);
|
|
|
|
_SSOutlineTexureID = Shader.PropertyToID("_SSOutlineTexure");
|
|
_EdgeTexureID = Shader.PropertyToID("_EdgeTex");
|
|
}
|
|
|
|
_canEnable = _mat1.shader.isSupported && _mat2.shader.isSupported && _mat3.shader.isSupported;
|
|
}
|
|
|
|
public override void OnCameraCleanup(CommandBuffer cmd)
|
|
{
|
|
base.OnCameraCleanup(cmd);
|
|
|
|
if (!_canEnable) return;
|
|
}
|
|
|
|
public override void Execute(ScriptableRenderContext context,
|
|
ref RenderingData renderingData)
|
|
{
|
|
if (!_canEnable) return;
|
|
var camera = renderingData.cameraData.camera;
|
|
if (camera != Camera.main)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var cmd = CommandBufferPool.Get("Draw Outline");
|
|
|
|
_DrawPureColor(cmd, context, ref renderingData);
|
|
|
|
_DoEdgeDetect(cmd, context, ref renderingData);
|
|
|
|
_DoMerge(cmd, context, ref renderingData);
|
|
|
|
context.ExecuteCommandBuffer(cmd);
|
|
cmd.ReleaseTemporaryRT(_EdgeTexureID);
|
|
cmd.ReleaseTemporaryRT(_SSOutlineTexureID);
|
|
CommandBufferPool.Release(cmd);
|
|
}
|
|
|
|
Plane[] frustumPlanes = new Plane[6];
|
|
private void _DrawPureColor(CommandBuffer cmd,
|
|
ScriptableRenderContext context,
|
|
ref RenderingData renderingData)
|
|
{
|
|
GeometryUtility.CalculateFrustumPlanes(renderingData.cameraData.camera, frustumPlanes);
|
|
var desc = renderingData.cameraData.cameraTargetDescriptor;
|
|
//using (new ProfilingScope(cmd, new ProfilingSampler("Draw PureColor")))
|
|
{
|
|
// 绘制己方
|
|
_mat1.SetColor(PureColor, OutlineManager.instance.m_OutlineColor);
|
|
cmd.GetTemporaryRT(_SSOutlineTexureID, desc.width, desc.height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);
|
|
cmd.SetRenderTarget(_SSOutlineTexureID);
|
|
cmd.ClearRenderTarget(true, true, new Color(0, 0, 0, 0));
|
|
var renders = OutlineManager.instance.m_RenderList;
|
|
for (var i = 0; i < renders.Count; ++i)
|
|
{
|
|
var render = renders[i];
|
|
if (render == null)
|
|
{
|
|
renders.RemoveAt(i--);
|
|
continue;
|
|
}
|
|
if (!render.gameObject.activeInHierarchy)
|
|
{
|
|
continue;
|
|
}
|
|
// 判断是否在屏幕内
|
|
if (!GeometryUtility.TestPlanesAABB(frustumPlanes, render.bounds))
|
|
{
|
|
continue;
|
|
}
|
|
cmd.DrawRenderer(render, _mat1);
|
|
}
|
|
|
|
}
|
|
|
|
// using (new ProfilingScope(cmd, new ProfilingSampler("Draw PureColor")))
|
|
{
|
|
// 绘制敌方
|
|
_mat1_1.SetColor(PureColor, OutlineManager.instance.m_OutlineColorEnemy);
|
|
var renders = OutlineManager.instance.m_RenderListEnemy;
|
|
for (var i = 0; i < renders.Count; ++i)
|
|
{
|
|
var render = renders[i];
|
|
if (render == null)
|
|
{
|
|
renders.RemoveAt(i--);
|
|
continue;
|
|
}
|
|
if (!render.gameObject.activeInHierarchy)
|
|
{
|
|
continue;
|
|
}
|
|
// 判断是否在屏幕内
|
|
if (!GeometryUtility.TestPlanesAABB(frustumPlanes, render.bounds))
|
|
{
|
|
continue;
|
|
}
|
|
cmd.DrawRenderer(render, _mat1_1);
|
|
}
|
|
|
|
}
|
|
|
|
// context.ExecuteCommandBuffer(cmd);
|
|
// CommandBufferPool.Release(cmd);
|
|
}
|
|
|
|
private void _DoEdgeDetect(CommandBuffer cmd,
|
|
ScriptableRenderContext context,
|
|
ref RenderingData renderingData)
|
|
{
|
|
// var cmd = CommandBufferPool.Get("Draw Outline");
|
|
// using (new ProfilingScope(cmd, new ProfilingSampler("Final SSOutline")))
|
|
{
|
|
var desc = renderingData.cameraData.cameraTargetDescriptor;
|
|
cmd.GetTemporaryRT(_EdgeTexureID, desc.width, desc.height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);
|
|
var screenWidth = desc.width;
|
|
var sampleDistance = OutlineManager.instance.m_SampleDistance;
|
|
var wrapDistance = sampleDistance / 1080 * screenWidth;
|
|
var scaleProgress = CameraManager.Instance.GetOutlineScale(wrapDistance);
|
|
_mat2.SetFloat(SampleDistance, scaleProgress);
|
|
_mat2.SetColor(OutlineColor, OutlineManager.instance.m_OutlineColor);
|
|
cmd.Blit(_SSOutlineTexureID, _EdgeTexureID, _mat2);
|
|
|
|
}
|
|
// context.ExecuteCommandBuffer(cmd);
|
|
// CommandBufferPool.Release(cmd);
|
|
}
|
|
|
|
private void _DoMerge(CommandBuffer cmd,
|
|
ScriptableRenderContext context,
|
|
ref RenderingData renderingData)
|
|
{
|
|
// using (new ProfilingScope(cmd, new ProfilingSampler("SSOutline Merge")))
|
|
{
|
|
// TODO: 使用新方法会报错
|
|
#pragma warning disable CS0618 // 类型或成员已过时
|
|
var source = renderingData.cameraData.renderer.cameraColorTarget;
|
|
#pragma warning restore CS0618 // 类型或成员已过时
|
|
cmd.SetGlobalTexture("_EdgeTex", _EdgeTexureID);
|
|
cmd.Blit(source, _SSOutlineTexureID, _mat3);
|
|
cmd.Blit(_SSOutlineTexureID, source, _mat3);
|
|
}
|
|
// context.ExecuteCommandBuffer(cmd);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public Settings settings;
|
|
private CustomRenderPass _pass;
|
|
private static readonly int SampleDistance = Shader.PropertyToID("_SampleDistance");
|
|
private static readonly int OutlineColor = Shader.PropertyToID("_OutlineColor");
|
|
private static readonly int PureColor = Shader.PropertyToID("_PureColor");
|
|
|
|
public override void AddRenderPasses(ScriptableRenderer renderer,
|
|
ref RenderingData renderingData)
|
|
{
|
|
renderer.EnqueuePass(_pass);
|
|
}
|
|
|
|
public override void Create()
|
|
{
|
|
_pass = new CustomRenderPass(settings);
|
|
_pass.renderPassEvent = settings.renderPassEvent;
|
|
}
|
|
}
|