合并两张纹理时如何对其中一张应用平移旋转缩放变换后再融合
纹理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
相关产品推荐
相关产品推荐

