Physically Based Rendering
in 3D Graphics

Alec Shedelbower, Wolfram Research

(RowDefault[, (Spacer1), , (Spacer1), ])  #WolframTechConf

Overview

1. What is Physically Based Rendering

2. MaterialShading Basics

3. Photorealistic Materials

4. PBR Theory

What is Physically
Based Rendering?

What is Physically Based Rendering (PBR)?

Attempt to render images by modeling light as it behaves in the real world.

Focus is placed on using physically-plausible models to achieve realistic results.

PBR Umbrella ☂

Physically based...
•  Light Sources
•  Cameras
•  Shading

Why Use Physically Based Rendering?

•  Physical Accuracy – More accurate models lead to more photorealistic renders.

•  Intuitive Parameterization – Parameters based on physical values instead of purely aesthetic ones (ex. roughness vs specular exponent).

•  Portability – PBR parameters are fairly standard across rendering programs. Easy to find freely available materials.

MaterialShading
Basics

MaterialShading – New in 12.3

Physically based shading implementation in the Wolfram Language.

MaterialShading["Gold"]

Graphics3D[{MaterialShading["Gold"],Cylinder[]},Lighting->"ThreePoint"]

MaterialShading – Graphics

Use as a 3D graphics directive:

Graphics3D[{MaterialShading["Copper"],CapsuleShape[]},Lighting->"ThreePoint"]

knot=KnotData["SolomonSeal","ImageData"];
Graphics3D[{MaterialShading["Glazed"],knot},Lighting->"ThreePoint"]

MaterialShading – Meshes

Use with MeshCellStyle:

MeshRegion[ExampleData[{"Geometry3D","Beethoven"},"MeshRegion"],MeshCellStyle->{{2,All}->MaterialShading["Bronze"]},Lighting->"ThreePoint",PlotTheme->"SmoothShading"]

MaterialShading – Plots

Use in plot functions:

Plot3D[Sin[x+y^2],{x,-3,3},{y,-2,2}, PlotPoints->80,Mesh->None,Lighting->"ThreePoint",PlotStyle->MaterialShading["Satin"]]

AnatomyPlot3D[{AnatomyStyling[<|_->MaterialShading["Gold"],(Entity["muscle", Entity["AnatomicalStructure","Muscle"], "Entity[\"AnatomicalStructure\", \"Muscle\"]", "anatomical structure"])->MaterialShading["Copper"],(Entity["skeleton", Entity["AnatomicalStructure","Skeleton"], "Entity[\"AnatomicalStructure\", \"Skeleton\"]", "anatomical structure"])-> MaterialShading["Iron"]|>],(Entity["right hand", Entity["AnatomicalStructure","RightHand"], "Entity[\"AnatomicalStructure\", \"RightHand\"]", "anatomical structure"])},Lighting->"ThreePoint",ImageSize->Medium]

Named Materials

MaterialShading["material"]

({{(Labeled[, "Aluminum"]), (Labeled[, "Brass"]), (Labeled[, "Bronze"]), (Labeled[, "Copper"]), (Labeled[, "Electrum"]), (Labeled[, "Gold"]), (Labeled[, "Iron"])}, {(Labeled[, "Pewter"]), (Labeled[, "Silver"]), (Labeled[, "Clay"]), (Labeled[, "Foil"]), (Labeled[, "Glazed"]), (Labeled[, "Plastic"]), (Labeled[, "Rubber"])}, {(Labeled[, "Satin"]), (Labeled[, "Velvet"]), , , , , }})

Modify Material Color

MaterialShading[{"material", col}]

Modify the base color of an existing named material:

knot=;
Graphics3D[{MaterialShading[{"Plastic",}],knot},Lighting->"ThreePoint"]

Custom Material

MaterialShading[<|(Subscript[param, 1]) -> (Subscript[val, 1]), ...|>]

Specify the parameters explicitly. Default material is a white, rough non-metal:

Graphics3D[{MaterialShading[<||>],knot},]

