添加了覆盖屏幕空间的纹理检查。

This commit is contained in:
2026-06-08 11:53:17 +08:00
parent a30542f85d
commit 4add58d458
2 changed files with 131 additions and 46 deletions
+1
View File
@@ -1,2 +1,3 @@
# Unity 屏幕空间后处理阶段检查器-模型数据提取器 # Unity 屏幕空间后处理阶段检查器-模型数据提取器
依赖 [MaterialFunctionLibrary](https://gitea.xeric.cc/LiRuochen_WorkFlow/MaterialFunctionLibrary) 插件。
@@ -136,19 +136,15 @@ namespace XericLibrary.PostProcess
#region Inspector 配置参数 #region Inspector 配置参数
[Header("拾取材质与尺寸")] [Header("拾取材质与尺寸")] public Material pickMaterial;
public Material pickMaterial;
public Vector2Int pickRTSize = new Vector2Int(64, 64); public Vector2Int pickRTSize = new Vector2Int(64, 64);
[Header("采样区域设置")] [Header("采样区域设置")] public Rect sampleRect = new Rect(0f, 0f, 1f, 1f);
public Rect sampleRect = new Rect(0f, 0f, 1f, 1f);
[Header("读取频率控制")] [Header("读取频率控制")] [Range(0.01f, 1.0f)]
[Range(0.01f, 1.0f)]
public float readbackInterval = 0.1f; public float readbackInterval = 0.1f;
[Header("调试设置")] [Header("调试设置")] public bool enableDebugLog = false;
public bool enableDebugLog = false;
#endregion #endregion
@@ -160,6 +156,11 @@ namespace XericLibrary.PostProcess
private bool m_IsReadbackInProgress = false; private bool m_IsReadbackInProgress = false;
private int m_ReadbackFrameCounter = 0; private int m_ReadbackFrameCounter = 0;
// 调试覆盖图相关
private Material m_DebugOverlayMaterial;
private static readonly int DebugRectProp = Shader.PropertyToID("_DebugRect");
private static readonly int DebugMainTex = Shader.PropertyToID("_MainTex");
class CustomRenderPass : ScriptableRenderPass class CustomRenderPass : ScriptableRenderPass
{ {
public Material passMaterial; public Material passMaterial;
@@ -169,6 +170,11 @@ namespace XericLibrary.PostProcess
public Rect passSampleRect; public Rect passSampleRect;
public bool requestReadback; public bool requestReadback;
// 屏幕调试
public bool drawDebugOverlay;
public Material debugOverlayMaterial;
public RTHandle cameraColorTarget; // 用于获取屏幕渲染目标
private int m_MatIDProperty = Shader.PropertyToID("_MatID"); private int m_MatIDProperty = Shader.PropertyToID("_MatID");
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
@@ -223,12 +229,52 @@ namespace XericLibrary.PostProcess
context.ExecuteCommandBuffer(cmd); context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd); CommandBufferPool.Release(cmd);
// 在 CommandBuffer 执行后,发起回读请求(读取隔离缓冲区)
if (requestReadback && passReadbackBuffer != null) if (requestReadback && passReadbackBuffer != null)
{ {
AsyncGPUReadback.Request(passReadbackBuffer.rt, 0, TextureFormat.RGBAFloat, AsyncGPUReadback.Request(passReadbackBuffer.rt, 0, TextureFormat.RGBAFloat,
GeoLayerPickerRenderPassFeature.Instance.OnReadbackComplete); GeoLayerPickerRenderPassFeature.Instance.OnReadbackComplete);
} }
// --- 绘制全屏调试图 ---
if (drawDebugOverlay && debugOverlayMaterial != null && passRTHandle != null)
{
var feature = GeoLayerPickerRenderPassFeature.Instance;
if (feature == null) return;
RTHandle currentColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle;
CommandBuffer debugCmd = CommandBufferPool.Get("GeoPickerDebugOverlay");
// 【核心 1】:使用 MaterialPropertyBlock 隔离参数
MaterialPropertyBlock mpb = new MaterialPropertyBlock();
// 【修正 1】:直接使用字符串名称和 RTHandle 对象本身(RTHandle 隐式转为 Texture)
// 彻底避开 nameID (RenderTargetIdentifier) 的类型转换坑!
mpb.SetTexture(DebugMainTex, passRTHandle);
mpb.SetVector(DebugRectProp, new Vector4(
feature.sampleRect.x,
feature.sampleRect.y,
feature.sampleRect.width,
feature.sampleRect.height
));
// 设置渲染目标为当前屏幕
CoreUtils.SetRenderTarget(debugCmd, currentColorTarget);
// 【修正 2】:DrawProcedural 必须显式传入 instanceCount (1) 作为第 6 个参数!
debugCmd.DrawProcedural(
Matrix4x4.identity, // 1. matrix
debugOverlayMaterial, // 2. material
0, // 3. shaderPass
MeshTopology.Triangles, // 4. topology
3, // 5. vertexCount (全屏三角形)
1, // 6. instanceCount (必须显式写 1!)
mpb // 7. MaterialPropertyBlock
);
context.ExecuteCommandBuffer(debugCmd);
CommandBufferPool.Release(debugCmd);
}
} }
} }
@@ -245,8 +291,17 @@ namespace XericLibrary.PostProcess
}; };
// 释放旧的 RTHandle // 释放旧的 RTHandle
if (m_PickRTHandle != null) { m_PickRTHandle.Release(); m_PickRTHandle = null; } if (m_PickRTHandle != null)
if (m_ReadbackBufferHandle != null) { m_ReadbackBufferHandle.Release(); m_ReadbackBufferHandle = null; } {
m_PickRTHandle.Release();
m_PickRTHandle = null;
}
if (m_ReadbackBufferHandle != null)
{
m_ReadbackBufferHandle.Release();
m_ReadbackBufferHandle = null;
}
// 分配新的 RTHandle // 分配新的 RTHandle
m_PickRTHandle = RTHandles.Alloc( m_PickRTHandle = RTHandles.Alloc(
@@ -267,7 +322,21 @@ namespace XericLibrary.PostProcess
if (m_DecodedDataArray == null || m_DecodedDataArray.Length != requiredLength) if (m_DecodedDataArray == null || m_DecodedDataArray.Length != requiredLength)
{ {
m_DecodedDataArray = new PickedGeoData[requiredLength]; m_DecodedDataArray = new PickedGeoData[requiredLength];
if(enableDebugLog) Debug.Log($"[GeoLayerPicker] 数组重新初始化,长度: {requiredLength}"); if (enableDebugLog) Debug.Log($"[GeoLayerPicker] 数组重新初始化,长度: {requiredLength}");
}
// 初始化调试材质
if (m_DebugOverlayMaterial == null)
{
Shader overlayShader = Shader.Find("Hidden/XericLibrary/ScreenOverrideRect");
if (overlayShader != null)
{
m_DebugOverlayMaterial = CoreUtils.CreateEngineMaterial(overlayShader);
}
else
{
Debug.LogError("[GeoLayerPicker] 找不到调试 Shader: Hidden/XericLibrary/Debug/GeoPickerOverlay");
}
} }
} }
@@ -279,7 +348,7 @@ namespace XericLibrary.PostProcess
{ {
RebuildDrawList(); RebuildDrawList();
m_IsDirty = false; m_IsDirty = false;
if(enableDebugLog) Debug.Log($"[GeoLayerPicker] DrawList 重建完成,包含 {m_DrawList.Count} 个 SubMesh。"); if (enableDebugLog) Debug.Log($"[GeoLayerPicker] DrawList 重建完成,包含 {m_DrawList.Count} 个 SubMesh。");
} }
m_ReadbackFrameCounter++; m_ReadbackFrameCounter++;
@@ -302,6 +371,7 @@ namespace XericLibrary.PostProcess
shouldRead = true; shouldRead = true;
} }
// 后处理参数
m_ScriptablePass.passMaterial = pickMaterial; m_ScriptablePass.passMaterial = pickMaterial;
m_ScriptablePass.passRTHandle = m_PickRTHandle; m_ScriptablePass.passRTHandle = m_PickRTHandle;
m_ScriptablePass.passReadbackBuffer = m_ReadbackBufferHandle; m_ScriptablePass.passReadbackBuffer = m_ReadbackBufferHandle;
@@ -309,6 +379,11 @@ namespace XericLibrary.PostProcess
m_ScriptablePass.passSampleRect = sampleRect; m_ScriptablePass.passSampleRect = sampleRect;
m_ScriptablePass.requestReadback = shouldRead; m_ScriptablePass.requestReadback = shouldRead;
// 配置调试覆盖图参数
m_ScriptablePass.drawDebugOverlay = enableDebugLog; // 由 Inspector 开关控制
m_ScriptablePass.debugOverlayMaterial = m_DebugOverlayMaterial;
// m_ScriptablePass.cameraColorTarget = renderer.cameraColorTargetHandle; // 获取当前屏幕目标
renderer.EnqueuePass(m_ScriptablePass); renderer.EnqueuePass(m_ScriptablePass);
} }
@@ -400,11 +475,20 @@ namespace XericLibrary.PostProcess
m_PickRTHandle.Release(); m_PickRTHandle.Release();
m_PickRTHandle = null; m_PickRTHandle = null;
} }
if (m_ReadbackBufferHandle != null) if (m_ReadbackBufferHandle != null)
{ {
m_ReadbackBufferHandle.Release(); m_ReadbackBufferHandle.Release();
m_ReadbackBufferHandle = null; m_ReadbackBufferHandle = null;
} }
// 释放调试材质
if (m_DebugOverlayMaterial != null)
{
CoreUtils.Destroy(m_DebugOverlayMaterial);
m_DebugOverlayMaterial = null;
}
if (Instance == this) Instance = null; if (Instance == this) Instance = null;
} }
} }