blender-uv-texturing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Blender UV Texturing

Blender UV纹理处理

This skill fills the gap between “assign a material” and “the supplied texture pack actually fits the model.” It is mandatory for template/atlas-driven assets.
此技能填补了“分配材质”与“提供的纹理包真正适配模型”之间的空白。对于基于模板/图集的资产来说,这是必不可少的步骤。

Decision tree

决策树

What does the texture represent?
├── Whole object from front/reference → Project-from-View style UVs from the validation camera
├── Atlas with separate parts         → crop/map each part to its own UV island/rectangle
├── Repeating material                → generated/object coords or tiled UVs
├── Face/expression decal             → alpha material plane or projected UV island; no black background
├── Roughness/bump/normal map         → Non-Color data, correct node type
└── Lightmap                          → separate UV/lightmap channel or optional multiply helper; not emission
纹理代表什么?
├── 从正面/参考图看的完整对象 → 从验证相机生成“从视图投影”风格的UV
├── 包含独立部件的图集 → 将每个部件裁剪/映射到对应的UV岛/矩形区域
├── 可重复材质 → 使用生成/对象坐标或 tiled UV
├── 面部/表情贴花 → 使用带alpha的材质平面或投影UV岛;无黑色背景
├── 粗糙度/凹凸/法线贴图 → 非颜色数据,使用正确的节点类型
└── 光照贴图 → 使用独立的UV/光照贴图通道或可选的乘法辅助节点;不使用发光材质

Non-negotiable rules

不可违反的规则

  1. Image textures need a material node setup to render/export; viewport UV display alone is not enough.
  2. Basecolor/albedo = sRGB. Roughness, metallic, bump, normal, AO/lightmap = Non-Color.
  3. Atlas textures must be mapped by region. Never apply a full atlas to every mesh part.
  4. Alpha decals must use alpha-connected material settings (
    BLEND
    ,
    Alpha Hashed
    , or
    Alpha Clip
    ) and a keyed/correct PNG. Do not leave black planes.
  5. For GLB, keep to exporter-recognized nodes where possible: Principled BSDF with Image Texture inputs, UVs, normals, tangents.
  6. Validate with a checker texture or overlay render before final material tuning.
  1. 图像纹理需要材质节点设置才能渲染/导出;仅在视口显示UV是不够的。
  2. 基础色/反照率 = sRGB。粗糙度、金属度、凹凸、法线、AO/光照贴图 = 非颜色(Non-Color)。
  3. 图集纹理必须按区域映射。绝不能将整张图集应用到每个网格部件。
  4. Alpha贴花必须使用连接alpha的材质设置(
    BLEND
    Alpha Hashed
    Alpha Clip
    ),并使用抠图正确的PNG图片。不能保留黑色平面。
  5. 针对GLB格式,尽可能使用导出器可识别的节点:带图像纹理输入、UV、法线、切线的Principled BSDF。
  6. 在最终材质调整前,使用棋盘格纹理或叠加渲染进行验证。

Recipes

操作方案

Create front-projected UVs from world X/Z bounds

从世界X/Z边界创建正面投影UV

python
import bpy

def assign_front_projected_uv(obj_name, uv_name='UV_front_projected'):
    obj = bpy.data.objects[obj_name]
    mesh = obj.data
    uv = mesh.uv_layers.get(uv_name) or mesh.uv_layers.new(name=uv_name)
    mesh.uv_layers.active = uv
    xs = [v.co.x for v in mesh.vertices]
    zs = [v.co.z for v in mesh.vertices]
    minx, maxx = min(xs), max(xs)
    minz, maxz = min(zs), max(zs)
    dx = max(maxx - minx, 1e-8)
    dz = max(maxz - minz, 1e-8)
    for poly in mesh.polygons:
        for li in poly.loop_indices:
            co = mesh.vertices[mesh.loops[li].vertex_index].co
            uv.data[li].uv = ((co.x - minx) / dx, (co.z - minz) / dz)
    mesh.update()
python
import bpy

