Blender批量创建3D NFT
我想为大约 1000 多个 NFT 收藏品创建 3D 角色,但不知道该怎么做。手动一个一个地创建所有模型是愚蠢的。
实际上,我喜欢使用 Blender 来创建 3D 模型,所以也想使用它。
当我在互联网上搜索时,我发现Blender Scripting(Python)可以用于随机组合各种特征以编程方式创建3D模型的解决方案。它使用Python语言。
1、NFT藏品目录结构
目录树如下:
- parts ——其中包含的每个 3D 零件。
- body ——身体。
- head ——头。
- misc — 其他文件(背景、灯光、相机等)。
- outputs——由 Blender 脚本生成的图像和元数据。
- script - Python脚本文件。
2、创建3D部件
这一次,创建 2 种类型的零件,包括头部,身体。和misc(包括背景图像、相机、灯光的文件)。
步骤如下:
- 打开 Blender 并创建一个新文件并删除所有默认对象,并将其保存在body或head文件夹中。(例如nft-collectibles/parts/head/head_rabbit.blend)
- 在 Blender 中,创建一个与文件名相同的新集合。(例如,如果文件名为head_rabbit.blend,则集合名称为head_rabbit)
- 在刚刚创建的集合中创建一个零件模型。
- 调整大小和位置,使角色看起来自然。
- 最后保存。
2.1 3D NFT 头部件示例
文件名:nft-collectibles/parts/head/head_rabbit.blend
收藏名:head_rabbit
文件名:nft-collectibles/parts/head/head_frog.blend
收藏名:head_frog
2.2 3D NFT身体部件示例
文件名:nft-collectibles/parts/body/body_shirt.blend
收藏名:body_shirt
文件名:nft-collectibles/parts/head/body_zombie.blend
收藏名:body_zombie
2.3 3D NFT 辅助部件示例
文件名:nft-collectibles/parts/misc/misc.blend
收藏名:misc
3、创建Blender Python脚本文件
要创建脚本文件,请在 Blender的脚本工作区中打开你喜欢的代码/文本编辑器或文本编辑器。
3.1 gen_metadata.py
这是为了为 NFT 生成随机元数据:
import bpy # The module for Blender Python
import json
import random
# This time, 100 characters will be generated.
TOTAL_CHARACTERS = 100
# Specify the directory in which generate images finally.
OUTPUTS_DIR = "c:/nft-collectibles/outputs/"
# List of parts (the file name (collection name) of each created part is included in this.)
list_body = [
"hoodie",
"overall",
"pants",
"shirt",
"tanktop",
"t_shirt",
"zombie"
]
list_head = [
"devil",
"dragon",
"frog",
"king",
"pirate",
"rabbit",
"robot",
"skull",
"warrior"
]
def random_attributes():
# Select parts randomly from lists
random_head = random.choice(list_head)
random_body = random.choice(list_body)
# Format each name for the value of attributes in metadata (e.g. "head_rabbit" -> "Head Rabbit")
random_head = random_head.replace("_", " ").title()
random_body = random_body.replace("_", " ").title()
attributes = [
{
"trait_type": "Body",
"value": random_body
},
{
"trait_type": "Head",
"value": random_head
}
]
return attributes
def main():
print("Start generating metadata...")
# Create a tempolary dict
dict_list = []
for i in range(TOTAL_CHARACTERS):
attributes = random_attributes(i)
d = { "attributes": attributes }
dict_list.append(d)
# Create a list of unique data removed duplicates
unique_list = list(map(json.loads, set(map(json.dumps, dict_list))))
# If the duplicated found, cancel scripting and try again
if len(unique_list) < TOTAL_CHARACTERS:
print("ERROR: Properties duplicate")
return
# Save metadata files (.json) to outputs folder
for i, attr_dict in enumerate(unique_list):
# Create a metadata object
obj = {
"name": "Character #" + str(i),
"description": "A collection of 3D character",
"image": "https://example.com/"+ str(i) + ".png",
"external_url": "https://example.com/",
"attributes": attr_dict["attributes"]
}
with open(OUTPUTS_DIR + str(i) + ".json", 'w') as outjson:
json.dump(obj, outjson, indent=4)
print("Generated metadata id: {}\n".format(i))
main()
3.2 gen_model.py
这是为了从元数据生成模型。
import bpy
import json
import random
import shutil
# This time, 100 characters will be generated.
TOTAL_CHARACTERS = 100
# Path
PARTS_DIR = "c:/nft-collectibles/parts/"
OUTPUTS_DIR = "c:/nft-collectibles/outputs/"
# Initialize the scene (deleting the all default objects)
def init():
for obj in bpy.data.objects:
bpy.data.objects.remove(obj)
for col in bpy.data.collections:
bpy.data.collections.remove(col)
# Set configurations for rendering
def set_render_config():
# For example, set the rendering engine "EEVEE" (but Blender may be configured EEVEE default. if so, you don't need to do that)
r = bpy.context.scene.render
r.engine = "BLENDER_EEVEE"
r.resolution_x = 1024
r.resolution_y = 1024
# Set the output file format
r.image_settings.file_format = 'PNG'
def append_misc():
path = PARTS_DIR + "misc/" + "misc.blend/Collection/"
collection_name = "misc"
bpy.ops.wm.append(filename=collection_name, directory=path)
# Link camera to scene
cam = bpy.data.objects["camera"]
scene = bpy.context.scene
scene.camera = cam
def append_body(trait_value):
body_name = "body_" + trait_value
path = PARTS_DIR + "body/" + body_name + ".blend/Collection/"
bpy.ops.wm.append(filename=body_name, directory=path)
def append_head(trait_value):
head_name = "head_" + trait_value
path = PARTS_DIR + "head/" + head_name + ".blend/Collection/"
bpy.ops.wm.append(filename=head_name, directory=path)
def render(id):
# Render
bpy.ops.render.render(write_still=1)
# Save
bpy.data.images['Render Result'].save_render(filepath=OUTPUTS_DIR + id + ".png")
def remove_parts():
# Remove all parts except "misc"
for col in bpy.data.collections:
if col.name != "misc":
for obj in col.objects:
bpy.data.objects.remove(obj)
bpy.data.collections.remove(col)
continue
def generate(id, metadata):
for attr in metadata["attributes"]:
# Body
if attr["trait_type"] == "Body" and attr["value"] != "":
append_body(attr["value"])
# Head
if attr["trait_type"] == "Head" and attr["value"] != "":
append_head(attr["value"])
render(str(id))
# After rendered, remove all parts
remove_parts()
def main():
print("Start generating models...")
init()
set_render_config()
append_misc() # Regarding "misc", add it to the scene in advance because it is common to all characters.
# Generate character images
for i in TOTAL_CHARACTERS:
with open(OUTPUTS_DIR + str(i) + ".json", 'r') as metaJson:
data = json.load(metaJson)
generate(i, data)
print("Generated model id: {}\n".format(id))
main()
4、 运行脚本
创建脚本文件后,你可以运行它们。
打开 Blender 并单击编辑器顶部 几何节点旁边的脚本工作区。
要检查处理过程中的状态,可以通过单击顶部菜单中的“窗口”->“切换系统控制台”来打开控制台。
4.1、生成元数据
单击Open -> 选择gen_metadata.py -> 单击Run Script。
如上源代码所示(gen_metadata.py,第68-73行),如果数据组合重复,该过程将被取消。在这种情况下,你需要再次单击运行脚本。
之后,可以看到在output文件夹中生成了0.json、1.json等元数据文件。
4.2 生成3D NFT角色
点击Open -> 选择一个gen_model.py -> 点击Run Script。
之后,可以看到在output文件夹中生成了0.png、1.png等渲染图像文件。
原文链接:Create NFT 3D Collectibles Using Blender Scripting
BimAnt翻译整理,转载请标明出处