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

如何在Metal中固定采样纹理三角区域绘制到目标画布?

解决方案:将纹理固定三角区域映射到任意目标三角

要实现把纹理的同一固定三角区域绘制到所有目标三角中,核心是用重心坐标(Barycentric Coordinates)建立目标三角与纹理固定三角的相对位置映射,而不是直接用顶点坐标对应纹理坐标。以下是具体修改步骤和代码:

1. 定义必要的结构体(共享着色器头文件)

首先补充结构体,用于传递纹理固定三角的坐标和顶点重心坐标:

// 存储纹理上固定三角的三个顶点纹理坐标
struct FixedTriangleTexCoords {
    float2 p0;
    float2 p1;
    float2 p2;
};

struct Uniforms {
    float4 color;
    bool drawWithTexture;
    FixedTriangleTexCoords fixedTriangle; // 新增:纹理固定三角的坐标
};

// 修改顶点输出结构体,加入重心坐标
struct VertexOut {
    float4 position [[position]];
    float2 barycentric; // 重心坐标,用于插值计算相对位置
};

2. 修改顶点着色器:传递重心坐标

给每个目标三角的顶点分配对应的重心坐标,硬件会自动在三角内部插值这些坐标:

vertex VertexOut vertex_main(const device float2* position [[buffer(0)]],
                             uint vid [[vertex_id]]) {
    VertexOut out;
    float2 pos = position[vid];
    out.position = float4(pos, 0, 1);
    
    // 按顶点顺序分配重心坐标,顺序需与传入的顶点数据对应
    switch(vid) {
        case 0:
            out.barycentric = float2(1.0, 0.0);
            break;
        case 1:
            out.barycentric = float2(0.0, 1.0);
            break;
        case 2:
            out.barycentric = float2(0.0, 0.0);
            break;
        default:
            out.barycentric = float2(0.0, 0.0);
    }
    return out;
}

3. 修改片段着色器:基于重心坐标采样固定纹理区域

利用插值后的重心坐标,计算当前像素在纹理固定三角中的对应位置,再进行采样:

fragment float4 fragment_main(VertexOut in [[stage_in]],
                              texture2d<float> tex [[texture(0)]],
                              constant Uniforms& uniforms [[buffer(1)]]) {
    constexpr sampler s(address::repeat, filter::linear);
    if (uniforms.drawWithTexture) {
        // 用重心坐标插值计算纹理固定三角的采样坐标
        float w = 1.0 - in.barycentric.x - in.barycentric.y;
        float2 texCoord = w * uniforms.fixedTriangle.p0 + 
                          in.barycentric.x * uniforms.fixedTriangle.p1 + 
                          in.barycentric.y * uniforms.fixedTriangle.p2;
        
        // 处理Y轴翻转(根据你的纹理实际存储方向调整)
        texCoord[1] = 1.0 - texCoord[1];
        return tex.sample(s, texCoord);
    } else {
        return uniforms.color;
    }
}

关键说明

  • 重心坐标作用:硬件会自动在三角内插值重心坐标,每个像素的重心坐标代表它在目标三角内的相对位置,用这个位置去映射纹理固定三角,就能实现所有目标三角复用同一纹理区域。
  • CPU端配置:需要在CPU端设置fixedTriangle的三个坐标,比如要采样纹理左上角的三角,可设p0=(0,0), p1=(1,0), p2=(0,1)(根据你的纹理坐标系调整)。
  • 顶点顺序对应:顶点着色器中重心坐标的分配顺序,必须与你传入的顶点数据顺序一致,否则会出现映射错位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 10:03:30