Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layer closure implementation in testrender #1538

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 110 additions & 7 deletions src/testrender/shading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1039,9 +1039,107 @@ struct MxSheen final : public BSDF, MxSheenParams {
};


Color3 clamp(const Color3& c, float min, float max)
{
return Color3(c.x < min ? min : max < c.x ? max : c.x,
c.y < min ? min : max < c.y ? max : c.y,
c.z < min ? min : max < c.z ? max : c.z);
}

bool is_black(const Color3& c)
{
return c.x == 0 && c.y == 0 && c.z == 0;
}

Color3
evaluate_layer_opacity(const OSL::ShaderGlobals& sg, const ClosureColor* closure)
{
static const ustring u_ggx("ggx");

// Null closure, the layer is fully transparent
if (!closure)
return Color3(0);

switch (closure->id) {
case ClosureColor::MUL:
return closure->as_mul()->weight * evaluate_layer_opacity(sg, closure->as_mul()->closure);
case ClosureColor::ADD:
return evaluate_layer_opacity(sg, closure->as_add()->closureA) +
evaluate_layer_opacity(sg, closure->as_add()->closureB);
default: {
const ClosureComponent* comp = closure->as_comp();
Color3 w = comp->w;
switch (comp->id) {
case MX_LAYER_ID : {
const MxLayerParams* srcparams = comp->as<MxLayerParams>();
return w * (evaluate_layer_opacity(sg, srcparams->top) +
evaluate_layer_opacity(sg, srcparams->base));
}
case REFLECTION_ID:
case FRESNEL_REFLECTION_ID: {
Reflection bsdf(*comp->as<ReflectionParams>());
return w * bsdf.get_albedo(sg);
}
case MX_GENERALIZED_SCHLICK_ID: {
const MxGeneralizedSchlickParams* srcparams = comp->as<MxGeneralizedSchlickParams>();
// Transmissive dielectrics are opaque
if (!is_black(srcparams->transmission_tint))
return Color3(1);
MicrofacetParams params = {};
params.N = srcparams->N;
params.U = srcparams->U;
params.dist = srcparams->distribution;
params.xalpha = srcparams->roughness_x;
params.yalpha = srcparams->roughness_y;
params.eta = 100.0f; // TODO: support generalized fresnel equation properly
if (params.dist == u_ggx) {
Microfacet<GGXDist, 0> mf(params);
return w * mf.get_albedo(sg);
}
else // assume beckman
{
Microfacet<BeckmannDist, 0> mf(params);
return w * mf.get_albedo(sg);
}
}
case MX_DIELECTRIC_ID : {
const MxDielectricParams* srcparams = comp->as<MxDielectricParams>();
// Transmissive dielectrics are opaque
if (is_black(srcparams->transmission_tint))
return Color3(1);
MicrofacetParams params = {};
params.N = srcparams->N;
params.U = srcparams->U;
params.dist = srcparams->distribution;
params.xalpha = srcparams->roughness_x;
params.yalpha = srcparams->roughness_y;
params.eta = srcparams->ior;
if (params.dist == u_ggx) {
Microfacet<GGXDist, 0> mf(params);
return w * mf.get_albedo(sg);
}
else // assume beckman
{
Microfacet<BeckmannDist, 0> mf(params);
return w * mf.get_albedo(sg);
}
}
case MX_SHEEN_ID: {
MxSheen bsdf(*comp->as<MxSheenParams>());
return w * bsdf.get_albedo(sg);
}
default : // Assume unhandled BSDFs are opaque
return Color3(1);
}
}
}
OSL_ASSERT(false && "Layer opacity evaluation failed");
return Color3(0);
}

