Skip to content

Commit 941beb9

Browse files
Fix rendering energy loss in RenderEngineVtk
Energy loss is due to three issues. 1. Drake introduced an erroneous patch which bled energy badly. 2. Set the skybox to use gamma correction, even for hdr images. 3. Introduce a *new* patch to change the VTK brdf model from a single-scatter approximation to a multi-scatter approximation. This will have an immediate change on rendered outputs -- images will be brighter. Based on brightness changes: 1. The lighting configuration tutorial has been updated accordingly. 2. The unit tests for RenderEngineVtk have had reference values (subject to PBR) brightened accordingly. Current camera configurations will need to be updated, especially with respect to their exposure values and lighting levels. Renderings for which high exposure values seemed necessary will now seem oversaturated. Furthermore, with more energy coming from the environment map, lights may need to be brighter to have a comparable effect as before. TODO: - Push my model and my env map so it can be downloaded via curl. - Submit PR with instructions on how to reproduce with the given files.
1 parent b8c7707 commit 941beb9

File tree

7 files changed

+55
-53
lines changed

7 files changed

+55
-53
lines changed

geometry/render_vtk/internal_render_engine_vtk.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,8 +952,7 @@ void RenderEngineVtk::InitializePipelines() {
952952
// environment map.
953953
skybox->SetFloorRight(0, -1, 0);
954954
skybox->SetProjection(vtkSkybox::Sphere);
955-
// Linear color space (aka *not HDR*) requires gamma correction.
956-
skybox->SetGammaCorrect(!env_map.is_hdr);
955+
skybox->GammaCorrectOn();
957956
renderer->AddActor(skybox);
958957
}
959958
// Setting an environment map should require all materials to be PBR.

geometry/render_vtk/test/internal_render_engine_vtk_test.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,34 +2099,34 @@ TEST_F(RenderEngineVtkTest, EnvironmentMap) {
20992099
{.description = "Facing +Wz, toward the blue face, magenta behind; HDR",
21002100
.R_WC = RotationMatrixd(),
21012101
.bg_color = Rgba(0, 0, 1),
2102-
.sphere_color = Rgba(0.61176471, 0.38039216, 0.56470588), // magenta-ish
2102+
.sphere_color = Rgba(0.97254902, 0.62352941, 0.89411765), // magenta-ish
21032103
.map_path = hdr_path},
21042104
{.description = "Facing blue; testing the skybox",
21052105
.R_WC = RotationMatrixd(),
21062106
.bg_color = Rgba(0, 0, 1),
2107-
.sphere_color = Rgba(0.61176471, 0.38039216, 0.56470588), // magenta-ish
2107+
.sphere_color = Rgba(0.97254902, 0.62352941, 0.89411765), // magenta-ish
21082108
.map_path = hdr_path,
21092109
.show_map = false},
21102110
{.description = "Facing blue; testing the clone",
21112111
.R_WC = RotationMatrixd(),
21122112
.bg_color = Rgba(0, 0, 1),
2113-
.sphere_color = Rgba(0.61176471, 0.38039216, 0.56470588), // magenta-ish
2113+
.sphere_color = Rgba(0.97254902, 0.62352941, 0.89411765), // magenta-ish
21142114
.map_path = hdr_path,
21152115
.render_clone = true},
21162116
{.description = "Facing +Wy, toward the green face, yellow behind; HDR",
21172117
.R_WC = RotationMatrixd::MakeXRotation(M_PI / 2),
21182118
.bg_color = Rgba(0, 1, 0),
2119-
.sphere_color = Rgba(0.60784314, 0.56470588, 0.38039216), // yellow-ish
2119+
.sphere_color = Rgba(0.96862745, 0.89411765, 0.62352941), // yellow-ish
21202120
.map_path = hdr_path},
21212121
{.description = "Facing +Wx, toward the red face, cyan behind; HDR",
21222122
.R_WC = RotationMatrixd::MakeYRotation(M_PI / 2),
21232123
.bg_color = Rgba(1, 0, 0),
2124-
.sphere_color = Rgba(0.30980392, 0.60392157, 0.60392157), // cyan-ish
2124+
.sphere_color = Rgba(0.50980392, 0.96470588, 0.96470588), // cyan-ish
21252125
.map_path = hdr_path},
21262126
{.description = "Facing +Wz, toward the blue face, magenta behind; LDR",
21272127
.R_WC = RotationMatrixd(),
21282128
.bg_color = Rgba(0.0588, 0.0588, 0.9255),
2129-
.sphere_color = Rgba(0.45098039, 0.25490196, 0.39607843), // magenta-ish
2129+
.sphere_color = Rgba(0.71372549, 0.41960784, 0.61960784), // magenta-ish
21302130
.map_path = ldr_path},
21312131
};
21322132

