diff --git a/README.md b/README.md index a8f7f18..a567a99 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,38 @@ # Unity 屏幕空间后处理阶段检查器-模型数据提取器 -依赖 [MaterialFunctionLibrary](https://gitea.xeric.cc/LiRuochen_WorkFlow/MaterialFunctionLibrary) 插件。 \ No newline at end of file +依赖 [MaterialFunctionLibrary](https://gitea.xeric.cc/LiRuochen_WorkFlow/MaterialFunctionLibrary) 插件。 + +插件能力: + +1. 快速抓取到一个物体上多个不同材质分类区域在屏幕特定区域内的占比,中心位置坐标等信息 +2. 支持webgl平台 + +## 使用示例 + +``` csharp + +public class GeoLayerPicker : MonoBehaviour +{ + public List MeshFilters; + public void Start() + { + GeoLayerPickerRenderPassFeature.Instance?.AddGeoMeshes(MeshFilters); // 将模型设置到处理器中 + } + public void LateUpdate() + { + var islands = GeoLayerPickerRenderPassFeature.Instance.GetMaterialIslands(); + foreach (var island in islands) + { + Debug.Log($"材质: {island.GetMaterialName()} (ID:{island.matID})"); + Debug.Log($" 像素数: {island.totalPixelCount}"); + Debug.Log($" 中心世界坐标: {island.centerWorldPos}"); + Debug.Log($" 中心像素坐标: {island.centerPixelPos}"); + } + } +} + +``` + +处理器中已经包含了必要的转换功能,比如 `island.GetCenterRectAnchoredPosition(rectTransform)` 就可以得到ui坐标。 + + diff --git a/Runtime/MeshDetection_URP/GeoLayerPickerRenderPassFeature.cs b/Runtime/MeshDetection_URP/GeoLayerPickerRenderPassFeature.cs index a572a3c..d8fc036 100644 --- a/Runtime/MeshDetection_URP/GeoLayerPickerRenderPassFeature.cs +++ b/Runtime/MeshDetection_URP/GeoLayerPickerRenderPassFeature.cs @@ -73,6 +73,9 @@ namespace XericLibrary.PostProcess public int totalPixelCount; public Vector2 centerPixelPos; public Vector3 centerWorldPos; + + public Vector3 minWorldPos; + public Vector3 maxWorldPos; public bool isValid => matID > 0 && segments.Count > 0; public Material GetMaterial() @@ -131,6 +134,58 @@ namespace XericLibrary.PostProcess return new Vector2(anchoredX, anchoredY); } + + public Vector3 GetCenterWorldPosition() + { + return centerWorldPos; + } + + public Vector2 GetScreenPosition(Camera camera = null) + { + if (camera == null) + { + camera = Camera.main; + } + if (camera == null) + return Vector2.zero; + + return camera.WorldToScreenPoint(centerWorldPos); + } + + public Vector2 GetViewportPosition(Camera camera = null) + { + if (camera == null) + { + camera = Camera.main; + } + if (camera == null) + return Vector2.zero; + + return camera.WorldToViewportPoint(centerWorldPos); + } + + public Bounds GetWorldBounds() + { + Bounds bounds = new Bounds(centerWorldPos, Vector3.zero); + bounds.Encapsulate(minWorldPos); + bounds.Encapsulate(maxWorldPos); + return bounds; + } + + public float GetWorldVolume() + { + Vector3 size = maxWorldPos - minWorldPos; + return Mathf.Abs(size.x * size.y * size.z); + } + + public float GetWorldArea() + { + Vector2 size = new Vector2( + Mathf.Abs(maxWorldPos.x - minWorldPos.x), + Mathf.Abs(maxWorldPos.z - minWorldPos.z) + ); + return size.x * size.y; + } } /// @@ -464,6 +519,8 @@ namespace XericLibrary.PostProcess { island.centerPixelPos = Vector2.zero; island.centerWorldPos = Vector3.zero; + island.minWorldPos = Vector3.zero; + island.maxWorldPos = Vector3.zero; continue; } @@ -476,10 +533,25 @@ namespace XericLibrary.PostProcess island.centerPixelPos = new Vector2(avgCol, avgRow); - int centerX = Mathf.Clamp(Mathf.RoundToInt(avgCol), 0, width - 1); - int centerY = Mathf.Clamp(Mathf.RoundToInt(avgRow), 0, height - 1); - int centerIndex = centerY * width + centerX; + Dictionary rowPixelCounts = new Dictionary(); + foreach (var seg in island.segments) + { + if (!rowPixelCounts.ContainsKey(seg.rowIndex)) + { + rowPixelCounts[seg.rowIndex] = 0; + } + rowPixelCounts[seg.rowIndex] += seg.length; + } + int maxRowIndex = rowPixelCounts.OrderByDescending(kvp => kvp.Value).First().Key; + + var segmentsInMaxRow = island.segments.Where(s => s.rowIndex == maxRowIndex).ToList(); + MaterialSegment maxSegment = segmentsInMaxRow.OrderByDescending(s => s.length).First(); + + int centerX = (maxSegment.colStart + maxSegment.colEnd) / 2; + int centerY = maxRowIndex; + + int centerIndex = centerY * width + centerX; if (centerIndex >= 0 && centerIndex < m_DecodedDataArray.Length) { island.centerWorldPos = m_DecodedDataArray[centerIndex].worldPos; @@ -488,6 +560,26 @@ namespace XericLibrary.PostProcess { island.centerWorldPos = Vector3.zero; } + + island.minWorldPos = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); + island.maxWorldPos = new Vector3(float.MinValue, float.MinValue, float.MinValue); + + foreach (var seg in island.segments) + { + for (int col = seg.colStart; col <= seg.colEnd; col++) + { + int index = seg.rowIndex * width + col; + if (index < 0 || index >= m_DecodedDataArray.Length) + continue; + + var pixelData = m_DecodedDataArray[index]; + if (pixelData.isValid && pixelData.matID == island.matID) + { + island.minWorldPos = Vector3.Min(island.minWorldPos, pixelData.worldPos); + island.maxWorldPos = Vector3.Max(island.maxWorldPos, pixelData.worldPos); + } + } + } } } diff --git a/Runtime/MeshDetection_URP/ScreenOverrideRect.shader b/Runtime/MeshDetection_URP/ScreenOverrideRect.shader index 71899d2..b9f3330 100644 --- a/Runtime/MeshDetection_URP/ScreenOverrideRect.shader +++ b/Runtime/MeshDetection_URP/ScreenOverrideRect.shader @@ -75,9 +75,10 @@ Shader "Hidden/XericLibrary/GeoLayerPicker/ScreenOverrideRect" } // 将世界坐标映射为可见颜色 - float3 debugColor = frac(col.rgb * 0.1); - float matIDColor = frac(col.a * 0.05); - debugColor.r = lerp(debugColor.r, matIDColor, 0.5); + float3 debugColor = abs(sin(col.rgb * float3(0.03, 0.1, 0.05))) * 0.5; + float3 debugColor2 = abs(cos(col.rgb * float3(0.05, 0.09, 0.07))) * 0.5 + 0.5; + float matIDColor = frac(col.a * 0.07); + debugColor = lerp(debugColor, debugColor2, matIDColor); return float4(debugColor, 0.9); } ENDHLSL