计算机图形学流体模拟 blender 渲染脚本

发布时间:2024年01月09日

做流体模拟的时候,想要复现别人的成果,但是别人的代码都是每帧输出 ply 格式的文件,渲染部分需要自己完成

看了一下,似乎用 blender 是最简单的,于是记录一下过程中用到的代码

Blender 版本 4.0

批量导入 ply

假设所有 ply 文件都和 blend 文件位于同一目录

希望导入所有 ply 文件,都放在一个 collection 里面,并且只连接到这个 collection

import bpy 
import os

in_dir = bpy.path.abspath("//")
filters = []  # files to ignore
files_number = 0

def only_link_to_one_collection(obj, collection):
    for other_col in obj.users_collection:
        other_col.objects.unlink(obj)
    if obj.name not in collection.objects:
        collection.objects.link(obj)
        
def import_ply(path, filters):
    need_file_items = []
    need_file_names = []

    filterDict = {}
    for item in filters:
        filterDict[item] = True;

    file_lst = os.listdir(path)
    
    for item in file_lst:
        fileName, fileExtension = os.path.splitext(item)
        if fileExtension == ".ply" and (not item in filterDict):
            need_file_items.append(item)
            need_file_names.append(fileName)
    
    fluid_mesh_collection = bpy.data.collections.new(name='FluidMesh')
    bpy.context.scene.collection.children.link(fluid_mesh_collection)
    
    files_number = len(need_file_items)
    for i in range(files_number):
        item = need_file_items[i]
        itemName = need_file_names[i]
        ufilename = path + "\\" + item
        bpy.ops.wm.ply_import(filepath=ufilename)
        cur_obj = bpy.data.objects[itemName]
        if (cur_obj):
            only_link_to_one_collection(cur_obj, fluid_mesh_collection)
            cur_obj.hide_set(False)
            cur_obj.hide_render = True

import_ply(in_dir, filters)

Mesh 预处理

删除没有使用到的材质

import bpy

toRemove = [block for block in bpy.data.materials if block.users == 0]
for block in toRemove:
    bpy.data.materials.remove(block)

添加 Glass BSDF 材质

import bpy

fluid_mat = bpy.data.materials.new("FluidMat")
fluid_mat.use_nodes = True

principled_node = fluid_mat.node_tree.nodes.get("Principled BSDF")
fluid_mat.node_tree.nodes.remove(principled_node)

glass_node = fluid_mat.node_tree.nodes.new("ShaderNodeBsdfGlass")
glass_node.location = (0, 0)

glass_node.inputs[0].default_value = (0.730, 0.927, 1.0, 1.0)
glass_node.inputs[1].default_value = 0.0
glass_node.inputs[2].default_value = 1.333

output_node = fluid_mat.node_tree.nodes.get("Material Output")
output_node.location = (200, 0)

fluid_mat.node_tree.links.new(glass_node.outputs[0], output_node.inputs[0])

for obj in bpy.data.collections['FluidMesh'].all_objects:
    obj.active_material = fluid_mat

重定位 Mesh

import bpy

for obj in bpy.data.collections['FluidMesh'].all_objects:
    obj.rotation_euler[0] = 1.5708  # 90d
    obj.location = (-4, 4, 0)

清理旧的动画

import bpy

for obj in bpy.data.collections['FluidMesh'].all_objects:
    obj.animation_data_clear()

制作动画帧

Hide_Render 动画

import bpy

for obj in bpy.data.collections['FluidMesh'].all_objects:
    mesh_name = obj.name
    i = int(mesh_name)
    
    obj.hide_viewport = True
    obj.hide_render = True
    obj.keyframe_insert("hide_viewport", frame=0)
    obj.keyframe_insert("hide_render", frame=0)
    
    obj.hide_viewport = False
    obj.hide_render = False
    obj.keyframe_insert("hide_viewport", frame=i+1)
    obj.keyframe_insert("hide_render", frame=i+1)
    
    obj.hide_viewport = True
    obj.hide_render = True
    obj.keyframe_insert("hide_viewport", frame=i+2)
    obj.keyframe_insert("hide_render", frame=i+2)

输出渲染动画

地面、天光等创建暂时不写脚本里

import bpy
import math

camera = bpy.data.objects['Camera']
camera.location = (20, -20, 20)
camera.rotation_euler = (math.radians(60), 0, math.radians(45))

bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.device = 'GPU'
bpy.context.scene.cycles.samples = 256

bpy.context.scene.render.resolution_x = 1080
bpy.context.scene.render.resolution_y = 720
bpy.context.scene.render.fps = 30

bpy.context.scene.render.filepath = bpy.path.abspath("//fluid_anim.mkv")
bpy.context.scene.render.image_settings.file_format = 'FFMPEG'

bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = len(bpy.data.collections['FluidMesh'].all_objects)+1

bpy.ops.render.render(animation=True)

效果

请添加图片描述

文章来源:https://blog.csdn.net/hijackedbycsdn/article/details/135472267
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。