Custom Material – Base Color

Also known as albedo color. Equivalent to the standard FaceForm color.

Graphics3D[{MaterialShading[<|"BaseColor"->Red|>],knot},]

Graphics3D[{MaterialShading[<|"BaseColor"->#|>],knot},]&/@{,,}

Custom Material – Emission Color

Equivalent to Glow directive.

Graphics3D[{MaterialShading[<|"EmissionColor"->Red|>],knot},]

Graphics3D[{MaterialShading[<|"EmissionColor"->#|>],knot},]&/@{,,}

Custom Material – Roughness

Some renderers use its inverse called smoothness.

Graphics3D[{MaterialShading[<|"RoughnessCoefficient"->0.2|>],knot},]

Graphics3D[{,MaterialShading[<|"RoughnessCoefficient"->#|>],knot},]&/@{0.2,0.4,1}

Custom Material – Metallic

Specify that a material is a conductor (metal).

Graphics3D[{MaterialShading[<|"MetallicCoefficient"->1,"RoughnessCoefficient"->0.8|>],knot},]

Graphics3D[{MaterialShading[<|"MetallicCoefficient"->#,"RoughnessCoefficient"->0.75|>],knot},]&/@{0,0.5,1}

Custom Material – Anisotropy

Specify preferred direction of reflection (if any). Commonly seen in materials such as brushed metal.

Manipulate[
Graphics3D[{MaterialShading[<|"SpecularAnisotropyCoefficient"->{anisotropy,θ},"RoughnessCoefficient"->0.75`,"MetallicCoefficient"->1|>],Sphere[]},],
{anisotropy,0,1},
{θ,0,Pi}
]

Custom Material – Coat

Simulate a thin translucent coating over the base material (typically polyurethane or lacquer). Useful for modeling materials like car paint and wood floors.

Graphics3D[{MaterialShading[<|"CoatColor"->White,"CoatRoughnessCoefficient"->0.1,"MetallicCoefficient"->1.0,"RoughnessCoefficient"->0.8|>],knot},]

Graphics3D[{MaterialShading[<|"CoatColor"->#,"CoatRoughnessCoefficient"->0.1,"MetallicCoefficient"->1.0,"RoughnessCoefficient"->0.8|>],knot},]&/@{,,}

Graphics3D[{MaterialShading[<|"CoatColor"->White,"CoatRoughnessCoefficient"->#,"MetallicCoefficient"->1.0,"RoughnessCoefficient"->0.8|>],knot},]&/@{0.05,0.2,0.4}

Custom Material – Sheen

Some fabric with short perpendicular fibers cause backscatter at grazing angles. Similar to the rim lighting effect.

Graphics3D[{MaterialShading[<|"SheenColor"->Red,"SheenRoughnessCoefficient"->0.1|>],knot},]

Graphics3D[{MaterialShading[<|"SheenColor"->#,"SheenRoughnessCoefficient"->0.2|>],knot},]&/@{,,}

Graphics3D[{MaterialShading[<|"SheenColor"->Red,"SheenRoughnessCoefficient"->#|>],knot},]&/@{0.05,0.2,0.5}

All Parameters

Base Layer

BaseColor
SpecularColor
EmissionColor
RoughnessCoefficient
MetallicCoefficient
SpecularAnisotropyCoefficient

Coat

CoatColor
CoatRoughnessCoefficient
CoatAnisotropyCoefficient

Sheen

SheenColor
SheenRoughnessCoefficient

Other

SurfaceNormals
AmbientExposureFraction

Photorealistic Renders

Composite Materials

•  Real world objects are rarely made of a purely uniform material.

•  Parameters often vary across the surface instead of being constant.

How can we specify this variance?

Texture Maps

Concept

1. Encode parameter data as pixels in a 2D texture.
2. Define a mapping from each point on model to the 2D texture.

Examples

Specification already exists for the base color in the standard system shader:

checker=;
polygon=Polygon[{{-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1}}, 
   VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]

Graphics3D[{Texture[checker], polygon}, ]

MaterialShading equivalent:

Graphics3D[{MaterialShading[<|"BaseColor"->Texture[checker]|>], polygon}, ]

Graphics3D[{MaterialShading[<|"BaseColor"->Texture[checker]|>], #}, ]&/@{Ball[],Cuboid[]}

Beyond Base Color Mapping

MaterialShading is not limited to mapping the BaseColor – other parameters can be mapped as well.

Roughness

Graphics3D[{MaterialShading[<|"RoughnessCoefficient"->Texture[checker]|>],Sphere[]},Lighting->"Accent"]

Metallic

Graphics3D[{MaterialShading[<|"MetallicCoefficient"->Texture[checker],"RoughnessCoefficient"->0.75|>],Sphere[]},Lighting->"Accent"]

Normal Maps

Method for faking fine geometric details by adjusting surface normals.

Graphics3D[{MaterialShading[<|"SurfaceNormals"->Texture[]|>],Cuboid[]},Boxed->False,Lighting->"Accent"]

Generating Normal Maps

Generate a height map from a function:

heightMap=Image[Table[(1+Sin[x^2+y^2])/2,{x,-4,4,.05},{y,-4,4,.05}]]

Convert height map to a compatible normal map:

normalMap=({{"[◼]", "NormalTexture" }})[heightMap]

Graphics3D[{MaterialShading[<|"SurfaceNormals"->Texture[normalMap]|>],Cuboid[]},Lighting->"Accent",Boxed->False]

Texture Map Parameters

The following parameters support Texture values:

•  BaseColor
•  SpecularColor
•  CoatColor
•  SheenColor
•  EmissionColor
•  MetallicCoefficient
•  RoughnessCoefficient
•  AmbientExposureFraction
•  SurfaceNormals

Combining Texture Map Parameters

Use multiple texture maps to create realistic materials.

Brick Wall

brickMat=MaterialShading[<|
"BaseColor"-> Texture[],
"SurfaceNormals"-> Texture[]
|>]

Graphics3D[{brickMat,Cuboid[]},Lighting->"Neutral",Boxed-> False]

Plot3D[Sin[x^2+y^2],{x,-2,2},{y,-2,2}, ,PlotStyle->brickMat]

Lava

lavaMat=MaterialShading[<|"BaseColor" -> , 
    "SurfaceNormals" -> Texture[], "RoughnessCoefficient" -> 0.6, 
    "EmissionColor" -> Texture[]|>]

Plot3D[Sin[x] Cos[y],{x,0,2 π},{y,0,2 π},Mesh->False,Lighting->"Neutral",PlotRange->{Automatic,Automatic,{-2,2}},PlotStyle->lavaMat,Background->Black,Axes->False,Boxed->False]

Modeling the Earth

Get texture data for the Earth using geo data:

baseColor=GeoImage[GeoRange-> "World",GeoProjection->"Equirectangular",RasterSize-> 1024];
elevations=QuantityMagnitude[GeoElevationData[Entity["City",{"Champaign","Illinois","UnitedStates"}],GeoRange->"World"]];
seaLevel=Rescale[0,MinMax[elevations]];
heightMap=Image[Rescale[elevations]];
roughness=ImageApply[If[#>seaLevel,1,0.4]&,heightMap];
heightMap=ImageApply[If[#>seaLevel,#,seaLevel+0.01Sin[#*10^3]]&,heightMap];
normal=ResourceFunction["NormalTexture"][heightMap,1/6];
emission=ImageResize[Import["https://eoimages.gsfc.nasa.gov/images/imagerecords/55000/55167/earth_lights_lrg.jpg"],1024];

{baseColor,roughness,emission,normal}=ConformImages[{baseColor,roughness,emission,normal},baseColor];

earthMaterial=MaterialShading[<|"BaseColor"-> Texture[baseColor],"RoughnessCoefficient"-> Texture[roughness],"EmissionColor"->{Texture[ emission],0.4},"SurfaceNormals"->Texture[normal],"SpecularColor"-> White|>]

ImageAssemble[{{baseColor,roughness},{emission,normal}}]

Graphics3D[{earthMaterial,Sphere[]},]

Interactive Texture Map Example

Apply texture maps one at a time to see their effect.

Manipulate[
DynamicModule[{baseMap,normalMap,roughnessMap,metallicMap,emissionMap,aoMap},
{baseMap,normalMap,roughnessMap,metallicMap,emissionMap,aoMap}=Texture/@{,,,,,};
Graphics3D[{MaterialShading[<|"BaseColor"->If[base,baseMap,Automatic],"SurfaceNormals"-> If[normal,normalMap,Automatic],"RoughnessCoefficient"-> If[roughness,roughnessMap,Automatic],"MetallicCoefficient"-> If[metallic,metallicMap,Automatic],"EmissionColor"-> If[emission,emissionMap,Automatic],"AmbientExposureFraction"-> If[ao,aoMap,Automatic],"TextureCoordinateScale"->2 {2,1}|>],Sphere[]},Lighting->"Neutral",Boxed->False,SphericalRegion->True,Background->GrayLevel[0],ImagePadding->30,ImageSize->Large,ViewPoint->Front]
],
{{ao,False,"Ambient Exposure"},{True,False}},
{{normal,False,"Normals"},{True,False}},
{{base,False,"Base Color"},{True,False}},
{{emission,False,"Emission"},{True,False}},
{{roughness,False,"Roughness"},{True,False}},
{{metallic,False,"Metallic"},{True,False}},
ControlPlacement->Left
]

PBR Theory

Microfacet Theory

•  Light is made up of perfect rays.
•  Surfaces are made up of tiny facets that act like mirrors.
•  Orientation of these facets controls the appearance of macro-surface.
•  Can model these microfacets using statistical distributions.

Mirror Surface vs Glossy Surface

Reflection and Refraction

When a light ray hits a surface, it splits into a reflected and refracted component.

Reflected Light

Bounces off in the ideal reflection direction. We call this specular reflection (from Latin speculum, meaning mirror).

Refracted Light

Enters the surface and starts interacting with particles in the material.

Some light manages to escape in an effectively random direction. We call this diffuse reflection, as the escaping light rays spread out in all directions.

Modeling as Distributions

Not practical to model all rays and microfacets explicitly, though it’s fun to visualize:

Instead, we model them as distributions. Knowing the sum of these two distributions let’s us know exactly how bright that surface point should be from any viewing direction.

Real World Measurements

Exact distributions can be measured using specialized equipment.

({{}, {Measured BRDF of PVC with an angle of incidence of 55° [1]}})

Impractical to use measured data directly. Instead, create a parametric model capable of approximating a variety of materials.

({{({{, }})}, {Parametric BRDF used by MaterialShading}})

[1] Ngan, A., F. Durando and W. Matusik. Experimental Analysis of BRDF Models. The Eurographics Association (2005).

Bidirectional Reflectance Distribution Function (BRDF)

The total distribution of the reflected light is described by the BRDF.

(Subscript[f, r])(...)==(Subscript[f, s])(...) + (Subscript[f, d])(...)

(Subscript[f, d])==(ρ/π)

(Subscript[f, s])==((D G F)/(4 (n·(Subscript[ω, i])) (n·(Subscript[ω, o]))))  ({{, , }, {"Distribution Term (D)", "Geometry Term (G)", "Fresnel Term (F)"}})

Learn More

MaterialShading Usage:
https://reference.wolfram.com/language/ref/MaterialShading.html

Formulas and More Thorough PBR Explanation:
https://reference.wolfram.com/language/tutorial/PhysicallyBasedRendering.html

Upcoming Talks

Constructive Solid Geometry – By Charles Pooh, 12:00pm-12:30pm