render iteration

This commit is contained in:
Jonas H
2026-02-08 14:06:35 +01:00
parent 2422106725
commit 82c3e1e3b0
67 changed files with 6381 additions and 1564 deletions

View File

@@ -0,0 +1,135 @@
import bpy
from pathlib import Path
def bake_heightmap(terrain_obj, resolution=1024, output_path=None):
"""
Bake terrain heightmap using Blender's render/bake system.
Args:
terrain_obj: Terrain mesh object
resolution: Texture resolution (square)
output_path: Path to save EXR file
"""
print(f"Baking heightmap for: {terrain_obj.name}")
print(f"Resolution: {resolution}×{resolution}")
# Ensure object has UV map
if not terrain_obj.data.uv_layers:
print("Adding UV map...")
terrain_obj.data.uv_layers.new(name="UVMap")
# Create new image for baking
bake_image = bpy.data.images.new(
name="Heightmap_Bake",
width=resolution,
height=resolution,
alpha=False,
float_buffer=True,
is_data=True
)
# Setup material for baking
if not terrain_obj.data.materials:
mat = bpy.data.materials.new(name="Heightmap_Material")
terrain_obj.data.materials.append(mat)
else:
mat = terrain_obj.data.materials[0]
mat.use_nodes = True
nodes = mat.node_tree.nodes
nodes.clear()
# Create nodes for height baking
# Geometry node to get position
geo_node = nodes.new(type='ShaderNodeNewGeometry')
# Separate XYZ to get Z (height)
separate_node = nodes.new(type='ShaderNodeSeparateXYZ')
mat.node_tree.links.new(geo_node.outputs['Position'], separate_node.inputs['Vector'])
# Emission shader to output height value
emission_node = nodes.new(type='ShaderNodeEmission')
mat.node_tree.links.new(separate_node.outputs['Z'], emission_node.inputs['Color'])
# Material output
output_node = nodes.new(type='ShaderNodeOutputMaterial')
mat.node_tree.links.new(emission_node.outputs['Emission'], output_node.inputs['Surface'])
# Add image texture node (required for baking target)
image_node = nodes.new(type='ShaderNodeTexImage')
image_node.image = bake_image
image_node.select = True
nodes.active = image_node
# Select object and set mode
bpy.context.view_layer.objects.active = terrain_obj
terrain_obj.select_set(True)
# Setup render settings for baking
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.samples = 1
bpy.context.scene.cycles.bake_type = 'EMIT'
print("Baking...")
bpy.ops.object.bake(type='EMIT', use_clear=True)
print("Bake complete!")
# Save as EXR
if output_path:
bake_image.filepath_raw = str(output_path)
bake_image.file_format = 'OPEN_EXR'
bake_image.use_half_precision = False
scene = bpy.context.scene
original_color_mode = scene.render.image_settings.color_mode
original_color_depth = scene.render.image_settings.color_depth
scene.render.image_settings.color_mode = 'BW'
scene.render.image_settings.color_depth = '32'
bake_image.save_render(str(output_path), scene=scene)
scene.render.image_settings.color_mode = original_color_mode
scene.render.image_settings.color_depth = original_color_depth
print(f"Saved to: {output_path}")
# Cleanup
bpy.data.images.remove(bake_image)
return True
if __name__ == "__main__":
project_root = Path(bpy.data.filepath).parent.parent
output_path = project_root / "textures" / "terrain_heightmap.exr"
output_path.parent.mkdir(parents=True, exist_ok=True)
# Find terrain object
terrain_obj = bpy.data.objects.get("TerrainPlane")
if not terrain_obj:
print("'TerrainPlane' not found. Searching for terrain mesh...")
for obj in bpy.data.objects:
if obj.type == 'MESH' and ('terrain' in obj.name.lower() or 'plane' in obj.name.lower()):
terrain_obj = obj
print(f"Using: {obj.name}")
break
if not terrain_obj:
raise ValueError("No terrain object found!")
bake_heightmap(
terrain_obj=terrain_obj,
resolution=1000,
output_path=output_path
)
print("\n" + "="*60)
print("Heightmap baking complete!")
print(f"Output: {output_path}")
print("="*60)