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

Added initial draft for OSL closures #614

Merged
Changes from 1 commit
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
77 changes: 69 additions & 8 deletions libraries/stdlib/osl/stdosl.h
Original file line number Diff line number Diff line change
Expand Up @@ -580,13 +580,20 @@ closure color subsurface(float eta, float g, color mfp, color albedo) BUILTIN;
// -------------------------------------------------------------//
// Constructs a diffuse reflection BSDF based on the Oren-Nayar reflectance model.
// A roughness of 0.0 gives Lambertian reflectance.
//
// \param N Normal vector of the surface point beeing shaded.
// \param albedo Surface albedo.
// \param roughness Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
//
closure color oren_nayar_diffuse_bsdf(normal N, color albedo, float roughness) BUILTIN;
// Constructs a diffuse reflection BSDF based on the corresponding component of
// the Disney Principled shading model.
//
// \param N Normal vector of the surface point beeing shaded.
// \param albedo Surface albedo.
// \param roughness Surface roughness [0,1].
//
closure color burley_diffuse_bsdf(normal N, color albedo, float roughness) BUILTIN;
// Constructs a reflection and/or transmission BSDF based on a microfacet reflectance
Expand All @@ -601,13 +608,32 @@ closure color burley_diffuse_bsdf(normal N, color albedo, float roughness) BUILT
// a VDF closure describing the surface interior to handle absorption and scattering
// inside the medium.
//
// \param N Normal vector of the surface point beeing shaded.
// \param U Tangent vector of the surface point beeing shaded.
// \param reflection_tint Weight per color channel for the reflection lobe. Should be (1,1,1) for a physically-correct dielectric surface,
// but can be tweaked for artistic control. Set to (0,0,0) to disable reflection.
// \param transmission_tint Weight per color channel for the transmission lobe. Should be (1,1,1) for a physically-correct dielectric surface,
// but can be tweaked for artistic control. Set to (0,0,0) to disable transmission.
// \param roughness_x Surface roughness in the U direction. Valid range [0,1] with a perceptually linear response over the range.
// \param roughness_y Surface roughness in the V direction. Valid range [0,1] with a perceptually linear response over the range.
// \param ior Refraction index.
// \param distribution Microfacet distribution. An implementation is expected to support the following distributions: { "ggx" }
//
closure color dielectric_bsdf(normal N, vector U, color reflection_tint, color transmission_tint, float roughness_x, float roughness_y, float ior, string distribution) BUILTIN;
// Constructs a reflection BSDF based on a microfacet reflectance model.
// Uses a Fresnel curve with complex refraction index for conductors/metals.
// If an artistic parametrization is preferred the artistic_ior() utility function
// can be used to convert from artistic to physical parameters.
//
// \param N Normal vector of the surface point beeing shaded.
// \param U Tangent vector of the surface point beeing shaded.
// \param roughness_x Surface roughness in the U direction. Valid range [0,1] with a perceptually linear response over the range.
niklasharrysson marked this conversation as resolved.
Show resolved Hide resolved
// \param roughness_y Surface roughness in the V direction. Valid range [0,1] with a perceptually linear response over the range.
// \param ior Refraction index.
// \param extinction Extinction coefficient.
// \param distribution Microfacet distribution. An implementation is expected to support the following distributions: { "ggx" }
//
closure color conductor_bsdf(normal N, vector U, float roughness_x, float roughness_y, color ior, color extinction, string distribution) BUILTIN;
niklasharrysson marked this conversation as resolved.
Show resolved Hide resolved
// Constructs a reflection and/or transmission BSDF based on a microfacet reflectance model
Expand All @@ -620,15 +646,23 @@ closure color conductor_bsdf(normal N, vector U, float roughness_x, float roughn
// a VDF closure describing the surface interior to handle absorption and scattering
// inside the medium.
//
// TODO:
// - Transmission handling for this node has not been fully defined yet in MaterialX.
// In particular how is IOR for refractions derived from the f0, f90 parameterization?
// Do we just derive it from f0? For an artist it seems hard to control refractions that way.
// \param N Normal vector of the surface point beeing shaded.
// \param U Tangent vector of the surface point beeing shaded.
// \param reflection_tint Weight per color channel for the reflection lobe. Set to (0,0,0) to disable reflection.
// \param transmission_tint Weight per color channel for the transmission lobe. Set to (0,0,0) to disable transmission.
// \param roughness_x Surface roughness in the U direction. Valid range [0,1] with a perceptually linear response over the range.
// \param roughness_y Surface roughness in the V direction. Valid range [0,1] with a perceptually linear response over the range.
// \param f0 Reflectivity per color channel at facing angles.
// \param f90 Reflectivity per color channel at grazing angles.
// \param distribution Microfacet distribution. An implementation is expected to support the following distributions: { "ggx" }
//
closure color generalized_schlick_bsdf(normal N, vector U, color reflection_tint, color transmission_tint, float roughness_x, float roughness_y, color f0, color f90, float exponent, string distribution) BUILTIN;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is external IOR / IOR layering tracked? If it's done behind the scenes by passing the IOR ratio to the closure, that may not be enough information for the generalized Schlick BSDF closure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nhoffman-lucasfilm That's a great question. I believe this will be tracked through the use of the medium_vdf closure that describes the medium which the light travels through before hitting a new interface. The medium_vdf has an ior parameter that is an absolute IOR value for the medium.

For the primary intersection I guess air/vacuum is assumed outside. I'm not sure how it's handled for situations where the camera starts inside, like a camera under water, but I suppose a media closure could be attached to the camera.

For cases where BSDFs are layered without the use of media in-between I think all the needed information should be available still, since IOR could be derived from the parameters on each BSDF.

But maybe people from Imageworks, Adsk/Arnold or other teams that have implemented OSL closures in practice can fill in more details here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We attach medium data to every ray (if present). If a camera is inside some medium we find the object and evaluate the shader to grab what you're calling medium_vdf here. We also compute relative IOR outside the shader. Basically we intercept the BSDF creation from closure data and override the IOR parameters.

May be worth mentioning that we have an optional parameter to all bsdfs called "force_eta" (float from 0 to 1). This allows the shader, and the artist, to override the dynamic IOR. For instance, if the look changes too much for them when underwater, they can tone down the change.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We track the IOR of the bulk medium as the ray transmits through dielectric boundaries, via the usual priority system approach. The interior bulk medium IOR is taken from the specular lobe in the standard surface model (i.e. this lobe effectively defines the IOR of the bulk). We don't take into account IOR jumps between the various layers in the model though (e.g the coat BSDF "above" the specular layer, is not aware of the specular IOR), which is probably a reasonable approach considering the closure mixture model is a somewhat ad-hoc representation of the layered structure anyway.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't currently handle the "camera under water" situation, unfortunately. Though it seems that determining this is a matter for the renderer to handle, e.g. by casting a ray to infinity and tracking the media.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"We also compute relative IOR outside the shader. Basically we intercept the BSDF creation from closure data and override the IOR parameters" - in other words the ratio (external_ior / bulk_ior) is passed into the closure's "ior" parameter? In that case, for the generalized_schlick_bsdf closure a different parameter adjustment would be needed, adjusting f0 using something like the equations from slides 107-108 or slide 111 in https://blog.selfshadow.com/publications/s2020-shading-course/hoffman/s2020_pbs_hoffman_slides.pdf (a similar adjustment might need to be made for the f90 parameter - I've spent a little bit of time on that but don't have a formula for that one ready yet). Would this kind of closure-specific parameter adjustment be feasible, or is does that logic need to be agnostic to which closure is used?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related question - is there a way to determine the reflection's "sidedness" inside the closure? When using IOR as a parameter, internal vs. external reflection can be easily determined from the relative IOR - if it is greater or small than 1. But 1/eta and eta produce the same value for f0, so an extra bit (literally) of information is needed to disambiguate those two cases for the generalized_schlick_bsdf closure.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not overriding the closure parameter itself, but the BSDF internal object that gets created on the renderer side. We do some translation for non-ior parametrizations, but we haven't polished that a lot, it just works. Also, this doesn't affect internal BSDF layering, we don't track stuff there.

About sidedness, our convention: The shader always puts the IOR of the front surface regardless of what side is being rendered. The implementation is responsible for doing 1/eta if on the backside. We did this to remove the burden from the shaders, but other people might have other opinions.

// Constructs a translucent (diffuse transmission) BSDF based on the Lambert reflectance model.
//
// \param N Normal vector of the surface point beeing shaded.
// \param albedo Surface albedo.
//
closure color translucent_bsdf(normal N, color albedo) BUILTIN;

// Constructs a closure that represents straight transmission through a surface.
Expand All @@ -640,7 +674,8 @@ closure color translucent_bsdf(normal N, color albedo) BUILTIN;
closure color transparent_bsdf() BUILTIN;
// Constructs a BSSRDF for subsurface scattering within a homogeneous medium.
// \param N Normal of the surface point beeing shaded.
//
// \param N Normal vector of the surface point beeing shaded.
// \param albedo Surface albedo.
// \param sss_depth Mean-free path in units of scene length.
// \param sss_color Scattering color / transmittance. The desired color resulting from white light transmitted a distance of 'sss_depth'
Expand All @@ -654,6 +689,10 @@ closure color subsurface_bssrdf(normal N, color albedo, float sss_depth, color s
// This closure may be vertically layered over a base BSDF, where energy that is not reflected
// will be transmitted to the base closure.
//
// \param N Normal vector of the surface point beeing shaded.
// \param albedo Surface albedo.
// \param roughness Surface roughness [0,1].
//
closure color sheen_bsdf(normal N, color albedo, float roughness) BUILTIN;
// Adds an iridescent thin film layer over a microfacet base BSDF. This must be layered over
niklasharrysson marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -664,6 +703,9 @@ closure color sheen_bsdf(normal N, color albedo, float roughness) BUILTIN;
// - This might be better to represent as optional extra arguments on the closures that do support
// thin-film iridescence (dielectric_bsdf, conductor_bsdf and generalized_schlick_bsdf)?
//
// \param thickness Thickness of the thin film.
// \param ior Refraction index of the thin film.
//
closure color thin_film_bsdf(float thickness, float ior) BUILTIN;
Expand All @@ -673,10 +715,18 @@ closure color thin_film_bsdf(float thickness, float ior) BUILTIN;
// Constructs an EDF emitting light uniformly in all directions.
//
// \param emittance Radiant emittance of light leaving the surface.
//
closure color uniform_edf(color emittance) BUILTIN;

// Constructs an EDF emitting light inside a cone around the normal direction.
//
// \param emittance Radiant emittance of light leaving the surface.
// \param N Cone direction vector.
niklasharrysson marked this conversation as resolved.
Show resolved Hide resolved
// \param inner_angle Angle of inner cone where emission falloff starts.
// \param outer_angle Angle of outer cone where emission goes to zero. If set to a smaller value
// than inner_angle no falloff will occur within the cone.
//
closure color conical_edf(color emittance, normal N, float inner_angle, float outer_angle) BUILTIN;
Expand All @@ -687,7 +737,8 @@ closure color conical_edf(color emittance, normal N, float inner_angle, float ou
// Constructs a VDF scattering light for a participating medium, based on the Henyey-Greenstein
// phase function. Forward, backward and uniform scattering is supported and controlled by the
// anisotropy input.
// \param albedo Volume albedo.
//
niklasharrysson marked this conversation as resolved.
Show resolved Hide resolved
// \param albedo Volume single scattering albedo.
// \param extinction Volume extinction coefficient.
// \param anisotropy Scattering anisotropy [-1,1]. Negative values give backwards scattering, positive values give forward scattering,
// and 0.0 gives uniform scattering.
Expand All @@ -706,6 +757,9 @@ closure color anisotropic_vdf(color albedo, color extinction, float anisotropy)
// of handling this is by albedo scaling, using "base*(1-reflectance(top)) + top", where
// reflectance() calculates the directional albedo of a given top BSDF.
//
// \param top Closure defining the top layer.
// \param base Closure defining the base layer.
//
// TODO:
// - This could also be achived by closure nesting where each layerable closure takes
// a closure color "base" input instead.
Expand All @@ -725,8 +779,15 @@ closure color layer(closure color top, closure color base) BUILTIN;
// Converts the artistic parameterization reflectivity and edge_color to complex IOR values.
// To be used with the conductor_bsdf() closure.
// [OG14] "Artist Friendly Metallic Fresnel", http://jcgt.org/published/0003/04/03/paper.pdf
//
// \param reflectivity Reflectivity per color channel at facing angles ('r' parameter in [OG14]).
// \param edge_tint Color bias for grazing angles ('g' parameter in [OG14]).
// NOTE: This is not equal to 'f90' in a Schlick Fresnel parameterization.
// \param ior Output refraction index.
// \param extinction Output extinction coefficient.
//
void artistic_ior(color reflectivity, color edge_color, output color ior, output color extinction);
void artistic_ior(color reflectivity, color edge_tint, output color ior, output color extinction);

// ******************* MATERIALX PBS LIBRARY CLOSURES - DRAFT END ******************* //
Expand Down