def assign_front_projected_uv(obj_name, uv_name='UV_front_projected'):
    obj = bpy.data.objects[obj_name]
    mesh = obj.data
    uv = mesh.uv_layers.get(uv_name) or mesh.uv_layers.new(name=uv_name)
    mesh.uv_layers.active = uv
    xs = [v.co.x for v in mesh.vertices]
    zs = [v.co.z for v in mesh.vertices]
    minx, maxx = min(xs), max(xs)
    minz, maxz = min(zs), max(zs)
    dx = max(maxx - minx, 1e-8)
    dz = max(maxz - minz, 1e-8)
    for poly in mesh.polygons:
        for li in poly.loop_indices:
            co = mesh.vertices[mesh.loops[li].vertex_index].co
            uv.data[li].uv = ((co.x - minx) / dx, (co.z - minz) / dz)
    mesh.update()

Map a mesh to a rectangle in an atlas

将网格映射到图集的矩形区域

Atlas rectangle is
[u0, v0, u1, v1]
in normalized UV coordinates. Use this after creating local 0–1 UVs.
python
def remap_uv_rect(obj_name, rect, uv_name=None):
    obj = bpy.data.objects[obj_name]
    layer = obj.data.uv_layers.get(uv_name) if uv_name else obj.data.uv_layers.active
    u0, v0, u1, v1 = rect
    for item in layer.data:
        u, v = item.uv
        item.uv = (u0 + u * (u1-u0), v0 + v * (v1-v0))
    obj.data.update()
图集矩形在归一化UV坐标中为
[u0, v0, u1, v1]
。在创建本地0–1 UV后使用此方法。
python
def remap_uv_rect(obj_name, rect, uv_name=None):
    obj = bpy.data.objects[obj_name]
    layer = obj.data.uv_layers.get(uv_name) if uv_name else obj.data.uv_layers.active
    u0, v0, u1, v1 = rect
    for item in layer.data:
        u, v = item.uv
        item.uv = (u0 + u * (u1-u0), v0 + v * (v1-v0))
    obj.data.update()

Image texture material with correct color spaces

带正确色彩空间的图像纹理材质

python
import bpy

def image(path, colorspace):
    img = bpy.data.images.load(path, check_existing=True)
    img.colorspace_settings.name = colorspace
    return img

def make_pbr_texture_material(name, basecolor, roughness=None, normal_or_bump=None, alpha=False):
    mat = bpy.data.materials.new(name)
    mat.use_nodes = True
    nt = mat.node_tree
    bsdf = nt.nodes.get('Principled BSDF')
    tex = nt.nodes.new('ShaderNodeTexImage')
    tex.image = image(basecolor, 'sRGB')
    nt.links.new(tex.outputs['Color'], bsdf.inputs['Base Color'])
    if alpha and 'Alpha' in bsdf.inputs:
        nt.links.new(tex.outputs['Alpha'], bsdf.inputs['Alpha'])
        mat.blend_method = 'BLEND'
    if roughness:
        r = nt.nodes.new('ShaderNodeTexImage')
        r.image = image(roughness, 'Non-Color')
        nt.links.new(r.outputs['Color'], bsdf.inputs['Roughness'])
    if normal_or_bump:
        btex = nt.nodes.new('ShaderNodeTexImage')
        btex.image = image(normal_or_bump, 'Non-Color')
        bump = nt.nodes.new('ShaderNodeBump')
        bump.inputs['Strength'].default_value = 0.02
        nt.links.new(btex.outputs['Color'], bump.inputs['Height'])
        nt.links.new(bump.outputs['Normal'], bsdf.inputs['Normal'])
    return mat
python
import bpy

def image(path, colorspace):
    img = bpy.data.images.load(path, check_existing=True)
    img.colorspace_settings.name = colorspace
    return img

def make_pbr_texture_material(name, basecolor, roughness=None, normal_or_bump=None, alpha=False):
    mat = bpy.data.materials.new(name)
    mat.use_nodes = True
    nt = mat.node_tree
    bsdf = nt.nodes.get('Principled BSDF')
    tex = nt.nodes.new('ShaderNodeTexImage')
    tex.image = image(basecolor, 'sRGB')
    nt.links.new(tex.outputs['Color'], bsdf.inputs['Base Color'])
    if alpha and 'Alpha' in bsdf.inputs:
        nt.links.new(tex.outputs['Alpha'], bsdf.inputs['Alpha'])
        mat.blend_method = 'BLEND'
    if roughness:
        r = nt.nodes.new('ShaderNodeTexImage')
        r.image = image(roughness, 'Non-Color')
        nt.links.new(r.outputs['Color'], bsdf.inputs['Roughness'])
    if normal_or_bump:
        btex = nt.nodes.new('ShaderNodeTexImage')
        btex.image = image(normal_or_bump, 'Non-Color')
        bump = nt.nodes.new('ShaderNodeBump')
        bump.inputs['Strength'].default_value = 0.02
        nt.links.new(btex.outputs['Color'], bump.inputs['Height'])
        nt.links.new(bump.outputs['Normal'], bsdf.inputs['Normal'])
    return mat

