持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 4 天,点击查看活动详情
效果图
进一步的修改可以得到如下效果
具体步骤
准备好材质
首先,我们使用名为 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)
创建原型立方体作为网格数据来源
创建为 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')
(完)