What is New in Mathematica 3D Graphics

Yuzhu Lu, Wolfram Research, Inc.

Join the Conversation #WolframTechConf

Overview of 3D Graphics:

Primitives, Directives, Options

Rendering Engines

ColorBuffer/DepthBuffer

ColorFormat

Some New Features in Progress:

FastRendering

Mipmap

Lighting on Volume Rendering

Primitives

Point . Line . Polygon . GraphicsComplex . Arrow . BezierCurve . BSplineCurve . Cone . Cylinder . Cuboid . Sphere . GeometricTransformation . Text . Prism . Pyramid . Raster3D . Tetrahedron . Tube . BSplineSurface . Hexahedron . Raster3D . 
HalfLine . InfinityLine . HalfPlane . InfinityPlane . ConicHullRegion . Inset. 
Ball . Circumsphere . Simplex . Ellipsoid . Parallelepiped . Triangle . SSSTriangle . SASTriangle . ASATriangle . AASTriangle . Parallelogram

Directives

PointSize . Thickness . Dashed . Dotted . Dashing . FaceForm . EdgeForm . Texture . AbsolutePointSize . AbsoluteThickness . AbsoluteDashing . Specularity . Glow . Arrowheads . CapForm . JoinForm . Opacity . Named Color . RGBColor . CMYKColor . Hue . GrayLevel . LABColor . LCHColor . LUVColor . XYZColor .

Options

Background . Lighting . VertexColors . VertexNormals . ViewPoint . ViewVertical . ViewCenter . ViewAngle . ViewVector . ViewRange . ViewMatrix . SphericalRegion . RotateAction . PlotRange . PlotRangePadding . ImageSize  . Boxed . AspectRatio . BoxRatio . BoxStyle . Axes . AxesEdge . AxesLabel . AxesStyle . AxesOrigin . FrameStyle . GridLinesStyle . TickStyle . LabelStyle . FaceGrid . FaceGridStyle . Epilog . Prolog . PlotLabel . Method . ColorFunction . ImagePadding . ImageSizeRaw . ClipRange . VertexTextureCoordinates . VertexDataCoordinates . BaseStyle . Alignment . ClipPlanes . ClipPlanesStyle

Overview of 3D Graphics

Graphics3DRenderingEngine

1. HardwareDepthBuffer: Rendered with hardware depth buffer
2. HardwareDepthPeeling: Rendered with hardware depth peeling method
3. BSPTree: Sorted with BSP Tree before rendering 
4. Software: Projected and rendered as 2D graphics
5. Automatic: HardwareDepthBuffer + HardwareDepthPeeling (Default)

Graphics3D[ ..., BaseStyle->{ RenderingOptions->{ “Graphics3DRenderingEngine”->”BSPTree” } } ]

For this example:

a=ParametricPlot3D[{u Cos[v],u Sin[v],Im[(u Exp[I v]^5)^(1/5)]},{u,0,2},{v,0,2Pi},ExclusionsStyle->{Opacity[0.5],Directive[Thick,Blue]},PlotStyle->Texture[]];
b=Graphics3D[{Yellow,Polygon[{{-3,-3,-0.5},{-3,3,-0.5},{3,3,-0.5},{3,-3,-0.5}}],Green,Opacity[1],Cuboid[{-2,-2,-2},{2,2,-0.5}],White,Table[With[{p={i,j,k}*.2-0.5},{Opacity[.5],Sphere[p, .1]}],{i,5},{j,5},{k,5}]}];
Show[{a,b}]

Grid[{{,HardwareDepthBuffer,HardwareDepthPeeling,Bsp Tree,Software},{"Depth Computing","Depth Buffer","Depth Buffer", "BSP Tree Sorting", "BSP Tree Sorting"},{"Project 3D into 2D","No","No", "No", "Yes"},{"Rendering Layer","OpenGL/Direct3D", "OpenGL/Direct3D", "OpenGL/Direct3D", "2D Layer/3D Layer"},{"Performace","Fast","Fast","Slow","Even Slower"},{"Memory Usage","Small(40M)", "Small(40M)","Huge(480M)","Huge(480M)"},{"Transparency Support","False", "True","True","True"},{"Availablity","True", "Hardware/Driver Dpendent","True","True"},{"Possible Artifacts","Z Fighting", "Z Fighting","Mesh Lines Look Dashed, Occasional Stitching Issues","Mesh Lines Look Dashed, Occasional Stitching Issues, Some Features not Supported(Texture)"},{,,,,}},Frame->All,ItemStyle->{Automatic,Automatic,{{{1,1},{1,5}}->{Bold,16,RGBColor[0,0,0.8]},{{1,9},{1,1}}->{Bold,16,RGBColor[0,0,0.8]}}}]

Depth Peeling Availability

