添加从纹理到屏幕空间的换算。

This commit is contained in:
2026-06-08 17:10:59 +08:00
parent c3b9eef683
commit efc9ce0456
@@ -1,3 +1,4 @@
using System;
using UnityEngine; using UnityEngine;
using UnityEngine.Rendering; using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal; using UnityEngine.Rendering.Universal;
@@ -88,6 +89,45 @@ namespace XericLibrary.PostProcess
var mat = GetMaterial(); var mat = GetMaterial();
return mat != null ? mat.name : "Unknown"; return mat != null ? mat.name : "Unknown";
} }
public Vector2 GetCenterRectLocation()
{
var feature = GeoLayerPickerRenderPassFeature.Instance;
if (feature == null)
return Vector2.zero;
float texWidth = feature.pickRTSize.x;
float texHeight = feature.pickRTSize.y;
float normalizedX = centerPixelPos.x / texWidth;
float normalizedY = centerPixelPos.y / texHeight;
return new Vector2(normalizedX, normalizedY);
}
public Vector2 GetCenterRectLocation(RectTransform rectTransform)
{
var normalized = GetCenterRectLocation();
Vector2 rectSize = rectTransform.rect.size;
float x = rectTransform.rect.x + normalized.x * rectSize.x;
float y = rectTransform.rect.y + normalized.y * rectSize.y;
return new Vector2(x, y);
}
public Vector2 GetCenterRectAnchoredPosition(RectTransform rectTransform)
{
var normalized = GetCenterRectLocation();
Vector2 pivot = rectTransform.pivot;
Vector2 rectSize = rectTransform.rect.size;
float anchoredX = (normalized.x - pivot.x) * rectSize.x;
float anchoredY = (normalized.y - pivot.y) * rectSize.y;
return new Vector2(anchoredX, anchoredY);
}
} }
/// <summary> /// <summary>
@@ -495,21 +535,13 @@ namespace XericLibrary.PostProcess
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{ {
if (passMaterial == null || passRTHandle == null || passDrawList == null || passDrawList.Count == 0) if (passMaterial != null && passRTHandle != null && passDrawList != null && passDrawList.Count > 0)
return; {
CommandBuffer cmd = CommandBufferPool.Get("GeoLayerPickBuffer"); CommandBuffer cmd = CommandBufferPool.Get("GeoLayerPickBuffer");
// 手动设置渲染目标并清理,避免 URP 隐式状态干扰
cmd.SetRenderTarget(passRTHandle); cmd.SetRenderTarget(passRTHandle);
cmd.ClearRenderTarget(true, true, new Color(0, 0, 0, 0)); cmd.ClearRenderTarget(true, true, new Color(0, 0, 0, 0));
if (drawDebugOverlay)
{
Debug.Log($"[GeoLayerPicker] 开始绘制 {passDrawList.Count} 个SubMesh");
Debug.Log($"[GeoLayerPicker] 渲染目标: {passRTHandle.rt.name}, 尺寸: {passRTHandle.rt.width}x{passRTHandle.rt.height}");
}
Camera cam = renderingData.cameraData.camera; Camera cam = renderingData.cameraData.camera;
Matrix4x4 viewMatrix = cam.worldToCameraMatrix; Matrix4x4 viewMatrix = cam.worldToCameraMatrix;
Matrix4x4 projMatrix = cam.projectionMatrix; Matrix4x4 projMatrix = cam.projectionMatrix;
@@ -541,18 +573,10 @@ namespace XericLibrary.PostProcess
drawMpb.SetInt(m_MatIDProperty, data.uniqueMatID); drawMpb.SetInt(m_MatIDProperty, data.uniqueMatID);
cmd.DrawMesh(data.mesh, data.matrix, passMaterial, data.subMeshIndex, 0, drawMpb); cmd.DrawMesh(data.mesh, data.matrix, passMaterial, data.subMeshIndex, 0, drawMpb);
if (GeoLayerPickerRenderPassFeature.Instance != null &&
GeoLayerPickerRenderPassFeature.Instance.enableDebugLog &&
(i == 0 || i == passDrawList.Count - 1))
{
Debug.Log($"[GeoLayerPicker] 绘制第{i}个SubMesh, MatID={data.uniqueMatID}, 材质={data.material?.name ?? "null"}");
}
} }
cmd.SetViewProjectionMatrices(viewMatrix, renderingData.cameraData.GetProjectionMatrix()); cmd.SetViewProjectionMatrices(viewMatrix, renderingData.cameraData.GetProjectionMatrix());
// 如果本帧需要回读,将数据安全地 Blit 到隔离缓冲区
if (requestReadback && passReadbackBuffer != null) if (requestReadback && passReadbackBuffer != null)
{ {
cmd.Blit(passRTHandle, passReadbackBuffer); cmd.Blit(passRTHandle, passReadbackBuffer);
@@ -566,8 +590,8 @@ namespace XericLibrary.PostProcess
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) if (drawDebugOverlay && debugOverlayMaterial != null && passRTHandle != null)
{ {
var feature = GeoLayerPickerRenderPassFeature.Instance; var feature = GeoLayerPickerRenderPassFeature.Instance;
@@ -576,11 +600,7 @@ namespace XericLibrary.PostProcess
RTHandle currentColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle; RTHandle currentColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle;
CommandBuffer debugCmd = CommandBufferPool.Get("GeoPickerDebugOverlay"); CommandBuffer debugCmd = CommandBufferPool.Get("GeoPickerDebugOverlay");
// 【核心 1】:使用 MaterialPropertyBlock 隔离参数
MaterialPropertyBlock debugMpb = new MaterialPropertyBlock(); MaterialPropertyBlock debugMpb = new MaterialPropertyBlock();
// 【修正 1】:直接使用字符串名称和 RTHandle 对象本身(RTHandle 隐式转为 Texture)
// 彻底避开 nameID (RenderTargetIdentifier) 的类型转换坑!
debugMpb.SetTexture(DebugMainTex, passRTHandle); debugMpb.SetTexture(DebugMainTex, passRTHandle);
debugMpb.SetVector(DebugRectProp, new Vector4( debugMpb.SetVector(DebugRectProp, new Vector4(
@@ -590,18 +610,16 @@ namespace XericLibrary.PostProcess
feature.sampleRect.height feature.sampleRect.height
)); ));
// 设置渲染目标为当前屏幕
CoreUtils.SetRenderTarget(debugCmd, currentColorTarget); CoreUtils.SetRenderTarget(debugCmd, currentColorTarget);
// 【修正 2】:DrawProcedural 必须显式传入 instanceCount (1) 作为第 6 个参数!
debugCmd.DrawProcedural( debugCmd.DrawProcedural(
Matrix4x4.identity, // 1. matrix Matrix4x4.identity,
debugOverlayMaterial, // 2. material debugOverlayMaterial,
0, // 3. shaderPass 0,
MeshTopology.Triangles, // 4. topology MeshTopology.Triangles,
3, // 5. vertexCount (全屏三角形) 3,
1, // 6. instanceCount (必须显式写 1!) 1,
debugMpb // 7. MaterialPropertyBlock debugMpb
); );
context.ExecuteCommandBuffer(debugCmd); context.ExecuteCommandBuffer(debugCmd);
@@ -758,17 +776,10 @@ namespace XericLibrary.PostProcess
if (pixel.a > 0.5f) if (pixel.a > 0.5f)
{ {
int decodedMatID = Mathf.RoundToInt(pixel.a);
if (enableDebugLog && i == 0)
{
Debug.Log($"[GeoLayerPicker] 像素({x},{y}), alpha={pixel.a:F4}, 解码MatID={decodedMatID}");
}
m_DecodedDataArray[i] = new PickedGeoData m_DecodedDataArray[i] = new PickedGeoData
{ {
isValid = true, isValid = true,
matID = decodedMatID, matID = Mathf.RoundToInt(pixel.a),
worldPos = new Vector3(pixel.r, pixel.g, pixel.b) worldPos = new Vector3(pixel.r, pixel.g, pixel.b)
}; };
m_ValidDataCount++; m_ValidDataCount++;
@@ -779,31 +790,6 @@ namespace XericLibrary.PostProcess
} }
} }
if (enableDebugLog)
{
Debug.Log($"[GeoLayerPicker] 回读完成!总像素: {count}, 有效拾取像素: {m_ValidDataCount}");
Dictionary<int, int> matIDCounts = new Dictionary<int, int>();
foreach (var data in m_DecodedDataArray)
{
if (data.isValid)
{
if (!matIDCounts.ContainsKey(data.matID))
{
matIDCounts[data.matID] = 0;
}
matIDCounts[data.matID]++;
}
}
Debug.Log("[GeoLayerPicker] 材质ID分布:");
foreach (var kvp in matIDCounts)
{
var mat = GetMaterialByID(kvp.Key);
Debug.Log($" MatID={kvp.Key} ({mat?.name ?? "未知"}): {kvp.Value} 像素");
}
}
MarkIslandsDirty(); MarkIslandsDirty();
} }