Texture2DExtension

作者:追风剑情 发布于:2025-4-30 11:47 分类:Unity3d

using UnityEngine;
/// <summary>
/// Texture2D 扩展方法
/// </summary>
public static class Texture2DExtension
{
    // 克隆
    public static Texture2D Clone(this Texture2D texture)
    {
        if (texture == null)
            return null;
        if (!texture.isReadable)
        {
            Debug.LogError("texture isReadable is false.");
            return null;
        }
        int w = texture.width;
        int h = texture.height;
        Color[] colors = texture.GetPixels(0, 0, w, h);
        Texture2D tex = new Texture2D(w, h, texture.format, false);
        tex.SetPixels(0, 0, w, h, colors);
        tex.Apply();
        return tex;
    }

    /// <summary>
    /// 绘制贴花
    /// </summary>
    /// <param name="texture">必须勾选上Read/Write</param>
    /// <param name="uv">贴图的uv坐标</param>
    /// <param name="decal">贴花图片</param>
    /// <param name="scale">缩放系数</param>
    public static void DrawDecal(this Texture2D texture, Vector2 uv, Texture2D decal, float scale=1.0f)
    {
        if (decal == null)
        {
            Debug.LogError("decal texture is null.");
            return;
        }
        if (!decal.isReadable)
        {
            Debug.LogError("decal isReadable is false.");
            return;
        }
        //限制下缩放区间
        scale = Mathf.Clamp(scale, 0.001f, 100);
        //计算贴花绘制区域
        int w = texture.width;
        int h = texture.height;
        //缩放后的贴花宽高
        int dw = (int)(decal.width * scale);
        int dh = (int)(decal.height * scale);
        //贴花图片的中心点对齐uv坐标
        int x = (int)(w * uv.x) - dw / 2;
        int y = (int)(h * uv.y) - dh / 2;
        x = Mathf.Clamp(x, 0, w);
        y = Mathf.Clamp(y, 0, h);
        int ex = x + dw;
        int ey = y + dh;
        ex = Mathf.Clamp(ex, 0, w);
        ey = Mathf.Clamp(ey, 0, h);
        //绘制贴花
        for (int dx=0 ; x < ex; x++, dx++)
        {
            for (int dy=0, j=y; j < ey; j++, dy++)
            {
                //采样坐标
                int sx = (int)(dx / scale);
                int sy = (int)(dy / scale);
                Color dp = decal.GetPixel(sx, sy);
                if (dp.a == 0)
                    continue;
                texture.SetPixel(x, j, dp);
            }
        }
        texture.Apply();
    }

    // 绘制贴花
    public static void DrawDecal(this Texture2D texture, RaycastHit hit, Texture2D decal, float scale = 1.0f)
    {
        //模型需使用MeshCollider并且Convex设为false,否则textureCoord始终返回(0,0)
        if (!(hit.collider is MeshCollider))
        {
            Debug.LogError("must use MeshCollider.");
            return;
        }
        if ((hit.collider as MeshCollider).convex)
        {
            Debug.LogError("do not check 'convex'");
            return;
        }
        Vector2 uv = hit.textureCoord;
        DrawDecal(texture, uv, decal, scale);
    }
}

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号