Framwork/Assets/Test/ImageHierarchyBlender.cs

175 lines
5.6 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

namespace Runtime
{
// ImageHierarchyBlender.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.IO;
public class ImageHierarchyBlender : MonoBehaviour
{
public RectTransform parentContainer; // 父级容器
public Shader blendShader; // 混合Shader
public string fileName = "BlendedResult";
// 混合模式枚举
public enum BlendMode { AlphaBlend, Multiply, Screen }
public BlendMode blendMode = BlendMode.AlphaBlend;
[ContextMenu("Export Blended Image")]
public void ExportBlendedImage()
{
// 获取所有图形组件
List<Graphic> graphics = GetAllGraphics(parentContainer.gameObject);
// 创建RenderTexture
Vector2Int size = GetTotalSize(parentContainer);
RenderTexture rt = new RenderTexture(size.x, size.y, 0);
// 初始化画布
Texture2D finalTexture = InitializeCanvas(size);
Graphics.Blit(finalTexture, rt);
// 混合所有层
foreach (Graphic graphic in graphics)
{
if (!graphic.gameObject.activeInHierarchy) continue;
// 获取元素信息
Texture2D elementTex = CaptureGraphic(graphic);
Vector2 position = GetRelativePosition(graphic.rectTransform, parentContainer);
// 混合到画布
BlendLayer(ref finalTexture, elementTex, position, rt);
DestroyImmediate(elementTex);
}
// 保存结果
SaveTexture(finalTexture);
// 清理资源
RenderTexture.active = null;
DestroyImmediate(rt);
DestroyImmediate(finalTexture);
}
// 获取所有子物体的Graphic组件递归
List<Graphic> GetAllGraphics(GameObject parent)
{
List<Graphic> graphics = new List<Graphic>();
Graphic parentGraphic = parent.GetComponent<Graphic>();
if (parentGraphic != null) graphics.Add(parentGraphic);
foreach (Transform child in parent.transform)
{
graphics.AddRange(GetAllGraphics(child.gameObject));
}
return graphics;
}
// 计算容器总尺寸
Vector2Int GetTotalSize(RectTransform rectTransform)
{
return new Vector2Int(
Mathf.RoundToInt(rectTransform.rect.width),
Mathf.RoundToInt(rectTransform.rect.height)
);
}
// 初始化画布
Texture2D InitializeCanvas(Vector2Int size)
{
Texture2D tex = new Texture2D(size.x, size.y, TextureFormat.ARGB32, false);
Color[] pixels = new Color[size.x * size.y];
for (int i = 0; i < pixels.Length; i++) pixels[i] = Color.clear;
tex.SetPixels(pixels);
tex.Apply();
return tex;
}
// 捕获单个图形元素
Texture2D CaptureGraphic(Graphic graphic)
{
// 创建临时RenderTexture
RenderTexture rt = new RenderTexture(
(int)graphic.rectTransform.rect.width,
(int)graphic.rectTransform.rect.height, 0
);
// 渲染元素
graphic.material = null; // 重置材质
GraphicCapture(graphic, rt);
// 转换为Texture2D
Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);
RenderTexture.active = rt;
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
tex.Apply();
RenderTexture.active = null;
DestroyImmediate(rt);
return tex;
}
// 渲染单个图形到RenderTexture
void GraphicCapture(Graphic graphic, RenderTexture rt)
{
Material material = new Material(blendShader);
material.mainTexture = graphic.mainTexture;
material.color = graphic.color;
Graphics.SetRenderTarget(rt);
GL.PushMatrix();
GL.LoadOrtho();
material.SetPass(0);
GL.Begin(GL.QUADS);
GL.TexCoord2(0, 0); GL.Vertex3(0, 0, 0);
GL.TexCoord2(1, 0); GL.Vertex3(1, 0, 0);
GL.TexCoord2(1, 1); GL.Vertex3(1, 1, 0);
GL.TexCoord2(0, 1); GL.Vertex3(0, 1, 0);
GL.End();
GL.PopMatrix();
}
// 获取相对位置
Vector2 GetRelativePosition(RectTransform child, RectTransform parent)
{
Vector2 localPosition = child.anchoredPosition;
// 处理锚点差异
Vector2 parentPivot = parent.pivot;
Vector2 childAnchorMin = child.anchorMin;
Vector2 parentSize = parent.rect.size;
return new Vector2(
localPosition.x + (childAnchorMin.x - parentPivot.x) * parentSize.x,
localPosition.y + (childAnchorMin.y - parentPivot.y) * parentSize.y
);
}
// 混合单层
void BlendLayer(ref Texture2D baseTex, Texture2D blendTex, Vector2 position, RenderTexture rt)
{
Material blendMaterial = new Material(blendShader);
blendMaterial.SetTexture("_BlendTex", blendTex);
blendMaterial.SetVector("_Position", position);
blendMaterial.SetFloat("_BlendMode", (float)blendMode);
Graphics.Blit(baseTex, rt, blendMaterial);
RenderTexture.active = rt;
baseTex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
baseTex.Apply();
}
// 保存为PNG
void SaveTexture(Texture2D tex)
{
byte[] bytes = tex.EncodeToPNG();
string path = Path.Combine(Application.streamingAssetsPath, "Exports", fileName + ".png");
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllBytes(path, bytes);
Debug.Log($"Saved to: {path}");
}
}
}