131 lines
4.9 KiB
C#
131 lines
4.9 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.Universal;
|
|
|
|
namespace X.Rendering.Feature
|
|
{
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct Capsule
|
|
{
|
|
public Vector3 a, b;
|
|
public float radius;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct Character
|
|
{
|
|
public Vector3 position;
|
|
public float radius;
|
|
public Vector4 lightDir; //xyz:lightDir, w:根据lightColor 算个系数
|
|
public int startID, endID;
|
|
}
|
|
|
|
public class CapsuleAO : ScriptableRendererFeature
|
|
{
|
|
[Serializable]
|
|
public class Settings
|
|
{
|
|
public RenderPassEvent RenderPassEvent = RenderPassEvent.BeforeRenderingTransparents;
|
|
public float AmbientIntensity = 0.2f;
|
|
public float ShadowIntensity = 0.4f;
|
|
public float ShadowSharpness = 20;
|
|
[Range(1, 90)]
|
|
public float ConeAngle = 1;
|
|
public Material CapsuleAOMat;
|
|
}
|
|
|
|
[SerializeField]
|
|
Settings settings;
|
|
CapsuleAOPass capsuleAOPass;
|
|
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
|
{
|
|
{
|
|
renderer.EnqueuePass(capsuleAOPass);
|
|
}
|
|
}
|
|
|
|
public override void Create()
|
|
{
|
|
capsuleAOPass = new(settings);
|
|
}
|
|
|
|
class CapsuleAOPass : ScriptableRenderPass, IDisposable
|
|
{
|
|
private Settings settings;
|
|
private GraphicsBuffer capsuleDataBuffer;
|
|
private GraphicsBuffer characterDataBuffer;
|
|
private ProfilingSampler profiler;
|
|
|
|
|
|
|
|
public CapsuleAOPass(Settings settings)
|
|
{
|
|
this.settings = settings;
|
|
profiler = new (nameof(CapsuleAOPass));
|
|
renderPassEvent = settings.RenderPassEvent;
|
|
}
|
|
|
|
|
|
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
|
|
{
|
|
base.Configure(cmd, cameraTextureDescriptor);
|
|
ConfigureInput(ScriptableRenderPassInput.Depth | ScriptableRenderPassInput.Normal);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
capsuleDataBuffer?.Dispose();
|
|
capsuleDataBuffer = null;
|
|
characterDataBuffer?.Dispose();
|
|
characterDataBuffer = null;
|
|
}
|
|
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
|
{
|
|
if (!XRenderFeatureManager.Instance)
|
|
{
|
|
return;
|
|
}
|
|
ref var characterArray = ref XRenderFeatureManager.Instance.CharacterArray;
|
|
ref var capsuleArray = ref XRenderFeatureManager.Instance.CapsuleArray;
|
|
if (!capsuleArray.IsCreated)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(capsuleDataBuffer == null || capsuleDataBuffer.count != capsuleArray.Length)
|
|
{
|
|
capsuleDataBuffer?.Release();
|
|
capsuleDataBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, capsuleArray.Length, UnsafeUtility.SizeOf<Capsule>());
|
|
}
|
|
|
|
if (characterDataBuffer == null || characterDataBuffer.count != characterArray.Length)
|
|
{
|
|
characterDataBuffer?.Release();
|
|
characterDataBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, characterArray.Length, UnsafeUtility.SizeOf<Character>());
|
|
}
|
|
|
|
capsuleDataBuffer.SetData(capsuleArray);
|
|
characterDataBuffer.SetData(characterArray);
|
|
|
|
var cmd = renderingData.commandBuffer;
|
|
using var scp = new ProfilingScope(cmd, profiler);
|
|
cmd.SetGlobalBuffer("_CapsuleData", capsuleDataBuffer);
|
|
cmd.SetGlobalBuffer("_CharacterData", characterDataBuffer);
|
|
cmd.SetGlobalInt("_CapsulesCount", capsuleArray.Length);
|
|
cmd.SetGlobalInt("_CharactersCount", characterArray.Length);
|
|
cmd.SetGlobalFloat("_AmbientIntensity", settings.AmbientIntensity);
|
|
cmd.SetGlobalFloat("_ShadowIntensity", settings.ShadowIntensity);
|
|
cmd.SetGlobalFloat("_ShadowSharpness", settings.ShadowSharpness);
|
|
cmd.SetGlobalFloat("_ConeAngle", settings.ConeAngle);
|
|
var renderer = renderingData.cameraData.renderer;
|
|
|
|
cmd.SetRenderTarget(renderer.cameraColorTargetHandle, loadAction: RenderBufferLoadAction.Load, storeAction: RenderBufferStoreAction.Store);
|
|
cmd.DrawProcedural(Matrix4x4.identity, settings.CapsuleAOMat, 0, MeshTopology.Triangles, 3);
|
|
}
|
|
}
|
|
}
|
|
} |