If[$OperatingSystem==="Windows","Optimized 3D Transparency"/.("DirectX"/.SystemInformation["Devices","GraphicsDevices"]),"Optimized 3D Transparency"/.("OnScreen"/.("OpenGL"/.SystemInformation["Devices","GraphicsDevices"]))]

What is Z fighting

Z fighting is caused by the  z value computing error from coplanar polygons and buffer precision

Graphics3D[{Blue,Cylinder[],Red,Sphere[{0,0,2}],Black,Thick,Dashed,Line[{{-2,0,2},{2,0,2},{0,0,4},{-2,0,2}}],Yellow,Polygon[{{-3,-3,-2},{-3,3,-2},{3,3,-2},{3,-3,-2}}],Green,Opacity[.3],Cuboid[{-2,-2,-2},{2,2,-1}]}]

Solution to Z fighting

Small offset to avoid coplanar polygons or nearly coplanar polygons

Graphics3D[{Blue,Cylinder[],Red,Sphere[{0,0,2}],Black,Thick,Dashed,Line[{{-2,0,2},{2,0,2},{0,0,4},{-2,0,2}}],Yellow,Polygon[{{-3,-3,-2},{-3,3,-2},{3,3,-2},{3,-3,-2}}],Green,Opacity[.3],Cuboid[{-2,-2,-2.001},{2,2,-1.001}]}]

Overview of 3D Graphics

ColorBuffer/DepthBuffer

1. Color: contains color value for each pixel rendered
2. Depth: contains depth value computed for each pixel rendered

Graphics3D[ ..., Method->{ “OneLayer”->{ “Depth”, 1 } } ]

Table[Graphics3D[{Blue,Cylinder[],Red,Sphere[{0,0,2}],Black,Thick,Dashed,Line[{{-2,0,2},{2,0,2},{0,0,4},{-2,0,2}}],Yellow,Polygon[{{-3,-3,-2},{-3,3,-2},{3,3,-2},{3,-3,-2}}],Green,Cuboid[{-2,-2,-2.001},{2,2,-1.001}]},Boxed->False,Method->{"OneLayer"->{a,1}}],{a,{"Color","Depth"}}]

A stack of color/depth buffers:

Graphics3D[{Text[Style[Camera,Bold,16],{2.6,-4.8,6}],Arrow[{{2.4,-4.4,5.4},{0.56,-0.96,1.2}}],Blue,Cylinder[],Red,Sphere[{0,0,2}],Black,Thick,Dashed,Line[{{-2,0,2},{2,0,2},{0,0,4},{-2,0,2}}],Yellow,Polygon[{{-3,-3,-2},{-3,3,-2},{3,3,-2},{3,-3,-2}}],Green,Cuboid[{-2,-2,-2.001},{2,2,-1.001}]},Boxed->False,ViewPoint->{100,0,0}]

Table[Table[Graphics3D[{Blue,Cylinder[],Red,Sphere[{0,0,2}],Black,Thick,Dashed,Line[{{-2,0,2},{2,0,2},{0,0,4},{-2,0,2}}],Yellow,Polygon[{{-3,-3,-2},{-3,3,-2},{3,3,-2},{3,-3,-2}}],Green,Cuboid[{-2,-2,-2.001},{2,2,-1.001}]},Boxed->False,Method->{"OneLayer"->{a,b}},PlotLabel->StringJoin[{"Layer ",ToString[b]}]],{a,{"Color","Depth"}}],{b,{1,2,3,4,5,6}}]

Overview of 3D Graphics

ColorFormat Option: the precision of ColorBuffer

UnsignedInteger8: 8 bit per channel per pixel
UnsignedInteger16: 16 bit per channel per pixel
Float16: 16 bit per channel per pixel
Float32: 32 bit per channel per pixel

Graphics3D[ ..., Method->{ “ColorFormat”->”Real32” } ]

