render normal
This commit is contained in:
parent
e4896b7277
commit
d9f8ac1268
@ -13,7 +13,6 @@ class BlenderUtils:
|
|||||||
CAMERA_NAME: str = "Camera"
|
CAMERA_NAME: str = "Camera"
|
||||||
CAMERA_RIGHT_NAME: str = "CameraRight"
|
CAMERA_RIGHT_NAME: str = "CameraRight"
|
||||||
CAMERA_OBJECT_NAME: str = "CameraObject"
|
CAMERA_OBJECT_NAME: str = "CameraObject"
|
||||||
LIGHT_NAME: str = "Light"
|
|
||||||
DISPLAY_TABLE_NAME: str = "display_table"
|
DISPLAY_TABLE_NAME: str = "display_table"
|
||||||
MESH_FILE_NAME: str = "mesh.obj"
|
MESH_FILE_NAME: str = "mesh.obj"
|
||||||
|
|
||||||
@ -68,11 +67,25 @@ class BlenderUtils:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setup_scene(init_light_and_camera_config, table_model_path, binocular_vision):
|
def setup_scene(init_light_and_camera_config, table_model_path, binocular_vision):
|
||||||
bpy.context.scene.render.engine = 'BLENDER_WORKBENCH'
|
bpy.context.scene.render.engine = 'BLENDER_EEVEE_NEXT'
|
||||||
bpy.context.scene.display.shading.show_xray = False
|
bpy.context.scene.display.shading.show_xray = False
|
||||||
bpy.context.scene.display.shading.use_dof = False
|
bpy.context.scene.display.shading.use_dof = False
|
||||||
bpy.context.scene.display.render_aa = 'OFF'
|
bpy.context.scene.display.render_aa = 'OFF'
|
||||||
bpy.context.scene.view_settings.view_transform = 'Standard'
|
bpy.context.scene.view_settings.view_transform = 'Standard'
|
||||||
|
|
||||||
|
bpy.context.scene.eevee.use_ssr = False # 关闭屏幕空间反射
|
||||||
|
bpy.context.scene.eevee.use_bloom = False # 关闭辉光
|
||||||
|
bpy.context.scene.eevee.use_gtao = False # 关闭环境光遮蔽
|
||||||
|
bpy.context.scene.eevee.use_soft_shadows = False # 关闭软阴影
|
||||||
|
bpy.context.scene.eevee.use_shadows = False # 关闭所有阴影
|
||||||
|
bpy.context.scene.world.use_nodes = False # 如果你不需要环境光,关闭环境节点
|
||||||
|
|
||||||
|
|
||||||
|
#bpy.context.scene.eevee.use_sss = False # 关闭次表面散射
|
||||||
|
|
||||||
|
# 2. 设置最低的采样数
|
||||||
|
bpy.context.scene.eevee.taa_render_samples = 1
|
||||||
|
bpy.context.scene.eevee.taa_samples = 1
|
||||||
BlenderUtils.init_light_and_camera(init_light_and_camera_config, binocular_vision)
|
BlenderUtils.init_light_and_camera(init_light_and_camera_config, binocular_vision)
|
||||||
|
|
||||||
BlenderUtils.add_plane("plane_floor", location=(0,0,0), orientation=(0,0,0))
|
BlenderUtils.add_plane("plane_floor", location=(0,0,0), orientation=(0,0,0))
|
||||||
@ -135,9 +148,7 @@ class BlenderUtils:
|
|||||||
def init_light_and_camera(init_light_and_camera_config, binocular_vision):
|
def init_light_and_camera(init_light_and_camera_config, binocular_vision):
|
||||||
|
|
||||||
camera = BlenderUtils.get_obj(BlenderUtils.CAMERA_NAME)
|
camera = BlenderUtils.get_obj(BlenderUtils.CAMERA_NAME)
|
||||||
light = BlenderUtils.get_obj(BlenderUtils.LIGHT_NAME)
|
|
||||||
BlenderUtils.set_camera_params(camera, init_light_and_camera_config[BlenderUtils.CAMERA_NAME], binocular_vision)
|
BlenderUtils.set_camera_params(camera, init_light_and_camera_config[BlenderUtils.CAMERA_NAME], binocular_vision)
|
||||||
BlenderUtils.set_light_params(light, init_light_and_camera_config[BlenderUtils.LIGHT_NAME])
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_obj_diag(name):
|
def get_obj_diag(name):
|
||||||
@ -167,51 +178,15 @@ class BlenderUtils:
|
|||||||
min_z = min([v.z for v in vertices_world])
|
min_z = min([v.z for v in vertices_world])
|
||||||
return min_z
|
return min_z
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def setup_render_mask():
|
|
||||||
bpy.context.scene.display.shading.light = 'FLAT'
|
|
||||||
bpy.context.scene.display.shading.color_type = 'MATERIAL'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def setup_render_normal():
|
|
||||||
bpy.context.scene.display.shading.light = 'MATCAP'
|
|
||||||
bpy.context.scene.display.shading.color_type = 'OBJECT'
|
|
||||||
bpy.context.scene.display.shading.studio_light = 'check_normal+y.exr'
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def render_and_save(output_dir, file_name, binocular_vision=False, target_object=None):
|
def render_and_save(output_dir, file_name, binocular_vision=False, target_object=None):
|
||||||
target_cameras = [BlenderUtils.CAMERA_NAME]
|
target_cameras = [BlenderUtils.CAMERA_NAME]
|
||||||
if binocular_vision:
|
if binocular_vision:
|
||||||
target_cameras.append(BlenderUtils.CAMERA_RIGHT_NAME)
|
target_cameras.append(BlenderUtils.CAMERA_RIGHT_NAME)
|
||||||
|
|
||||||
# BlenderUtils.setup_render_normal()
|
|
||||||
|
|
||||||
# for cam_name in target_cameras:
|
|
||||||
# bpy.context.scene.camera = BlenderUtils.get_obj(cam_name)
|
|
||||||
# cam_suffix = "L" if cam_name == BlenderUtils.CAMERA_NAME else "R"
|
|
||||||
# scene = bpy.context.scene
|
|
||||||
# scene.use_nodes = False
|
|
||||||
# scene.render.filepath = ""
|
|
||||||
|
|
||||||
# normal_dir = os.path.join(output_dir, "normal")
|
|
||||||
# if not os.path.exists(normal_dir):
|
|
||||||
# os.makedirs(normal_dir)
|
|
||||||
|
|
||||||
|
|
||||||
# scene.render.filepath = os.path.join(output_dir, normal_dir, f"{file_name}_{cam_suffix}.png")
|
|
||||||
# scene.render.image_settings.color_depth = '8'
|
|
||||||
# scene.render.resolution_percentage = 100
|
|
||||||
# scene.render.use_overwrite = False
|
|
||||||
# scene.render.use_file_extension = False
|
|
||||||
# scene.render.use_placeholder = False
|
|
||||||
|
|
||||||
# bpy.ops.render.render(write_still=True)
|
|
||||||
|
|
||||||
|
|
||||||
BlenderUtils.setup_render_mask()
|
|
||||||
for cam_name in target_cameras:
|
for cam_name in target_cameras:
|
||||||
bpy.context.scene.camera = BlenderUtils.get_obj(cam_name)
|
bpy.context.scene.camera = BlenderUtils.get_obj(cam_name)
|
||||||
bpy.context.scene.view_layers["ViewLayer"].use_pass_z = True
|
bpy.context.scene.view_layers["ViewLayer"].use_pass_z = True
|
||||||
|
bpy.context.scene.view_layers["ViewLayer"].use_pass_normal = True
|
||||||
cam_suffix = "L" if cam_name == BlenderUtils.CAMERA_NAME else "R"
|
cam_suffix = "L" if cam_name == BlenderUtils.CAMERA_NAME else "R"
|
||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
scene.render.filepath = ""
|
scene.render.filepath = ""
|
||||||
@ -255,6 +230,17 @@ class BlenderUtils:
|
|||||||
output_depth.format.color_depth = '16'
|
output_depth.format.color_depth = '16'
|
||||||
|
|
||||||
tree.links.new(map_range.outputs[0], output_depth.inputs[0])
|
tree.links.new(map_range.outputs[0], output_depth.inputs[0])
|
||||||
|
|
||||||
|
output_normal = tree.nodes.new('CompositorNodeOutputFile')
|
||||||
|
normal_dir = os.path.join(output_dir, "normal")
|
||||||
|
if not os.path.exists(normal_dir):
|
||||||
|
os.makedirs(normal_dir)
|
||||||
|
output_normal.base_path = normal_dir
|
||||||
|
output_normal.file_slots[0].path = f"{file_name}_{cam_suffix}.####"
|
||||||
|
output_normal.format.file_format = 'PNG'
|
||||||
|
output_normal.format.color_mode = 'RGB'
|
||||||
|
output_normal.format.color_depth = '8'
|
||||||
|
tree.links.new(rl.outputs['Normal'], output_normal.inputs[0])
|
||||||
|
|
||||||
bpy.ops.render.render(write_still=True)
|
bpy.ops.render.render(write_still=True)
|
||||||
|
|
||||||
@ -309,7 +295,6 @@ class BlenderUtils:
|
|||||||
keep_objects.add(BlenderUtils.CAMERA_OBJECT_NAME)
|
keep_objects.add(BlenderUtils.CAMERA_OBJECT_NAME)
|
||||||
keep_objects.add(BlenderUtils.CAMERA_NAME)
|
keep_objects.add(BlenderUtils.CAMERA_NAME)
|
||||||
keep_objects.add(BlenderUtils.CAMERA_RIGHT_NAME)
|
keep_objects.add(BlenderUtils.CAMERA_RIGHT_NAME)
|
||||||
keep_objects.add(BlenderUtils.LIGHT_NAME)
|
|
||||||
keep_objects.add(BlenderUtils.TABLE_NAME)
|
keep_objects.add(BlenderUtils.TABLE_NAME)
|
||||||
|
|
||||||
for obj in all_objects:
|
for obj in all_objects:
|
||||||
@ -336,7 +321,6 @@ class BlenderUtils:
|
|||||||
no_save_objects.add(BlenderUtils.CAMERA_OBJECT_NAME)
|
no_save_objects.add(BlenderUtils.CAMERA_OBJECT_NAME)
|
||||||
no_save_objects.add(BlenderUtils.CAMERA_NAME)
|
no_save_objects.add(BlenderUtils.CAMERA_NAME)
|
||||||
no_save_objects.add(BlenderUtils.CAMERA_RIGHT_NAME)
|
no_save_objects.add(BlenderUtils.CAMERA_RIGHT_NAME)
|
||||||
no_save_objects.add(BlenderUtils.LIGHT_NAME)
|
|
||||||
no_save_objects.add(BlenderUtils.TABLE_NAME)
|
no_save_objects.add(BlenderUtils.TABLE_NAME)
|
||||||
scene_info = {}
|
scene_info = {}
|
||||||
for obj in all_objects:
|
for obj in all_objects:
|
||||||
|
@ -83,7 +83,7 @@ class DataGenerator:
|
|||||||
|
|
||||||
def generate_display_platform(self):
|
def generate_display_platform(self):
|
||||||
config = self.random_config[BlenderUtils.DISPLAY_TABLE_NAME]
|
config = self.random_config[BlenderUtils.DISPLAY_TABLE_NAME]
|
||||||
|
|
||||||
height = random.uniform(config["min_height"], config["max_height"])
|
height = random.uniform(config["min_height"], config["max_height"])
|
||||||
radius = random.uniform(config["min_radius"], config["max_radius"])
|
radius = random.uniform(config["min_radius"], config["max_radius"])
|
||||||
while height > 0.5 * radius:
|
while height > 0.5 * radius:
|
||||||
@ -103,12 +103,29 @@ class DataGenerator:
|
|||||||
bpy.context.object.rigid_body.type = 'PASSIVE'
|
bpy.context.object.rigid_body.type = 'PASSIVE'
|
||||||
bpy.ops.object.shade_auto_smooth()
|
bpy.ops.object.shade_auto_smooth()
|
||||||
|
|
||||||
|
# 创建不受光照影响的材质
|
||||||
mat = bpy.data.materials.new(name="RedMaterial")
|
mat = bpy.data.materials.new(name="RedMaterial")
|
||||||
mat.diffuse_color = (1.0, 0.0, 0.0, 1.0) # Red with full alpha (1.0)
|
mat.use_nodes = True
|
||||||
if len(platform.data.materials) > 0:
|
|
||||||
platform.data.materials[0] = mat
|
# 清除默认节点
|
||||||
else:
|
nodes = mat.node_tree.nodes
|
||||||
platform.data.materials.append(mat)
|
for node in nodes:
|
||||||
|
nodes.remove(node)
|
||||||
|
|
||||||
|
# 添加 Emission 节点
|
||||||
|
emission_node = nodes.new(type='ShaderNodeEmission')
|
||||||
|
emission_node.inputs['Color'].default_value = (1.0, 0.0, 0.0, 1.0) # 红色
|
||||||
|
|
||||||
|
# 添加 Material Output 节点
|
||||||
|
output_node = nodes.new(type='ShaderNodeOutputMaterial')
|
||||||
|
|
||||||
|
# 连接节点
|
||||||
|
links = mat.node_tree.links
|
||||||
|
links.new(emission_node.outputs['Emission'], output_node.inputs['Surface'])
|
||||||
|
|
||||||
|
# 将材质赋给对象
|
||||||
|
platform.data.materials.clear()
|
||||||
|
platform.data.materials.append(mat)
|
||||||
|
|
||||||
self.display_table_config = {
|
self.display_table_config = {
|
||||||
"height": height,
|
"height": height,
|
||||||
@ -126,19 +143,19 @@ class DataGenerator:
|
|||||||
|
|
||||||
if random.random() <= config["random_rotation_ratio"]:
|
if random.random() <= config["random_rotation_ratio"]:
|
||||||
rotation = (
|
rotation = (
|
||||||
random.uniform(0, 2*np.pi),
|
random.uniform(0, 2 * np.pi),
|
||||||
random.uniform(0, 2*np.pi),
|
random.uniform(0, 2 * np.pi),
|
||||||
random.uniform(0, 2*np.pi)
|
random.uniform(0, 2 * np.pi)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rotation = (0, 0, 0)
|
rotation = (0, 0, 0)
|
||||||
z=0.05
|
z = 0.05
|
||||||
|
|
||||||
platform_bbox = self.platform.bound_box
|
platform_bbox = self.platform.bound_box
|
||||||
platform_bbox_world = [self.platform.matrix_world @ mathutils.Vector(corner) for corner in platform_bbox]
|
platform_bbox_world = [self.platform.matrix_world @ mathutils.Vector(corner) for corner in platform_bbox]
|
||||||
platform_top_z = max([v.z for v in platform_bbox_world])
|
platform_top_z = max([v.z for v in platform_bbox_world])
|
||||||
|
|
||||||
obj_mesh_path = BlenderUtils.get_obj_path(self.obj_dir,name)
|
obj_mesh_path = BlenderUtils.get_obj_path(self.obj_dir, name)
|
||||||
obj = BlenderUtils.load_obj(name, obj_mesh_path)
|
obj = BlenderUtils.load_obj(name, obj_mesh_path)
|
||||||
|
|
||||||
obj_bottom_z = BlenderUtils.get_object_bottom_z(obj)
|
obj_bottom_z = BlenderUtils.get_object_bottom_z(obj)
|
||||||
@ -149,12 +166,31 @@ class DataGenerator:
|
|||||||
|
|
||||||
bpy.ops.rigidbody.object_add()
|
bpy.ops.rigidbody.object_add()
|
||||||
bpy.context.object.rigid_body.type = 'ACTIVE'
|
bpy.context.object.rigid_body.type = 'ACTIVE'
|
||||||
|
|
||||||
|
# 创建不受光照影响的材质
|
||||||
mat = bpy.data.materials.new(name="GreenMaterial")
|
mat = bpy.data.materials.new(name="GreenMaterial")
|
||||||
mat.diffuse_color = (0.0, 1.0, 0.0, 1.0) # Green with full alpha (1.0)
|
mat.use_nodes = True
|
||||||
if len(obj.data.materials) > 0:
|
|
||||||
obj.data.materials[0] = mat
|
# 清除默认节点
|
||||||
else:
|
nodes = mat.node_tree.nodes
|
||||||
obj.data.materials.append(mat)
|
for node in nodes:
|
||||||
|
nodes.remove(node)
|
||||||
|
|
||||||
|
# 添加 Emission 节点
|
||||||
|
emission_node = nodes.new(type='ShaderNodeEmission')
|
||||||
|
emission_node.inputs['Color'].default_value = (0.0, 1.0, 0.0, 1.0) # 绿色
|
||||||
|
|
||||||
|
# 添加 Material Output 节点
|
||||||
|
output_node = nodes.new(type='ShaderNodeOutputMaterial')
|
||||||
|
|
||||||
|
# 连接节点
|
||||||
|
links = mat.node_tree.links
|
||||||
|
links.new(emission_node.outputs['Emission'], output_node.inputs['Surface'])
|
||||||
|
|
||||||
|
# 将材质赋给对象
|
||||||
|
obj.data.materials.clear()
|
||||||
|
obj.data.materials.append(mat)
|
||||||
|
|
||||||
self.target_obj = obj
|
self.target_obj = obj
|
||||||
|
|
||||||
|
|
||||||
@ -219,6 +255,13 @@ class DataGenerator:
|
|||||||
file_path = os.path.join(depth_dir, depth_file)
|
file_path = os.path.join(depth_dir, depth_file)
|
||||||
new_file_path = os.path.join(depth_dir, f"{name}.png")
|
new_file_path = os.path.join(depth_dir, f"{name}.png")
|
||||||
os.rename(file_path,new_file_path)
|
os.rename(file_path,new_file_path)
|
||||||
|
normal_dir = os.path.join(scene_dir, "normal")
|
||||||
|
for normal_file in os.listdir(normal_dir):
|
||||||
|
if not normal_file.endswith(".png"):
|
||||||
|
name, _ = os.path.splitext(normal_file)
|
||||||
|
file_path = os.path.join(normal_dir, normal_file)
|
||||||
|
new_file_path = os.path.join(normal_dir, f"{name}.png")
|
||||||
|
os.rename(file_path,new_file_path)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def simulate_scene(self, frame_limit=120, depth = 0, diag = 0):
|
def simulate_scene(self, frame_limit=120, depth = 0, diag = 0):
|
||||||
@ -274,6 +317,7 @@ class DataGenerator:
|
|||||||
count_success = 0
|
count_success = 0
|
||||||
self.set_progress("generate scene", 0, total)
|
self.set_progress("generate scene", 0, total)
|
||||||
result = "retry"
|
result = "retry"
|
||||||
|
print(f"Generating scene for {total} objects")
|
||||||
for target_obj_name in self.obj_name_list:
|
for target_obj_name in self.obj_name_list:
|
||||||
self.add_log(f"Generating scene for object <{target_obj_name}>", "info")
|
self.add_log(f"Generating scene for object <{target_obj_name}>", "info")
|
||||||
scene_info_path = os.path.join(self.output_dir, target_obj_name, "scene_info.json")
|
scene_info_path = os.path.join(self.output_dir, target_obj_name, "scene_info.json")
|
||||||
|
@ -10,7 +10,8 @@ if __name__ == "__main__":
|
|||||||
config_path = sys.argv[sys.argv.index('--') + 1]
|
config_path = sys.argv[sys.argv.index('--') + 1]
|
||||||
with open(config_path, "r") as file:
|
with open(config_path, "r") as file:
|
||||||
config = yaml.safe_load(file)
|
config = yaml.safe_load(file)
|
||||||
|
print("init data generator")
|
||||||
dg = DataGenerator(config)
|
dg = DataGenerator(config)
|
||||||
|
print("generate all scene data")
|
||||||
dg.gen_all_scene_data()
|
dg.gen_all_scene_data()
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user