Skip to content

Commit

Permalink
Update README and main.py for HDRI support and options
Browse files Browse the repository at this point in the history
- Added support for HDRI backdrops in README and main.py.
- Updated command-line options for backdrop handling.
- Improved light intensity handling in the rendering process.
- Resolved paths for saved files to be absolute.
- Enhanced documentation for clarity on new features.
  • Loading branch information
Matthias Humt committed Dec 7, 2024
2 parents 86495d4 + 0324152 commit 9b7a0e1
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 38 deletions.
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ blenderproc pip install fire loguru

The first call of `blenderproc` will download [`Blender`](https://blender.org). If you already have a local
installation, you can use
`--custom-blender-path /path/to/blender` (this also needs to be used for all subsequent calls of `blenderproc`).
`--custom-blender-path path/to/blender` (this also needs to be used for all subsequent calls of `blenderproc`).

## Basic Usage
To render a mesh (or point cloud if the input is one), simply run:
```bash
blenderproc run main.py path/to/3d.obj
```

The following options can be added to:
* **save** the rendered image: `--save path/to/output.png`
* **export** the object: `--export path/to/output.obj` (use `.glb` for a web-friendly format)
Expand All @@ -31,10 +30,10 @@ The following options can be added to:
You can test you render settings using any of the `Blender` primitives (`monkey`, `cube`, `sphere`, `cone`,
`cylinder`, ...) as the first argument.

| Mesh | Point cloud | Depth |
|------------------------------------------|--------------------------|--------------------------------------------|
| ![mesh](examples/mesh.png) | ![pcd](examples/pcd.png) | ![mesh_depth](examples/depth.png) |
| `--obj_path suzanne` (or just `suzanne`) | `--pcd` | `--pcd 1024` `--point_size 0.01` `--depth` |
| Mesh | Point cloud | Depth |
|------------------------------------------|-------------------------------|--------------------------------------------|
| ![mesh](examples/mesh.png) | ![pcd](examples/pcd.png) | ![mesh_depth](examples/depth.png) |
| `--obj_path suzanne` (or just `suzanne`) | `--pcd` `--light very_bright` | `--pcd 1024` `--point_size 0.01` `--depth` |

## Basic Options

Expand All @@ -60,17 +59,18 @@ changed using the `--bg_color` option.
| Mesh | Point cloud | Background |
|----------------------------------|--------------------------------|--------------------------------------|
| ![mesh](examples/mesh_color.png) | ![pcd](examples/pcd_color.png) | ![mesh_depth](examples/bg_color.png) |
| `--color bright_blue` | `--pcd` `--color cool` | `--bg_color pale_turquoise` |
| `--color bright_blue` | `--pcd` `--color cool` | `--bg_color pale_turquoise` |

### Background

By default, the background is transparent. To change this, use the `--bg_color` option as shown above. Additionally,
`--notransparent` can be used to render the backdrop object.
`--notransparent` can be used to render the backdrop object. To use HDRI images as backdrops, use `--backdrop path/to/hdri`.
HDRIs can be obtained e.g. via `blenderproc download haven path/to/save/dir`.

| Backdrop | Colored backdrop |
|--------------------------------|---------------------------------------|
| ![mesh](examples/backdrop.png) | ![pcd](examples/backdrop_colored.png) |
| `--notransparent` | `--notransparent --bg_color pale_red` |
| Backdrop | Colored backdrop | HDRI backdrop |
|--------------------------------|---------------------------------------|--------------------------------------------------------------------|
| ![mesh](examples/backdrop.png) | ![pcd](examples/backdrop_colored.png) | ![mesh_depth](examples/hdri.png) |
| `--notransparent` | `--notransparent --bg_color pale_red` | `--notransparent --backdrop path/to/photo_studio_loft_hall_2k.hdr` |

## Light

Expand Down Expand Up @@ -123,7 +123,7 @@ To create an animation, use the `--animate` option. The `--frames` option can be

### Interactive 3D Visualization

To provide an interactive 3D visualization, use `--export /path/to/mesh.glb` to export the object as a `.glb` file and
To provide an interactive 3D visualization, use `--export path/to/mesh.glb` to export the object as a `.glb` file and
use
```html
<script
Expand All @@ -142,7 +142,7 @@ model-viewer {
</style>

<model-viewer
src="/path/to/mesh.glb"
src="path/to/mesh.glb"
camera-controls tone-mapping="neutral"
shadow-intensity="1"
auto-rotate>
Expand Down
Binary file modified examples/depth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/hdri.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified examples/mesh_depth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified examples/pcd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 39 additions & 24 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,10 @@ def run(obj_path: str | Tuple[str, str],
cam_offset: Tuple[float, float, float] = (0, 0, 0),
resolution: int | Tuple[int, int] = 512,
fstop: Optional[float] = None,
backdrop: bool = True,
backdrop: [bool | str] = True,
light: Optional[Light | str | float] = None,
bg_color: Optional[Tuple[float, float, float] | Color | str] = None,
bg_light: float = 0.15,
transparent: bool | float = True,
look: Optional[Look | str] = None,
exposure: float = 0,
Expand Down Expand Up @@ -162,6 +163,7 @@ def run(obj_path: str | Tuple[str, str],
backdrop: Whether to include a backdrop plane
light: Lighting intensity preset or custom value
bg_color: Background color in RGB format
bg_light: Background light intensity
transparent: Whether to render with transparency
look: Visual style preset to apply
exposure: Global exposure adjustment
Expand Down Expand Up @@ -231,7 +233,7 @@ def run(obj_path: str | Tuple[str, str],
point_shape=point_shape,
point_size=point_size,
bg_color=bg_color,
save=None if save is None else Path(save),
save=None if save is None else Path(save).resolve(),
show=show or not save)
if not obj:
return
Expand All @@ -248,11 +250,16 @@ def run(obj_path: str | Tuple[str, str],
gravity = False
offset = np.array([0, 0, -0.6])

light = light or Light.BRIGHT
logger.debug(f"Setting light intensity to {light}")
light = light if isinstance(light, float) else Light[light.upper()].value if isinstance(light, str) else light.value
if gravity or backdrop:
setup_backdrop(obj=obj,
shadow_strength=Strength.OFF if isinstance(shadow, bool) and not shadow else Strength.MEDIUM,
transparent=transparent,
color=None if transparent else bg_color,
hdri_path=Path(backdrop).resolve() if isinstance(backdrop, str) else None,
bg_light=bg_light * light,
gravity=gravity,
offset=offset)

Expand All @@ -261,25 +268,22 @@ def run(obj_path: str | Tuple[str, str],
logger.debug(f"Setting ambient occlusion strength to {ao}")
add_ambient_occlusion(strength=ao)

light = light or (Light.BRIGHT if (is_mesh or depth) else Light.VERY_BRIGHT)
logger.debug(f"Setting light intensity to {light}")
light = light if isinstance(light, float) else Light[light.upper()].value if isinstance(light, str) else light.value
shadow = Shadow(shadow) if shadow else (Shadow.MEDIUM if (is_mesh or depth) else Shadow.SOFT)
logger.debug(f"Setting shadow type to {shadow}")
make_lights(obj=obj,
shadow=shadow,
light_intensity=light)

if animate:
save = Path(animate.value).with_suffix('.gif') if not save else Path(save)
save = Path(animate.value).with_suffix('.gif') if not save else Path(save).resolve()
make_animation(obj=obj,
save=save,
animation=animate,
bg_color=bg_color,
debug=debug)
elif not debug:
render_color(bg_color=bg_color,
save=None if save is None else Path(save),
save=None if save is None else Path(save).resolve(),
show=show or not save)

if export:
Expand Down Expand Up @@ -708,10 +712,9 @@ def cmap(x, y, z):
colors.append(cmap(*value))
else:
cmap = plt.get_cmap(color)
distances = np.linalg.norm(values - np.array(camera_location), axis=1)
distances = (distances - distances.min()) / (distances.max() - distances.min())
for d in distances:
colors.append(cmap(d))
distances = normalize(np.linalg.norm(values - np.array(camera_location), axis=1))
for dist in distances:
colors.append(cmap(dist))

# TODO: Is this possible with BlenderProc, i.e. obj.new_attribute?
mesh = obj.get_mesh()
Expand Down Expand Up @@ -768,6 +771,8 @@ def setup_backdrop(obj: bproc.types.MeshObject,
shadow_strength: Strength | str = Strength.MEDIUM,
transparent: bool | float = True,
color: Optional[Tuple[float, float, float] | Color | str] = None,
hdri_path: Optional[Path] = None,
bg_light: float = 0.15,
gravity: bool = False,
offset: np.ndarray = np.array([0, 0, -0.05])):
"""Sets up a backdrop for the given object in the Blender scene.
Expand All @@ -777,13 +782,25 @@ def setup_backdrop(obj: bproc.types.MeshObject,
rigid body physics for the object and the backdrop and simulates the physics to fix their final poses.
Args:
obj: The BlenderProc mesh object for which the backdrop is being set up.
shadow_strength: The strength of the shadow to be applied to the backdrop.
transparent: Whether the backdrop should be transparent.
color: The color to apply to the backdrop.
gravity: Whether to enable gravity for the object and the backdrop.
offset: The offset to apply to the backdrop's position.
obj: The BlenderProc mesh object for which the backdrop is being set up
shadow_strength: The strength of the shadow to be applied to the backdrop
transparent: Whether the backdrop should be transparent
color: The color to apply to the backdrop
hdri_path: The path to an HDRI image to use as backdrop or to the HAVEN dataset
bg_light: The intensity of the background light
gravity: Whether to enable gravity for the object and the backdrop
offset: The offset to apply to the backdrop's position
"""
if hdri_path:
if (hdri_path / 'hdri').exists():
hdri_path = bproc.loader.get_random_world_background_hdr_img_path_from_haven(str(hdri_path))
logger.debug(f"Setting HDRI backdrop to {hdri_path.stem}")
bproc.world.set_world_background_hdr_img(str(hdri_path), strength=bg_light)
if gravity:
logger.warning("Gravity is not compatible with an HDRI backdrop.")
return
bproc.renderer.set_world_background([1, 1, 1], strength=bg_light)

with stdout_redirected():
plane = bproc.loader.load_obj('backdrop.ply')[0]
plane.clear_materials()
Expand Down Expand Up @@ -1120,14 +1137,12 @@ def make_lights(obj: bproc.types.MeshObject,
It sets the world background, positions the lights, and adjusts their properties based on the provided parameters.
Args:
obj: The BlenderProc mesh object for which the lighting is being set up.
shadow: The type of shadow to apply to the key light.
light_intensity: The intensity of the key light.
fill_light: Whether to add a fill light to the scene.
rim_light: Whether to add a rim light to the scene.
obj: The BlenderProc mesh object for which the lighting is being set up
shadow: The type of shadow to apply to the key light
light_intensity: The intensity of the key light
fill_light: Whether to add a fill light to the scene
rim_light: Whether to add a rim light to the scene
"""
bproc.renderer.set_world_background([1, 1, 1], strength=0.15 * light_intensity)

key_light = bproc.types.Light('AREA', name='key_light')
key_light.set_location([1, 0.5, 2])
key_light.set_rotation_mat(bproc.camera.rotation_from_forward_vec(obj.get_location() - key_light.get_location()))
Expand Down

0 comments on commit 9b7a0e1

Please sign in to comment.