Skip to content

Commit

Permalink
Merge pull request DLR-RM#371 from DLR-RM/iss_360_blender_3_and_cycles_X
Browse files Browse the repository at this point in the history
Blender 3 and Cycles x
  • Loading branch information
themasterlink authored Dec 14, 2021
2 parents 479c359 + 9f0b3db commit 740404a
Show file tree
Hide file tree
Showing 56 changed files with 98 additions and 192 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ blender
.vscode/
output/
debug/
resources/AMASS
resources/cctextures*
resources/scenenet/*zip
resources/scenenet/SceneNetData
Expand Down
12 changes: 6 additions & 6 deletions blenderproc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,16 @@ Config file:
"config": {
"global": {
"output_dir": "/tmp/",
"auto_tile_size": False
"max_bounces": False
}
}
},
{
"module": "renderer.NewRenderer",
"config": {
"auto_tile_size": True,
"max_bounces": True,
"cycles": {
"samples": 255
"value": 255
}
}
}
Expand All @@ -87,7 +87,7 @@ Config file:
Inside the `renderer.NewRenderer` module:

```python
self.get_int("cycles/samples", 42)
self.get_int("cycles/value", 42)
# -> 255

self.get_float("pixel_aspect_x")
Expand All @@ -96,13 +96,13 @@ self.get_float("pixel_aspect_x")
self.get_string("output_dir", "output/")
# -> /tmp/ this value is drawn from the GlobalStorage

self.get_bool("auto_tile_size")
self.get_bool("max_bounces")
# -> True

self.config.get_int("resolution_x", 512)
# -> 512

self.config.get_int("tile_x")
self.config.get_int("example_value")
# -> throws an error
```

Expand Down
6 changes: 3 additions & 3 deletions blenderproc/api/renderer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

from blenderproc.python.renderer.RendererUtility import set_denoiser, set_light_bounces, toggle_auto_tile_size, \
set_tile_size, set_cpu_threads, toggle_stereo, set_simplify_subdivision_render, set_adaptive_sampling, \
set_samples, enable_distance_output, enable_depth_output, enable_normals_output, enable_diffuse_color_output,\
from blenderproc.python.renderer.RendererUtility import set_denoiser, set_light_bounces, \
set_cpu_threads, toggle_stereo, set_simplify_subdivision_render, set_noise_threshold, \
set_max_amount_of_samples, enable_distance_output, enable_depth_output, enable_normals_output, enable_diffuse_color_output,\
map_file_format_to_file_ending, render, set_output_format, enable_motion_blur, set_world_background
from blenderproc.python.renderer.SegMapRendererUtility import render_segmap
from blenderproc.python.renderer.FlowRendererUtility import render_optical_flow
Expand Down
2 changes: 1 addition & 1 deletion blenderproc/python/modules/renderer/FlowRenderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(self, config):

def run(self):
with Utility.UndoAfterExecution():
self._configure_renderer(default_samples=1)
self._configure_renderer(max_amount_of_samples=1)

if not self._avoid_output:
render_optical_flow(
Expand Down
25 changes: 4 additions & 21 deletions blenderproc/python/modules/renderer/RendererInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,6 @@ class RendererInterface(Module):
This means pixel is sampled until the noise level is smaller than specified or the maximum amount of
samples were reached. Do not use this with Non-RGB-Renders! Only used if specified" in config. Default: 0.0
- float
* - auto_tile_size
- If true, then the number of render tiles is set automatically using the render_auto_tile_size addon.
Default: True.
- bool
* - tile_x
- The number of separate render tiles to use along the x-axis. Ignored if auto_tile_size is set to true.
- int
* - tile_y
- The number of separate render tiles to use along the y-axis. Ignored if auto_tile_size is set to true.
- int
* - simplify_subdivision_render
- Global maximum subdivision level during rendering. Speeds up rendering. Default: 3
- int
Expand Down Expand Up @@ -125,28 +115,21 @@ class RendererInterface(Module):

def __init__(self, config: Config):
Module.__init__(self, config)
addon_utils.enable("render_auto_tile_size")

def _configure_renderer(self, default_samples: int = 256, use_denoiser: bool = False,
def _configure_renderer(self, max_amount_of_samples: int = 1024, use_denoiser: bool = False,
default_denoiser: str = "Intel"):
"""
Sets many different render parameters which can be adjusted via the config.
:param default_samples: Default number of samples to render for each pixel
:param max_amount_of_samples: Default maximum number of samples to render for each pixel
:param use_denoiser: If true, a denoiser is used, only use this on color information
:param default_denoiser: Either "Intel" or "Blender", "Intel" performs much better in most cases
"""
RendererUtility._render_init()
RendererUtility.set_samples(self.config.get_int("samples", default_samples))
RendererUtility.set_max_amount_of_samples(self.config.get_int("samples", max_amount_of_samples))

if self.config.has_param("use_adaptive_sampling"):
RendererUtility.set_adaptive_sampling(self.config.get_float("use_adaptive_sampling"))

if self.config.get_bool("auto_tile_size", True):
RendererUtility.toggle_auto_tile_size(True)
else:
RendererUtility.toggle_auto_tile_size(False)
RendererUtility.set_tile_size(self.config.get_int("tile_x"), self.config.get_int("tile_y"))
RendererUtility.set_noise_threshold(self.config.get_float("use_adaptive_sampling"))

# Set number of cpu cores used for rendering (1 thread is always used for coordination => 1
# cpu thread means GPU-only rendering)
Expand Down
2 changes: 1 addition & 1 deletion blenderproc/python/modules/renderer/SegMapRenderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def run(self):
default_values = self.config.get_raw_dict("default_values", {})

with Utility.UndoAfterExecution():
self._configure_renderer(default_samples=1)
self._configure_renderer(max_amount_of_samples=1)

if not self._avoid_output:
render_segmap(
Expand Down
7 changes: 4 additions & 3 deletions blenderproc/python/renderer/FlowRendererUtility.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ def render_optical_flow(output_dir: str = None, temp_dir: str = None, get_forwar

with Utility.UndoAfterExecution():
RendererUtility._render_init()
RendererUtility.set_samples(1)
RendererUtility.set_adaptive_sampling(0)
# the amount of samples must be one and there can not be any noise threshold
RendererUtility.set_max_amount_of_samples(1)
RendererUtility.set_noise_threshold(0)
RendererUtility.set_denoiser(None)
RendererUtility.set_light_bounces(1, 0, 0, 1, 0, 8, 0)

Expand Down Expand Up @@ -104,7 +105,7 @@ def _output_vector_field(forward_flow: bool, backward_flow: bool, output_dir: st
# Flow settings (is called "vector" in blender)
bpy.context.scene.render.use_compositing = True
bpy.context.scene.use_nodes = True
bpy.context.scene.view_layers["View Layer"].use_pass_vector = True
bpy.context.view_layer.use_pass_vector = True

# Adapt compositor to output vector field
tree = bpy.context.scene.node_tree
Expand Down
5 changes: 3 additions & 2 deletions blenderproc/python/renderer/NOCSRendererUtility.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ def render_nocs(output_dir: Optional[str] = None, file_prefix: str = "nocs_", ou

# Set all fast rendering parameters with only one ray per pixel
RendererUtility._render_init()
RendererUtility.set_samples(1)
RendererUtility.set_adaptive_sampling(0)
# the amount of samples must be one and there can not be any noise threshold
RendererUtility.set_max_amount_of_samples(1)
RendererUtility.set_noise_threshold(0)
RendererUtility.set_denoiser(None)
RendererUtility.set_light_bounces(1, 0, 0, 1, 0, 8, 0)
bpy.context.scene.cycles.filter_width = 0.0
Expand Down
55 changes: 19 additions & 36 deletions blenderproc/python/renderer/RendererUtility.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def set_denoiser(denoiser: Optional[str]):
Automatically disables all previously activated denoiser.
:param denoiser: The name of the denoiser which should be enabled. Options are "INTEL", "OPTIX", "BLENDER" and None. \
:param denoiser: The name of the denoiser which should be enabled. Options are "INTEL", "OPTIX" and None. \
If None is given, then no denoiser will be active.
"""
# Make sure there is no denoiser active
Expand Down Expand Up @@ -54,10 +54,6 @@ def set_denoiser(denoiser: Optional[str]):

links.new(render_layer_node.outputs['DiffCol'], denoise_node.inputs['Albedo'])
links.new(render_layer_node.outputs['Normal'], denoise_node.inputs['Normal'])
elif denoiser.upper() == "BLENDER":
bpy.context.scene.cycles.use_denoising = True
bpy.context.view_layer.cycles.use_denoising = True
bpy.context.scene.cycles.denoiser = "NLM"
else:
raise Exception("No such denoiser: " + denoiser)

Expand Down Expand Up @@ -95,27 +91,6 @@ def set_light_bounces(diffuse_bounces: Optional[int] = None, glossy_bounces: Opt
bpy.context.scene.cycles.volume_bounces = volume_bounces


def toggle_auto_tile_size(enable: bool):
""" Enables/Disables the automatic tile size detection via the render_auto_tile_size addon.
:param enable: True, if it should be enabled.
"""
bpy.context.scene.ats_settings.is_enabled = enable


def set_tile_size(tile_x: int, tile_y: int):
""" Sets the rendering tile size.
This will automatically disable the automatic tile size detection.
:param tile_x: The horizontal tile size in pixels.
:param tile_y: The vertical tile size in pixels.
"""
toggle_auto_tile_size(False)
bpy.context.scene.render.tile_x = tile_x
bpy.context.scene.render.tile_y = tile_y


def set_cpu_threads(num_threads: int):
""" Sets the number of CPU cores to use simultaneously while rendering.
Expand Down Expand Up @@ -151,27 +126,35 @@ def set_simplify_subdivision_render(simplify_subdivision_render: int):
bpy.context.scene.render.use_simplify = False


def set_adaptive_sampling(adaptive_threshold: float):
""" Configures adaptive sampling.
def set_noise_threshold(noise_threshold: float):
""" Configures the adaptive sampling, the noise threshold is typically between 0.1 and 0.001.
Adaptive sampling automatically decreases the number of samples per pixel based on estimated level of noise.
:param adaptive_threshold: Noise level to stop sampling at. If 0 is given, adaptive sampling is disabled.
We do not recommend setting the noise threshold value to zero and therefore turning off the adaptive sampling.
For more information see the official documentation:
https://docs.blender.org/manual/en/latest/render/cycles/render_settings/sampling.html#adaptive-sampling
:param noise_threshold: Noise level to stop sampling at. If 0 is given, adaptive sampling is disabled and only the
max amount of samples is used.
"""
if adaptive_threshold > 0:
if noise_threshold > 0:
bpy.context.scene.cycles.use_adaptive_sampling = True
bpy.context.scene.cycles.adaptive_threshold = adaptive_threshold
bpy.context.scene.cycles.adaptive_threshold = noise_threshold
else:
bpy.context.scene.cycles.use_adaptive_sampling = False


def set_samples(samples: int):
""" Sets the number of samples to render for each pixel.
def set_max_amount_of_samples(samples: int):
""" Sets the maximum number of samples to render for each pixel.
This maximum amount is usually not reached if the noise threshold is low enough.
If the noise threshold was set to 0, then only the maximum number of samples is used (We do not recommend this).
:param samples: The number of samples per pixel
:param samples: The maximum number of samples per pixel
"""
bpy.context.scene.cycles.samples = samples


def enable_distance_output(activate_antialiasing: bool, output_dir: Optional[str] = None, file_prefix: str = "distance_",
output_key: str = "distance", antialiasing_distance_max: float = None,
convert_to_depth: bool = False):
Expand Down Expand Up @@ -616,4 +599,4 @@ def set_world_background(color: List[float], strength: float = 1):
links.remove(nodes.get("Background").inputs['Color'].links[0])

nodes.get("Background").inputs['Strength'].default_value = strength
nodes.get("Background").inputs['Color'].default_value = color + [1]
nodes.get("Background").inputs['Color'].default_value = color + [1]
5 changes: 3 additions & 2 deletions blenderproc/python/renderer/SegMapRendererUtility.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ def render_segmap(output_dir: Optional[str] = None, temp_dir: Optional[str] = No

with Utility.UndoAfterExecution():
RendererUtility._render_init()
RendererUtility.set_samples(1)
RendererUtility.set_adaptive_sampling(0)
# the amount of samples must be one and there can not be any noise threshold
RendererUtility.set_max_amount_of_samples(1)
RendererUtility.set_noise_threshold(0)
RendererUtility.set_denoiser(None)
RendererUtility.set_light_bounces(1, 0, 0, 1, 0, 8, 0)

Expand Down
8 changes: 6 additions & 2 deletions blenderproc/python/types/StructUtility.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ def get_all_cps(self) -> list:

def clear_all_cps(self):
""" Removes all existing custom properties the struct has. """
keys = self.blender_obj.keys()
for key in keys:
# iterating over the keys is not possible as deleting them changes the structure of the
# underlying blender object -> to solve this we always remove only the first element until no element is left
while len(self.blender_obj.keys()) > 0:
# extract first element of the keys
key = list(self.blender_obj.keys())[0]
# delete this first element
del self.blender_obj[key]

def get_attr(self, attr_name: str) -> Any:
Expand Down
5 changes: 3 additions & 2 deletions blenderproc/python/utility/DefaultConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class DefaultConfig:
color_depth = 8
enable_transparency = False
jpg_quality = 95
samples = 100
samples = 1024
sampling_noise_threshold = 0.01
cpu_threads = 1
denoiser = "INTEL"
simplify_subdivision_render = 3
Expand All @@ -37,4 +38,4 @@ class DefaultConfig:

# Setup
default_pip_packages = ["wheel", "pyyaml==5.1.2", "imageio==2.9.0", "gitpython==3.1.18", "scikit-image==0.18.3", "pypng==0.0.20", "scipy==1.7.1",
"matplotlib==3.4.3", "pytz==2021.1", "h5py==3.4.0", "Pillow==8.3.2", "opencv-contrib-python==4.5.3.56", "scikit-learn==0.24.2"]
"matplotlib==3.4.3", "pytz==2021.1", "h5py==3.4.0", "Pillow==8.3.2", "opencv-contrib-python==4.5.3.56", "scikit-learn==0.24.2"]
10 changes: 4 additions & 6 deletions blenderproc/python/utility/Initializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ def init(horizon_color: list = [0.05, 0.05, 0.05], compute_device: str = "GPU",
if found:
break
# make sure that all visible GPUs are used
for group in prefs.get_devices():
for d in group:
d.use = True
for device in prefs.devices:
device.use = True

# Set the Experimental features on/off
if use_experimental_features:
Expand Down Expand Up @@ -117,9 +116,8 @@ def set_default_parameters():

# Init renderer
RendererUtility._render_init()
RendererUtility.set_samples(DefaultConfig.samples)
addon_utils.enable("render_auto_tile_size")
RendererUtility.toggle_auto_tile_size(True)
RendererUtility.set_max_amount_of_samples(DefaultConfig.samples)
RendererUtility.set_noise_threshold(DefaultConfig.sampling_noise_threshold)

# Set number of cpu cores used for rendering (1 thread is always used for coordination => 1
# cpu thread means GPU-only rendering)
Expand Down
2 changes: 1 addition & 1 deletion blenderproc/python/utility/InstallUtility.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def make_sure_blender_is_installed(custom_blender_path: str, blender_install_pat

# Determine configured version
# right new only support blender-2.93
major_version = "2.93"
major_version = "3.0"
minor_version = "0"
blender_version = "blender-{}.{}".format(major_version, minor_version)
if platform == "linux" or platform == "linux2":
Expand Down
12 changes: 7 additions & 5 deletions docs/tutorials/renderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,18 @@ In [depth images](https://en.wikipedia.org/wiki/Depth_map), each pixel contains

As blender uses a raytracer, the number of rays influences the required amount of computation and the noise in the rendered image.
The more rays are computed, the longer the rendering takes, but the more accurate and less noisy the resulting image is.
The number of rays can be controlled by using `bproc.renderer.set_samples(num_samples)`.
Hereby, `num_samples` sets the number of rays that are traced per pixel.
The noise level can be controlled by using `brpoc.renderer.set_noise_threshold(noise_threshold)`.
This means that for each pixel only so many rays are used to get below this noise threshold.
Hereby, `noise_threshold` is a float value above `0` and below `0.1`.
A higher value means more noise per pixel, a lower value results in less noise but longer computation time.
You can influence the maximum amount of samples per pixel with the `bproc.rendererset_max_amount_of_samples(max_amount_of_samples)` fct.
For more information about how blenders renderer works visit the [blender docu](https://docs.blender.org/manual/en/latest/render/cycles/render_settings/sampling.html).

The required amount of samples is unfortunately quite high to achieve a smooth result and therefore rendering can take quite long.
To reduce the number of required samples, blender offers Denoiser to reduce the noise in the resulting image.
The required noise level is unfortunately quite low to achieve a smooth result and therefore rendering can take quite long.
To reduce the number of required samples per pixel, blender offers Denoiser to reduce the noise in the resulting image.
Set them via `bproc.renderer.set_denoiser`:

* `bproc.renderer.set_denoiser("INTEL")`: Activates Intels [Open Image Denoiser](https://www.openimagedenoise.org/)
* `bproc.renderer.set_denoiser("BLENDER")`: Uses blenders built-in denoiser.
* `bproc.renderer.set_denoiser(None)`: Deactivates any denoiser.

Per default "INTEL" is used.
Expand Down
2 changes: 0 additions & 2 deletions examples/advanced/camera_depth_of_field/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@
# activate normal and depth rendering
bproc.renderer.enable_normals_output()
bproc.renderer.enable_depth_output(activate_antialiasing=False)
# set the amount of samples, which should be used for the color rendering
bproc.renderer.set_samples(350)

# render the whole pipeline
data = bproc.renderer.render()
Expand Down
3 changes: 0 additions & 3 deletions examples/advanced/coco_annotations/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@
# activate normal rendering
bproc.renderer.enable_normals_output()

# set the amount of samples, which should be used for the color rendering
bproc.renderer.set_samples(50)

# render the whole pipeline
data = bproc.renderer.render()
seg_data = bproc.renderer.render_segmap(map_by=["instance", "class", "name"])
Expand Down
2 changes: 0 additions & 2 deletions examples/advanced/diffuse_color_image/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
bproc.renderer.enable_depth_output(activate_antialiasing=False)
# Also enable the diffuse color image, which describes the base color of the textures
bproc.renderer.enable_diffuse_color_output()
# set the amount of samples, which should be used for the color rendering
bproc.renderer.set_samples(350)

# render the whole pipeline
data = bproc.renderer.render()
Expand Down
Loading

0 comments on commit 740404a

Please sign in to comment.