214 lines
5.5 KiB
C#
214 lines
5.5 KiB
C#
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
|
|
public class MultiImageBlender : MonoBehaviour
|
|
{
|
|
[Header("Base Settings")] public RectTransform container;
|
|
public Shader blendShader;
|
|
public string fileName = "MultiBlendResult";
|
|
public string saveFolder = "Exports";
|
|
|
|
[Header("Advanced Settings")] [Tooltip("Render order: from bottom to top (child index)")]
|
|
public bool useHierarchyOrder = true;
|
|
|
|
public Vector2Int outputResolution = new Vector2Int(1024, 1024);
|
|
|
|
private List<Image> targetImages = new List<Image>();
|
|
private RenderTexture compositeRT;
|
|
|
|
[ContextMenu("Execute Blend Export")]
|
|
public void ExecuteBlendExport()
|
|
{
|
|
// 初始化目标列表
|
|
CollectImages();
|
|
|
|
// 创建渲染目标
|
|
CreateRenderTexture();
|
|
|
|
// 初始化画布
|
|
ClearRenderTexture(compositeRT, Color.clear);
|
|
|
|
// 混合所有图片
|
|
foreach (Image img in targetImages)
|
|
{
|
|
if (!img.gameObject.activeInHierarchy) continue;
|
|
|
|
if (img.sprite == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// 准备纹理数据
|
|
Texture2D coloredTex = ProcessImageTexture(img);
|
|
Vector2 offset = CalculatePositionOffset(img.rectTransform);
|
|
|
|
// 执行混合
|
|
BlendLayer(coloredTex, img.color, offset);
|
|
|
|
DestroyImmediate(coloredTex);
|
|
}
|
|
|
|
// 保存结果
|
|
SaveResult();
|
|
|
|
// 清理资源
|
|
ReleaseResources();
|
|
}
|
|
|
|
void CollectImages()
|
|
{
|
|
targetImages.Clear();
|
|
|
|
if (useHierarchyOrder)
|
|
{
|
|
// 按层级顺序收集(从底到顶)
|
|
foreach (Transform child in container)
|
|
{
|
|
CollectRecursive(child);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 使用无序模式
|
|
Image[] images = container.GetComponentsInChildren<Image>();
|
|
targetImages.AddRange(images);
|
|
}
|
|
|
|
void CollectRecursive(Transform parent)
|
|
{
|
|
Image img = parent.GetComponent<Image>();
|
|
if (img != null) targetImages.Add(img);
|
|
|
|
foreach (Transform child in parent)
|
|
{
|
|
CollectRecursive(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
Texture2D ProcessImageTexture(Image image)
|
|
{
|
|
// 获取原始纹理
|
|
Texture2D sourceTex = image.sprite.texture;
|
|
|
|
// 应用颜色
|
|
Color[] pixels = sourceTex.GetPixels();
|
|
for (int i = 0; i < pixels.Length; i++)
|
|
{
|
|
pixels[i] = pixels[i] * image.color;
|
|
}
|
|
|
|
// 创建新纹理
|
|
Texture2D coloredTex = new Texture2D(
|
|
sourceTex.width,
|
|
sourceTex.height,
|
|
sourceTex.format,
|
|
false
|
|
);
|
|
|
|
coloredTex.SetPixels(pixels);
|
|
coloredTex.Apply();
|
|
|
|
return coloredTex;
|
|
}
|
|
|
|
Vector2 CalculatePositionOffset(RectTransform rt)
|
|
{
|
|
// 将局部坐标转换为容器空间坐标
|
|
Vector2 anchoredPos = rt.anchoredPosition;
|
|
|
|
// 计算标准化偏移(相对于输出分辨率)
|
|
return new Vector2(
|
|
anchoredPos.x / outputResolution.x,
|
|
anchoredPos.y / outputResolution.y
|
|
);
|
|
}
|
|
|
|
void CreateRenderTexture()
|
|
{
|
|
if (compositeRT != null)
|
|
compositeRT.Release();
|
|
|
|
compositeRT = new RenderTexture(
|
|
outputResolution.x,
|
|
outputResolution.y,
|
|
24,
|
|
RenderTextureFormat.ARGB32
|
|
);
|
|
}
|
|
|
|
void ClearRenderTexture(RenderTexture rt, Color clearColor)
|
|
{
|
|
RenderTexture.active = rt;
|
|
GL.Clear(true, true, clearColor);
|
|
RenderTexture.active = null;
|
|
}
|
|
|
|
void BlendLayer(Texture2D sourceTex, Color blendColor, Vector2 offset)
|
|
{
|
|
Material blendMat = new Material(blendShader);
|
|
blendMat.SetTexture("_MainTex", sourceTex);
|
|
blendMat.SetColor("_BlendColor", blendColor);
|
|
blendMat.SetVector("_BlendOffset", offset);
|
|
|
|
// 临时RT用于混合
|
|
RenderTexture tempRT = RenderTexture.GetTemporary(
|
|
compositeRT.width,
|
|
compositeRT.height,
|
|
0,
|
|
compositeRT.format
|
|
);
|
|
|
|
// 复制当前状态
|
|
Graphics.Blit(compositeRT, tempRT);
|
|
|
|
// 执行混合
|
|
Graphics.Blit(tempRT, compositeRT, blendMat);
|
|
|
|
// 清理临时RT
|
|
RenderTexture.ReleaseTemporary(tempRT);
|
|
DestroyImmediate(blendMat);
|
|
}
|
|
|
|
void SaveResult()
|
|
{
|
|
Texture2D outputTex = new Texture2D(
|
|
compositeRT.width,
|
|
compositeRT.height,
|
|
TextureFormat.ARGB32,
|
|
false
|
|
);
|
|
|
|
RenderTexture.active = compositeRT;
|
|
outputTex.ReadPixels(new Rect(0, 0, compositeRT.width, compositeRT.height), 0, 0);
|
|
outputTex.Apply();
|
|
|
|
// 保存文件
|
|
string dirPath = Path.Combine(Application.dataPath, saveFolder);
|
|
Directory.CreateDirectory(dirPath);
|
|
|
|
string filePath = Path.Combine(dirPath, fileName + ".png");
|
|
File.WriteAllBytes(filePath, outputTex.EncodeToPNG());
|
|
|
|
Debug.Log($"导出成功:{filePath}");
|
|
DestroyImmediate(outputTex);
|
|
}
|
|
|
|
void ReleaseResources()
|
|
{
|
|
if (compositeRT != null)
|
|
{
|
|
compositeRT.Release();
|
|
DestroyImmediate(compositeRT);
|
|
}
|
|
|
|
Resources.UnloadUnusedAssets();
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
ReleaseResources();
|
|
}
|
|
} |