【Blender 开发】程序化生成立体像素画 Logo

480 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 4 天,点击查看活动详情

效果图

ShaderJoyCubes.png

进一步的修改可以得到如下效果

ShaderJoyVoxel_720.png

!3&&!4_filtered.png

ShaderJoy_filtered.png

具体步骤

准备好材质

首先,我们使用名为 obj_color 的材质。如果它不存在的话,就创建它。

注意: 这种材质用于所有立方体。该材质将使用从立方体读取 custom_color 属性节点。

material_name = 'obj_color'
mats = bpy.data.materials
material = mats.get(material_name, mats.new(material_name))

准备好存放立方体的集合

我打算将所有立方体对象放在一个 COLLECTION

# 向主数据库添加一个名为 `pixels` 新的 collection
collection = bpy.data.collections.new("pixels") 
# 添加为 Scene Collection 的子 Collection
bpy.context.scene.collection.children.link(collection)

image.png

创建原型立方体作为网格数据来源

创建为 make_cube 函数所用的原型立方体。这样我们之后就可以重用该网格,避免每次都创建一个新的网格。

bpy.ops.mesh.primitive_cube_add()
default_cube = bpy.context.object
default_cube.data.materials.append(material)
mesh = default_cube.data # `bpy_types.Mesh'

创建一个立方体

在给定的位置用给定的颜色创建一个立方体

  • location: 立方体的位置
  • color: 立方体的颜色

首先,我们把颜色三个通道的组成部分分开,然后将从 RGB 颜色空间其转化为 HSV 颜色空间。之后,人为设定立方体的高度(该高度,基于 HSV 的 v 分量)。

在以上基础上,再通过原型立方体的数据块创建立方体对象(Object),并赋予指定的 尺寸位置颜色

def make_cube(location, color):
    x, y, unused_z = location

    r, g, b = color[0:3]
    h, s, v = colorsys.rgb_to_hsv(r, g, b)

    size = 16 * v

    location = [x, y, size]
    scale = [0.9, 0.9, size]
    
    # 取名为 `pixel` (如果重名的话 Blender 会自动重命名)
    cube = bpy.data.objects.new(name='pixel', object_data=mesh)
    cube.scale = scale
    cube.location = location

    # 为该对象指定一个 “custom_color” 属性值
    # 用于立方体颜色的材质
    cube['custom_color'] = color
    collection.objects.link(cube) # 链接到 `pixels` collection 下

遍历图像像素构建各个立方体

为图像中的每个像素调用之前定义的 make_cube() 函数。

图像必须已经存在 image_name 所指定的(字符串)名字 的数据块中。

def cubify(image_name):

    myImage = bpy.data.images[image_name]
    color_chans = myImage.channels
    width, height = myImage.size
    pixels = myImage.pixels
    
    for y in range(0, height):
        for x in range(0, width):
            block_number = (y * width) + x # 像素的位置
            color = pixels[block_number*color_chans : block_number*color_chans+color_chans] # 取出对应通道位置的像素
            if len(color) < color_chans: # 如果颜色无法满足一个通道的要求
                break
            if len(pixels) < block_number: # 如果越界
                break
            # 调用我们之前定义好的函数,一个颜色构造一个立方体
            make_cube([x * 2, y * 2, 0], color)

体素化一副 Logo 图像

如下直接调用我们之前定义好的 cubify 即可

# 立方体像素画一个 Logo 图
cubify('ShaderJoy_50x50')

(完)