// recursively walk through the closure tree, creating bsdfs as we go
void
process_closure(ShadingResult& result, const ClosureColor* closure,
process_closure(const OSL::ShaderGlobals& sg, ShadingResult& result, const ClosureColor* closure,
const Color3& w, bool light_only)
{
static const ustring u_ggx("ggx");
Expand All @@ -1052,12 +1150,12 @@ process_closure(ShadingResult& result, const ClosureColor* closure,
switch (closure->id) {
case ClosureColor::MUL: {
Color3 cw = w * closure->as_mul()->weight;
process_closure(result, closure->as_mul()->closure, cw, light_only);
process_closure(sg, result, closure->as_mul()->closure, cw, light_only);
break;
}
case ClosureColor::ADD: {
process_closure(result, closure->as_add()->closureA, w, light_only);
process_closure(result, closure->as_add()->closureB, w, light_only);
process_closure(sg, result, closure->as_add()->closureA, w, light_only);
process_closure(sg, result, closure->as_add()->closureB, w, light_only);
break;
}
default: {
Expand Down Expand Up @@ -1222,7 +1320,12 @@ process_closure(ShadingResult& result, const ClosureColor* closure,
break;
}
case MX_LAYER_ID: {
OSL_ASSERT(false && "MaterialX closure not yet implemented");
const MxLayerParams* srcparams = comp->as<MxLayerParams>();
Color3 base_w = w * (Color3(1, 1, 1) - clamp(evaluate_layer_opacity(sg, srcparams->top), 0.f, 1.f));
process_closure(sg, result, srcparams->top, w, light_only);
if (!is_black(base_w))
process_closure(sg, result, srcparams->base, base_w, light_only);
ok = true;
break;
}
}
Expand All @@ -1238,9 +1341,9 @@ process_closure(ShadingResult& result, const ClosureColor* closure,
OSL_NAMESPACE_ENTER

void
process_closure(ShadingResult& result, const ClosureColor* Ci, bool light_only)
process_closure(const OSL::ShaderGlobals& sg, ShadingResult& result, const ClosureColor* Ci, bool light_only)
{
::process_closure(result, Ci, Color3(1, 1, 1), light_only);
::process_closure(sg, result, Ci, Color3(1, 1, 1), light_only);
}

Vec3
Expand Down
2 changes: 1 addition & 1 deletion src/testrender/shading.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ struct ShadingResult {
void
register_closures(ShadingSystem* shadingsys);
void
process_closure(ShadingResult& result, const ClosureColor* Ci, bool light_only);
process_closure(const OSL::ShaderGlobals& sg, ShadingResult& result, const ClosureColor* Ci, bool light_only);
Vec3
process_background_closure(const ClosureColor* Ci);

Expand Down
4 changes: 2 additions & 2 deletions src/testrender/simpleraytracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
shadingsys->execute(*ctx, *m_shaders[shaderID], sg);
ShadingResult result;
bool last_bounce = b == max_bounces;
process_closure(result, sg.Ci, last_bounce);
process_closure(sg, result, sg.Ci, last_bounce);

// add self-emission
float k = 1;
Expand Down Expand Up @@ -960,7 +960,7 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
// execute the light shader (for emissive closures only)
shadingsys->execute(*ctx, *m_shaders[shaderID], light_sg);
ShadingResult light_result;
process_closure(light_result, light_sg.Ci, true);
process_closure(light_sg, light_result, light_sg.Ci, true);
// accumulate contribution
path_radiance += contrib * light_result.Le;
}
Expand Down
1 change: 1 addition & 0 deletions testsuite/render-mx-layer/NOOPTIMIZE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Render too expensive without optimization
19 changes: 19 additions & 0 deletions testsuite/render-mx-layer/envmap.osl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage

shader envmap(
color sky = color(0.7,0.8,0.9),
color horizon = color(0.3,0.6,0.9),
color sun = color(0.9,0.8,0.7),
vector sun_dir = vector(1,1,1),
float sun_angle = 5.0)
{
vector dir = normalize(I);
vector sd = normalize(sun_dir);
color c = mix(horizon, sky, dir.y * dir.y);
float cos_ang = cos(radians(sun_angle / 2));
if (dot(dir, normalize(sun_dir)) > cos_ang)
c += sun / (1 - cos_ang); // normalize
Ci = c * background();
}
16 changes: 16 additions & 0 deletions testsuite/render-mx-layer/layer.osl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage


surface
layer
[[ string description = "Layered material" ]]
(
color Cs = 1
[[ string description = "Base color",
float UImin = 0, float UImax = 1 ]],
)
{
Ci = layer(color(0, 0.1, 0) * sheen_bsdf(N, 1, 0), layer(layer(color(.8, 1, 1) * reflection(N, 1.5), oren_nayar_diffuse_bsdf(N, Cs, 1.0)), color(0, 1, 0) * diffuse(N)));
}
Binary file added testsuite/render-mx-layer/ref/out.exr
Binary file not shown.
9 changes: 9 additions & 0 deletions testsuite/render-mx-layer/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env python

# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage

failthresh = 0.005 # allow a little more LSB noise between platforms
outputs = [ "out.exr" ]
command = testrender("-r 320 240 -aa 6 scene.xml out.exr")
14 changes: 14 additions & 0 deletions testsuite/render-mx-layer/scene.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<World>
<Camera eye="0, 0, 10" look_at="0,0,0" fov="30" />

<ShaderGroup>
shader envmap layer1;
</ShaderGroup>
<Background resolution="1024" />

<ShaderGroup>
param color Cs 0.8 0.1 0.2;
shader layer layer1;
</ShaderGroup>
<Sphere center="0,0,0" radius="1.0" />
</World>