2026-04-19 02:38:48 +08:00
|
|
|
using XCEngine;
|
|
|
|
|
using XCEngine.Rendering;
|
|
|
|
|
|
2026-04-19 14:11:25 +08:00
|
|
|
namespace XCEngine.Rendering.Universal
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
|
|
|
|
public abstract class ScriptableRendererFeature
|
2026-04-21 20:17:08 +08:00
|
|
|
: Object
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
2026-04-20 01:14:37 +08:00
|
|
|
private bool m_disposed;
|
2026-04-20 15:03:45 +08:00
|
|
|
private bool m_runtimeCreated;
|
2026-04-21 19:43:45 +08:00
|
|
|
private bool m_isActive = true;
|
|
|
|
|
private int m_runtimeStateVersion = 1;
|
2026-04-21 19:59:20 +08:00
|
|
|
private int m_runtimeStateHash;
|
|
|
|
|
private bool m_runtimeStateHashResolved;
|
2026-04-21 19:43:45 +08:00
|
|
|
private ScriptableRendererData m_owner;
|
2026-04-20 01:14:37 +08:00
|
|
|
|
2026-04-19 00:05:29 +08:00
|
|
|
protected ScriptableRendererFeature()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-21 19:43:45 +08:00
|
|
|
public bool isActive
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return m_isActive;
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (m_isActive == value)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_isActive = value;
|
|
|
|
|
SetDirty();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void BindOwnerInstance(
|
|
|
|
|
ScriptableRendererData owner)
|
|
|
|
|
{
|
|
|
|
|
m_owner = owner;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal int GetRuntimeStateVersionInstance()
|
|
|
|
|
{
|
2026-04-21 19:59:20 +08:00
|
|
|
SynchronizeRuntimeStateVersion();
|
2026-04-21 19:43:45 +08:00
|
|
|
return m_runtimeStateVersion;
|
|
|
|
|
}
|
2026-04-19 00:05:29 +08:00
|
|
|
|
2026-04-20 15:03:45 +08:00
|
|
|
internal void CreateInstance()
|
|
|
|
|
{
|
|
|
|
|
if (m_runtimeCreated)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_disposed = false;
|
|
|
|
|
Create();
|
|
|
|
|
m_runtimeCreated = true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-20 01:14:37 +08:00
|
|
|
internal void ReleaseRuntimeResourcesInstance()
|
|
|
|
|
{
|
2026-04-21 19:43:45 +08:00
|
|
|
if (m_disposed ||
|
|
|
|
|
!m_runtimeCreated)
|
2026-04-20 01:14:37 +08:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReleaseRuntimeResources();
|
|
|
|
|
m_disposed = true;
|
2026-04-20 15:03:45 +08:00
|
|
|
m_runtimeCreated = false;
|
2026-04-20 01:14:37 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-19 00:05:29 +08:00
|
|
|
public virtual void Create()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual void ConfigureCameraRenderRequest(
|
2026-04-19 15:20:34 +08:00
|
|
|
CameraRenderRequestContext context)
|
2026-04-19 00:05:29 +08:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-20 01:48:16 +08:00
|
|
|
public virtual void ConfigureCameraFramePlan(
|
|
|
|
|
ScriptableRenderPipelinePlanningContext context)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-21 18:05:33 +08:00
|
|
|
public virtual void ConfigureRenderSceneSetup(
|
|
|
|
|
RenderSceneSetupContext context)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-21 17:41:44 +08:00
|
|
|
public virtual void ConfigureDirectionalShadowExecutionState(
|
|
|
|
|
DirectionalShadowExecutionContext context)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-19 00:05:29 +08:00
|
|
|
public virtual void AddRenderPasses(
|
|
|
|
|
ScriptableRenderer renderer,
|
|
|
|
|
RenderingData renderingData)
|
|
|
|
|
{
|
|
|
|
|
}
|
2026-04-19 16:17:38 +08:00
|
|
|
|
|
|
|
|
protected bool HasDirectionalShadow(
|
|
|
|
|
CameraRenderRequestContext context)
|
|
|
|
|
{
|
|
|
|
|
return context != null &&
|
|
|
|
|
InternalCalls
|
|
|
|
|
.Rendering_CameraRenderRequestContext_GetHasDirectionalShadow(
|
|
|
|
|
context.nativeHandle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void ClearDirectionalShadow(
|
|
|
|
|
CameraRenderRequestContext context)
|
|
|
|
|
{
|
|
|
|
|
if (context == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InternalCalls
|
|
|
|
|
.Rendering_CameraRenderRequestContext_ClearDirectionalShadow(
|
|
|
|
|
context.nativeHandle);
|
|
|
|
|
}
|
2026-04-20 01:14:37 +08:00
|
|
|
|
|
|
|
|
protected virtual void ReleaseRuntimeResources()
|
|
|
|
|
{
|
|
|
|
|
}
|
2026-04-21 19:43:45 +08:00
|
|
|
|
2026-04-21 19:59:20 +08:00
|
|
|
protected virtual int ComputeRuntimeStateHash()
|
|
|
|
|
{
|
|
|
|
|
int hash = 17;
|
|
|
|
|
hash =
|
|
|
|
|
RuntimeStateHashUtility.Combine(
|
|
|
|
|
hash,
|
|
|
|
|
m_isActive);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-21 19:43:45 +08:00
|
|
|
protected void SetDirty()
|
|
|
|
|
{
|
2026-04-21 19:59:20 +08:00
|
|
|
ApplyDirty(
|
|
|
|
|
ComputeRuntimeStateHash());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SynchronizeRuntimeStateVersion()
|
|
|
|
|
{
|
|
|
|
|
int runtimeStateHash =
|
|
|
|
|
ComputeRuntimeStateHash();
|
|
|
|
|
if (!m_runtimeStateHashResolved)
|
|
|
|
|
{
|
|
|
|
|
m_runtimeStateHash = runtimeStateHash;
|
|
|
|
|
m_runtimeStateHashResolved = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (runtimeStateHash == m_runtimeStateHash)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ApplyDirty(runtimeStateHash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ApplyDirty(
|
|
|
|
|
int runtimeStateHash)
|
|
|
|
|
{
|
|
|
|
|
m_runtimeStateHash = runtimeStateHash;
|
|
|
|
|
m_runtimeStateHashResolved = true;
|
|
|
|
|
|
2026-04-21 19:43:45 +08:00
|
|
|
if (m_runtimeCreated &&
|
|
|
|
|
!m_disposed)
|
|
|
|
|
{
|
|
|
|
|
ReleaseRuntimeResources();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_disposed = false;
|
|
|
|
|
m_runtimeCreated = false;
|
|
|
|
|
|
|
|
|
|
unchecked
|
|
|
|
|
{
|
|
|
|
|
++m_runtimeStateVersion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_runtimeStateVersion <= 0)
|
|
|
|
|
{
|
|
|
|
|
m_runtimeStateVersion = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_owner != null)
|
|
|
|
|
{
|
|
|
|
|
m_owner.InvalidateRendererFeaturesInstance();
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-19 00:05:29 +08:00
|
|
|
}
|
2026-04-21 19:59:20 +08:00
|
|
|
|
|
|
|
|
internal static class RuntimeStateHashUtility
|
|
|
|
|
{
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
bool value)
|
|
|
|
|
{
|
|
|
|
|
return Combine(
|
|
|
|
|
hash,
|
|
|
|
|
value ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
byte value)
|
|
|
|
|
{
|
|
|
|
|
return Combine(
|
|
|
|
|
hash,
|
|
|
|
|
(int)value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
uint value)
|
|
|
|
|
{
|
|
|
|
|
unchecked
|
|
|
|
|
{
|
|
|
|
|
return (hash * 31) + (int)value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
int value)
|
|
|
|
|
{
|
|
|
|
|
unchecked
|
|
|
|
|
{
|
|
|
|
|
return (hash * 31) + value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
float value)
|
|
|
|
|
{
|
|
|
|
|
return Combine(
|
|
|
|
|
hash,
|
|
|
|
|
value.GetHashCode());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
string value)
|
|
|
|
|
{
|
|
|
|
|
return Combine(
|
|
|
|
|
hash,
|
|
|
|
|
value != null
|
|
|
|
|
? value.GetHashCode()
|
|
|
|
|
: 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
Vector4 value)
|
|
|
|
|
{
|
|
|
|
|
hash = Combine(hash, value.X);
|
|
|
|
|
hash = Combine(hash, value.Y);
|
|
|
|
|
hash = Combine(hash, value.Z);
|
|
|
|
|
hash = Combine(hash, value.W);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
RenderQueueRange value)
|
|
|
|
|
{
|
|
|
|
|
hash = Combine(hash, value.lowerBound);
|
|
|
|
|
hash = Combine(hash, value.upperBound);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
FilteringSettings value)
|
|
|
|
|
{
|
|
|
|
|
hash = Combine(hash, value.renderQueueMin);
|
|
|
|
|
hash = Combine(hash, value.renderQueueMax);
|
|
|
|
|
hash = Combine(hash, value.renderLayerMask);
|
|
|
|
|
hash = Combine(hash, value.requireShadowCasting);
|
|
|
|
|
hash = Combine(hash, value.requireRenderObjectId);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
SortingSettings value)
|
|
|
|
|
{
|
|
|
|
|
return Combine(
|
|
|
|
|
hash,
|
|
|
|
|
(int)value.sortMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
RendererListDesc value)
|
|
|
|
|
{
|
|
|
|
|
hash = Combine(hash, (int)value.type);
|
|
|
|
|
hash = Combine(hash, value.filtering);
|
|
|
|
|
hash = Combine(hash, value.sorting);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
DepthState value)
|
|
|
|
|
{
|
|
|
|
|
hash = Combine(hash, value.writeEnabled);
|
|
|
|
|
hash =
|
|
|
|
|
Combine(hash, (int)value.compareFunction);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
StencilFaceState value)
|
|
|
|
|
{
|
|
|
|
|
hash =
|
|
|
|
|
Combine(hash, (int)value.failOperation);
|
|
|
|
|
hash =
|
|
|
|
|
Combine(hash, (int)value.passOperation);
|
|
|
|
|
hash =
|
|
|
|
|
Combine(hash, (int)value.depthFailOperation);
|
|
|
|
|
hash =
|
|
|
|
|
Combine(hash, (int)value.compareFunction);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
StencilState value)
|
|
|
|
|
{
|
|
|
|
|
hash = Combine(hash, value.enabled);
|
|
|
|
|
hash = Combine(hash, value.readMask);
|
|
|
|
|
hash = Combine(hash, value.writeMask);
|
|
|
|
|
hash = Combine(hash, value.frontFace);
|
|
|
|
|
hash = Combine(hash, value.backFace);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
RenderStateBlock value)
|
|
|
|
|
{
|
|
|
|
|
hash = Combine(hash, (int)value.mask);
|
|
|
|
|
hash = Combine(hash, value.depthState);
|
|
|
|
|
hash = Combine(hash, value.stencilState);
|
|
|
|
|
hash = Combine(hash, value.stencilReference);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int Combine(
|
|
|
|
|
int hash,
|
|
|
|
|
DrawingSettings value)
|
|
|
|
|
{
|
|
|
|
|
hash = Combine(hash, value.overrideMaterialPath);
|
|
|
|
|
hash = Combine(hash, value.shaderPassName);
|
|
|
|
|
hash = Combine(hash, value.renderStateBlock);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-19 00:05:29 +08:00
|
|
|
}
|
2026-04-19 02:38:48 +08:00
|
|
|
|