Bake target setup

烘焙目标设置

Blender baking requires a UV map and an active Image Texture node or color attribute as the bake target. Use Cycles for baking.
python
import bpy

obj = bpy.data.objects['GEO-target']
bpy.context.scene.render.engine = 'CYCLES'
img = bpy.data.images.new('BAKE_target', 2048, 2048, alpha=True)
mat = obj.data.materials[0]
mat.use_nodes = True
node = mat.node_tree.nodes.new('ShaderNodeTexImage')
node.image = img
mat.node_tree.nodes.active = node
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
bpy.ops.object.bake(type='DIFFUSE', pass_filter={'COLOR'}, margin=16)
img.filepath_raw = '/tmp/bake_target.png'
img.file_format = 'PNG'
img.save()
Blender烘焙需要UV贴图和活动的图像纹理节点或颜色属性作为烘焙目标。使用Cycles进行烘焙。
python
import bpy

obj = bpy.data.objects['GEO-target']
bpy.context.scene.render.engine = 'CYCLES'
img = bpy.data.images.new('BAKE_target', 2048, 2048, alpha=True)
mat = obj.data.materials[0]
mat.use_nodes = True
node = mat.node_tree.nodes.new('ShaderNodeTexImage')
node.image = img
mat.node_tree.nodes.active = node
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
bpy.ops.object.bake(type='DIFFUSE', pass_filter={'COLOR'}, margin=16)
img.filepath_raw = '/tmp/bake_target.png'
img.file_format = 'PNG'
img.save()

Closed/extruded surface coverage gate

闭合/挤压曲面覆盖检查

For closed or extruded assets, do not stop at front projection. Use
closed-surface-uv-coverage
to verify front cap, back cap, and sidewall material/UV/generated coverage separately. Back/side curve overlays are accents, not texture fill.
对于闭合或挤压的资产,不能仅停留在正面投影。使用
closed-surface-uv-coverage
分别验证正面盖、背面盖和侧壁的材质/UV/生成覆盖情况。背面/侧面曲线叠加是装饰,而非纹理填充。

Validation checklist

验证清单

  • UV layer exists and is active.
  • Checker texture shows no obvious stretching on front-facing parts.
  • Atlas rectangles are per-part, not whole-atlas everywhere.
  • Roughness/bump/normal/lightmap color spaces are Non-Color.
  • Alpha material has blend mode set and no black backing plane.
  • Base GLB embeds/exports expected images and excludes reference planes.
  • A front overlay render confirms the texture aligns with the source template.
  • UV层已存在且处于活动状态。
  • 棋盘格纹理显示正面部件无明显拉伸。
  • 图集矩形按部件分配,而非整张图集应用到所有部件。
  • 粗糙度/凹凸/法线/光照贴图的色彩空间为非颜色(Non-Color)。
  • Alpha材质已设置混合模式,无黑色背景平面。
  • 基础GLB文件嵌入/导出预期图像,排除参考平面。
  • 正面叠加渲染确认纹理与源模板对齐。

Sources distilled

参考来源

  • Blender Manual: UV/Image texture workflow requires material nodes for rendered texture output.
  • Blender Manual: Image Texture node uses active UV map when Vector is unconnected.
  • Blender Manual: Cycles baking requires a UV map and active Image Texture/Color Attribute target.
  • Blender Manual: glTF exporter supports meshes, UVs, textures, and materials based mainly on Principled BSDF.
  • Khronos glTF PBR: base color, metallic/roughness, normals and related maps are core concepts for realtime transfer.
  • Blender手册:UV/图像纹理工作流需要材质节点才能输出可渲染的纹理。
  • Blender手册:当Vector未连接时,图像纹理节点使用活动UV贴图。
  • Blender手册:Cycles烘焙需要UV贴图和活动的图像纹理/颜色属性目标。
  • Blender手册:glTF导出器主要支持基于Principled BSDF的网格、UV、纹理和材质。
  • Khronos glTF PBR:基础色、金属度/粗糙度、法线及相关贴图是实时传输的核心概念。