-6.83 KB
Loading
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
The single scattering algorithm originally implemented is known to create
2+
rendering artfacts (dark, rough metals and dielectrics with overly bright
3+
fresnel reflections). This patch replaces the single-scatter model with a more
4+
modern multi-scatter approximation. (See change for reference to source.)
5+
6+
--- Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx
7+
+++ Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx
8+
@@ -1417,12 +1417,17 @@ void vtkOpenGLPolyDataMapper::ReplaceShaderLight(
9+
toString.clear();
10+
toString.str("");
11+
12+
- toString << " // In IBL, we assume that v=n, so the amount of light reflected is\n"
13+
- " // the reflectance F0\n"
14+
- " vec3 specularBrdf = F0 * brdf.r + F90 * brdf.g;\n"
15+
- " vec3 iblSpecular = prefilteredSpecularColor * specularBrdf;\n"
16+
- // no diffuse for metals
17+
- " vec3 iblDiffuse = (1.0 - F0) * (1.0 - metallic) * irradiance * albedo;\n"
18+
+ toString << " // Multi-scatter approximation: see https://bruop.github.io/ibl/\n"
19+
+ " diffuse = (1.0 - metallic) * (1.0 - 0.04) * albedo;\n"
20+
+ " vec3 Fr = max(vec3(1 - roughness), F0) - F0;\n"
21+
+ " vec3 k_S = F0 + Fr * pow(1.0 - NdV, 5.0);\n"
22+
+ " vec3 FssEss = k_S * brdf.r + F90 * brdf.g;\n"
23+
+ " float Ems = 1.0 - (brdf.r + brdf.g);\n"
24+
+ " vec3 F_avg = F0 + (1.0 - F0) / 21.0;\n"
25+
+ " vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);\n"
26+
+ " vec3 k_D = diffuse * (1.0 - FssEss - FmsEms);\n"
27+
+ " vec3 iblSpecular = FssEss * prefilteredSpecularColor;\n"
28+
+ " vec3 iblDiffuse = (FmsEms + k_D) * irradiance;\n"
29+
" vec3 color = iblDiffuse + iblSpecular;\n"
30+
"\n";
31+

tools/workspace/vtk_internal/patches/upstream/rendering_opengl2_scaled_albedo_for_ibl.patch

Lines changed: 0 additions & 37 deletions
This file was deleted.

tools/workspace/vtk_internal/repository.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,9 @@ def vtk_internal_repository(
192192
# - Patch file names should begin with the name of the module being
193193
# edited (e.g., patching IO/Image is named io_image_{foo}.patch).
194194
# - Use alphabetical order within a directory when listing patches.
195+
":patches/upstream/add_multi_scattering_to_pbr.patch",
195196
":patches/upstream/common_core_rm_iostream.patch",
196197
":patches/upstream/rendering_core_vtkcomposite_exception.patch",
197-
":patches/upstream/rendering_opengl2_scaled_albedo_for_ibl.patch",
198198
":patches/upstream/utilities_x11_more_functions.patch",
199199
":patches/common_core_fmt12.patch",
200200
":patches/common_core_fmt9.patch",

tutorials/configuring_rendering_lighting.ipynb

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,7 +1692,10 @@
16921692
"\n",
16931693
"# Center on the balls, filling the frame.\n",
16941694
"comparator.pose_camera_once(camera_in_world=[0, -3.5, 2],\n",
1695-
" target_in_world=[0, 0, 2])"
1695+
" target_in_world=[0, 0, 2])\n",
1696+
"\n",
1697+
"# Restore Meshcat exposure levels.\n",
1698+
"meshcat.SetProperty(\"/Render Settings/<object>\", \"exposure\", 1)"
16961699
]
16971700
},
16981701
{
@@ -2457,6 +2460,7 @@
24572460
"env = RenderEngineSpec(\n",
24582461
" \"Iteration 1\",\n",
24592462
" {\n",
2463+
" \"exposure\": 2,\n",
24602464
" \"lights\": [\n",
24612465
" LightParameter(type=\"directional\", frame=\"world\", direction=[0, 1, 0], intensity=10),\n",
24622466
" ],\n",
@@ -2491,6 +2495,7 @@
24912495
"env = RenderEngineSpec(\n",
24922496
" \"Iteration 2\",\n",
24932497
" {\n",
2498+
" \"exposure\": 2,\n",
24942499
" \"lights\": [\n",
24952500
" LightParameter(type=\"directional\", frame=\"world\", direction=[0, 1, -.5], intensity=10),\n",
24962501
" ],\n",
@@ -2522,6 +2527,7 @@
25222527
"env = RenderEngineSpec(\n",
25232528
" \"Iteration 3\",\n",
25242529
" {\n",
2530+
" \"exposure\": 2,\n",
25252531
" \"cast_shadows\": True,\n",
25262532
" \"lights\": [\n",
25272533
" LightParameter(type=\"directional\", frame=\"world\", direction=[0, 1, -.5], intensity=10),\n",
@@ -2555,6 +2561,7 @@
25552561
" \"Iteration 4\",\n",
25562562
" {\n",
25572563
" \"environment_map\": EnvironmentMap(texture=EquirectangularMap(path=hdr_path)),\n",
2564+
" \"exposure\": 2,\n",
25582565
" \"cast_shadows\": True,\n",
25592566
" \"lights\": [\n",
25602567
" LightParameter(type=\"directional\", frame=\"world\", direction=[0, 1, -.5], intensity=10),\n",
@@ -2582,15 +2589,18 @@
25822589
"metadata": {},
25832590
"outputs": [],
25842591
"source": [
2585-
"# Final configuration: Tone down the window light; we only want faint shadows from the window.\n",
2592+
"# Final configuration: Correct two things:\n",
2593+
"# 1. The shadows are more pronounced than we want. Dim the light to reduce the strength of the shadow.\n",
2594+
"# 2. The exposure value was set based *only* on the environment map. Adding the window light has made the scene\n",
2595+
"# over exposed. Reduce the exposure to return back to the desired levels.\n",
25862596
"env = RenderEngineSpec(\n",
25872597
" \"Iteration 5\",\n",
25882598
" {\n",
25892599
" \"environment_map\": EnvironmentMap(texture=EquirectangularMap(path=hdr_path)),\n",
25902600
" \"cast_shadows\": True,\n",
2591-
" \"exposure\": 3,\n",
2601+
" \"exposure\": 1.5,\n",
25922602
" \"lights\": [\n",
2593-
" LightParameter(type=\"directional\", frame=\"world\", direction=[0, 1, -.5], intensity=1),\n",
2603+
" LightParameter(type=\"directional\", frame=\"world\", direction=[0, 1, -.5], intensity=3.5),\n",
25942604
" ],\n",
25952605
" }\n",
25962606
")\n",
@@ -2631,14 +2641,13 @@
26312641
" \"environment_map\": EnvironmentMap(texture=EquirectangularMap(path=hdr_path)),\n",
26322642
" \"cast_shadows\": True,\n",
26332643
" \"shadow_map_size\": 1024,\n",
2634-
" # With additional lights, we reduce exposure.\n",
2635-
" \"exposure\": 2,\n",
2644+
" \"exposure\": 1, # more lights --> reduced exposure.\n",
26362645
" \"lights\": [\n",
26372646
" LightParameter(**(ceiling_light | {\"position\": [-1, 1, 3.0]})),\n",
26382647
" LightParameter(**(ceiling_light | {\"position\": [-1, -1, 3.0]})),\n",
26392648
" LightParameter(**(ceiling_light | {\"position\": [1, 1, 3.0]})),\n",
26402649
" LightParameter(**(ceiling_light | {\"position\": [1, -1, 3.0]})),\n",
2641-
" LightParameter(type=\"directional\", frame=\"world\", direction=[0, 1, -.5], intensity=1),\n",
2650+
" LightParameter(type=\"directional\", frame=\"world\", direction=[0, 1, -.5], intensity=5),\n",
26422651
" ],\n",
26432652
"}\n",
26442653
"env = RenderEngineSpec(\"Full Lighting\", render_config)\n",

0 commit comments

Comments
 (0)