You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

合并两张纹理时如何对其中一张应用平移旋转缩放变换后再融合

纹理TRS变换后合并实现方案

核心思路

对需要变换的纹理B,我们采用逆变换采样的逻辑实现,避免直接对纹理B的像素做正变换出现像素空洞的问题:遍历输出纹理的所有像素位置,通过逆变换矩阵计算当前位置是否落在变换后的纹理B范围内,若命中则读取纹理B的对应像素值覆盖到输出纹理。

实现代码

using UnityEngine;

public class TextureCombiner : MonoBehaviour
{
    /// <summary>
    /// 带TRS变换的纹理合并方法
    /// </summary>
    /// <param name="_textureA">底图纹理</param>
    /// <param name="_textureB">需要做变换后叠加的纹理</param>
    /// <param name="translateX">纹理B的水平平移量</param>
    /// <param name="translateY">纹理B的垂直平移量</param>
    /// <param name="rotateAngle">纹理B的旋转角度(弧度制,顺时针为正)</param>
    /// <param name="scaleX">纹理B的水平缩放系数</param>
    /// <param name="scaleY">纹理B的垂直缩放系数</param>
    /// <returns>合并后的纹理</returns>
    Texture2D CombineTexturesWithTRS(Texture2D _textureA, Texture2D _textureB, float translateX = 0, float translateY = 0, float rotateAngle = 0, float scaleX = 1, float scaleY = 1)
    {
        // 初始化结果纹理,和底图尺寸一致
        Texture2D textureResult = new Texture2D(_textureA.width, _textureA.height, TextureFormat.RGBA32, false);
        textureResult.SetPixels(_textureA.GetPixels());

        // 计算纹理B的中心坐标,作为变换锚点
        float bCenterX = _textureB.width / 2f;
        float bCenterY = _textureB.height / 2f;

        // 构造TRS变换矩阵,再求逆矩阵用于反向采样
        Matrix4x4 trsMatrix = Matrix4x4.TRS(new Vector3(translateX, translateY, 0), Quaternion.Euler(0, 0, rotateAngle * Mathf.Rad2Deg), new Vector3(scaleX, scaleY, 1));
        Matrix4x4 inverseMatrix = trsMatrix.inverse;

        // 遍历结果纹理所有像素
        for (int x = 0; x < textureResult.width; x++)
        {
            for (int y = 0; y < textureResult.height; y++)
            {
                // 将当前像素坐标转换为以纹理B变换后的位置为参考的坐标
                Vector3 resultPos = new Vector3(x, y, 0);
                // 逆变换得到对应纹理B的原始坐标
                Vector3 bLocalPos = inverseMatrix.MultiplyPoint(resultPos);
                // 转换为纹理B的像素坐标(默认纹理原点为左下角,和Unity原生规则对齐)
                float bPixelX = bLocalPos.x + bCenterX;
                float bPixelY = bLocalPos.y + bCenterY;

                // 判断坐标是否在纹理B的合法范围内
                if (bPixelX >= 0 && bPixelX < _textureB.width && bPixelY >= 0 && bPixelY < _textureB.height)
                {
                    Color bColor = _textureB.GetPixelBilinear(bPixelX / _textureB.width, bPixelY / _textureB.height);
                    if (bColor.a > 0.01f)
                    {
                        textureResult.SetPixel(x, y, bColor);
                    }
                }
            }
        }

        textureResult.Apply();
        return textureResult;
    }
}

优化说明

  • 如果你处理的是大尺寸纹理,CPU遍历像素的性能会比较差,可以改用GPU方案:把两张纹理传入Shader,在片元着色器中完成TRS变换和采样,最后用RenderTexture接收结果,性能会提升数倍。
  • 代码中默认变换锚点是纹理B的中心,如果需要调整锚点位置,修改bCenterX和bCenterY的取值即可。
  • 如果需要更精准的像素采样,把GetPixelBilinear换成GetPixel即可,前者是双线性采样,变换后的边缘会更平滑。

内容的提问来源于stack exchange,提问作者Dakso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:15:03