Graphics3D[{Raster3D[RawArray["Byte",Import["ExampleData/CTengine.tiff","Data"]],{{-1,-1,-1},{1,1,1}},{0,255},ColorFunction->(GrayLevel[#1,1/512.+(511. #1)/512.]&)],Opacity[1],Point[{0.5,.5,0.5}]},Method->{"ColorFormat"->#}]&/@{"UnsignedInteger8","UnsignedInteger16","Real16","Real32"}

Graphics3D[Raster3D[CrossMatrix[{64,64,64}], ColorFunction-> (GrayLevel[#1,(1/256.)+((255. #1)/256.)]&)],Method->{"ColorFormat"->#}]&/@{"UnsignedInteger8","UnsignedInteger16","Real16","Real32"}

Some New Features in Progress

FastRendering Option: Optimize the performance of static data

Performace Improvement: reuse the data on the hardware

Graphics3D[ ..., Method->{ ”FastRendering”->True } ]

Half million polygons:

100 thousand polygons:

ParametricPlot3D[{Cos[2 t],Sin[2 t],Cos[t]},{t,0,2 Pi},PlotStyle->Directive[CapForm[None],JoinForm["Miter"],Red],PlotRange->All,ColorFunction->Hue,Boxed->False,MaxRecursion->0,PlotPoints->300,Axes->None,Method->{"TubePoints"->300,"FastRendering"->False}]/.Line[pts_,rest___]:>Tube[pts,0.2,rest]

ParametricPlot3D[{Cos[2 t],Sin[2 t],Cos[t]},{t,0,2 Pi},PlotStyle->Directive[CapForm[None],JoinForm["Miter"],Red],PlotRange->All,ColorFunction->Hue,Boxed->False,MaxRecursion->0,PlotPoints->300,Axes->None,Method->{"TubePoints"->300,"FastRendering"->True}]/.Line[pts_,rest___]:>Tube[pts,0.2,rest]

Some New Features in Progress

Mipmap: Solve the aliasing artifacts with a very large Texture

Why the aliasing artifacts happens: the texture is huge, but the mapped target area is small, i.e. mapping multiple pixels to one pixel

How mipmap works: automatically generate a set of downsized duplicates of the main texture, use the right image based on the view point

Some New Features in Progress

VolumeLighting: Lighting on Raster3D isn’t easy, because there is no polygons and no normals

VolumeLighting is a Method Option of Raster3D: the following values can be used

Raster3D[ ..., Method->{ ”VolumeLighting”->”EnhancedEdge” } ]

Table[Graphics3D[{Specularity[White,6],Raster3D[RawArray["Byte",Import["ExampleData/CThead.tiff","Data"]],{{-1,-1,-1},{1,1,1}},{0,255},ColorFunction->"GrayLevelOpacity",Method->{"VolumeLighting"->t,"InterpolateValues"->True}]},Lighting->{{"Directional",White,ImageScaled[{0,0,2}]}},ViewPoint->{-3.2,0.89,-0.34},ImageSize->300,PlotLabel->t],{t,{False,True,"EnhancedEdge"}}]

Combine Lighting and ColorFunction:

Table[Graphics3D[{Specularity[White,30],Raster3D[RawArray["Byte",Import["ExampleData/CThead.tiff","Data"]],{{-1,-1,-1},{1,1,1}},{0,255},ColorFunction->(Blend[{{0, RGBColor[0.035,0.058,0,0]},{0.1, RGBColor[0.015,0,0.035,0]},{0.2, RGBColor[0,0,0,0.032]},{0.3, RGBColor[0.103,0.032,0,0]},{0.4, RGBColor[0,0,0,0]},{0.5, RGBColor[0.202,0.203,0.218,0.337]},{0.6, RGBColor[0.9,0.9,0.9,0.457]},{0.7, RGBColor[0.98,0.97,1,0.682]},{0.8, RGBColor[1,1,1,0.794]},{0.9, RGBColor[0.95,0.97,0.95,0.842]},{1, RGBColor[1,1,1,0.962]}}, #] &),Method->{ "VolumeLighting"->t,"InterpolateValues"->True}]},ViewPoint->{-3.2,0.89,-0.34},Lighting->{{"Directional",White,ImageScaled[{0,0,2}]}},ImageSize->300,PlotLabel->t],{t,{False,True,"EnhancedEdge"}}]

Any Lighting specification will work with Raster3D:

Table[Graphics3D[{Specularity[White,6],Raster3D[RawArray["Byte",Import["ExampleData/CThead.tiff","Data"]],{{-1,-1,-1},{1,1,1}},{0,255},ColorFunction->"GrayLevelOpacity",Method->{"VolumeLighting"->t,"InterpolateValues"->True}]},Lighting->{{"Spot",RGBColor[{0.882,0.627,0.506}],{{-1,1,0},{0,0,0}},Pi/6,{0,1,0}}},ViewPoint->{-3.2,0.89,-0.34},ImageSize->300,PlotLabel->t],{t,{True,"EnhancedEdge"}}]

Different Point light instruments at the corner points:

lights={PointSize[Large],Yellow,Point[Tuples[{-1,1},3]]};
lighting=({"Point",Hue[RandomReal[]],#}&/@Tuples[{-1,1},3]);

Table[Graphics3D[{lights,Specularity[White,6],Raster3D[RawArray["Byte",Import["ExampleData/CThead.tiff","Data"]],{{-1,-1,-1},{1,1,1}},{0,255},ColorFunction->"GrayLevelOpacity",Method->{"VolumeLighting"->t,"InterpolateValues"->True}]},Lighting->lighting,ViewPoint->{-3.2,0.89,-0.34},ImageSize->300,PlotLabel->t],{t,{True,"EnhancedEdge"}}]