ABSRACT (original paper): Illumination of scenes is usually generated in computer graphics using polygonal meshes. In this paper, we present a geometric method using projections. Starting from an implicit polynomial equation of a surface in 3-D or a curve in 2-D, we provide a semi-algebraic representation of each part of the construction. To solve polynomial condition systems and find constrained regions, we apply algebraic computational algorithms for computing the Gröbner basis and cylindrical algebraic decomposition. The final selection of illuminated and self-shaded components for polynomial surfaces of a degree higher than three is discussed. The text is accompanied by visualizations of illumination of surfaces up to degree eight. CITATION (original paper): Zamboj, M., & Řada, J. (2024). Geometric Illumination of Implicit Algebraic Surfaces. In Takenouchi K. (ed.) ICGG 2024 - Proceedings of the 21st International Conference on Geometry and Graphics. ICGG 2024. Lecture Notes on Data Engineering and Communications Technologies (in press). arXiv preprint https://doi.org/10.48550/arXiv.2403.19679.
The aim of this post is to present a geometric method to create shades and shadows of implicit surfaces. The results show only hard shadow, no shading.
Setting the scene
Setting the scene
Let us have a surface represented by its polynomial and a point light source . The point lighting is omitted in the graphics below.
L
In[]:=
poly=x^2+y^2+2z^3(-z^2+1/2);(*surfaceform*)l={1,0,-2};(*pointlightsource*)mr=2;(*forMaxRecursion*)plotpoints=100;(*forPlotPoints*)viewpoint={-1,-2,-1};(*forViewPoint*)boundary=Ball[{0,0,0},3](*totalplotboundary*);cppoly=ContourPlot3D[{poly==0},{x,y,z}∈boundary,ContourStyle->Directive[{White,Opacity[1],Specularity[.1]}],Mesh->None,BoundaryStyle->None,RegionBoundaryStyleNone,PlotPoints->plotpoints,MaxRecursion->mr,ImageSize->600,Background->Black,Axes->None,Boxed->False,ViewPoint->viewpoint,ViewAngle->Pi/8,Lighting->"Neutral"];Show[{cppoly,Graphics3D[{Orange,PointSize[.01],Point[l]}]}]
Out[]=
Below is default point lighting in Mathematica. Something missing, isn’t it?
In[]:=
Show[{ContourPlot3D[{poly==0},{x,y,z}∈boundary,ContourStyle->Directive[{White,Opacity[1],Specularity[.1]}],Mesh->None,BoundaryStyle->None,RegionBoundaryStyleNone,PlotPoints->plotpoints,MaxRecursion->mr,ImageSize->600,Background->Black,Axes->None,Boxed->False,ViewPoint->viewpoint,ViewAngle->Pi/8,LightingPointLight[White,l]],Graphics3D[{Orange,PointSize[.01],Point[l]}]}]
Out[]=
Tangent cones
Tangent cones
First, we construct the first polar to the surface poly from the point light source . We switch to homogeneous coordinates in the form . The homogeneous forms are denoted by overline . The polynomial of the first polar wrt. the given point is given by the gradient of the polynomial of the surface . In homogeneous coordinates: ∇.
σ
L
(,,,)
x
1
x
2
x
3
x
0
L(,,)(,,,)
l
x
l
y
l
z
L
l
1
l
2
l
3
l
0
σ
P
L
σ
σ
P
T
P
σ
In[]:=
polarform[poly_]:=Grad[ResourceFunction["PolynomialHomogenize"][poly//.{x->x1,y->x2,z->x3},{x1,x2,x3,x4},x0],{x1,x2,x3,x0}](*gradientinhomogeneouscoordinates*)hompolar[poly_,point_]:=polarform[poly].Append[point,1](*adding1onlyforfinitepointsinhomogeneouscoordinates*)dehom[hompoly_]:=hompoly//.{x1x,x2y,x3z,x01}(*usedinthenextfunction*)polar[poly_,point_]:=dehom[hompolar[poly,point]](*obtainthepolynomialofthepolarincartesiannonhomogeneousform*)
The first polar of our surface wrt. the point light source is shown below (green).
In[]:=
cppoly2=ContourPlot3D[{poly==0,polar[poly,l]==0},{x,y,z}∈boundary,ContourStyle->{Directive[{White,Opacity[1],Specularity[.1]}],Directive[{Green,Opacity[.3],Specularity[.1]}]},Mesh->None,BoundaryStyle->None,RegionBoundaryStyleNone,PlotPoints->plotpoints,MaxRecursion->mr,ImageSize->600,Background->Black,Axes->None,Boxed->False,ViewPoint->viewpoint,ViewAngle->Pi/8,Lighting->"Neutral"];Show[{cppoly2,Graphics3D[{Orange,PointSize[.01],Point[l]}]}]
Out[]=
The intersection of the surface and its first polar is the set of tangent points of tangents through (and singular points). The set of these tangent points is the boundary of the self-shade called a terminator i.e. it is a curve that separates the illuminated and shaded parts of the surface. The parts of the surface separated by the first polar are automatically in shade (see below). The visualization also highlights the terminator curve (green). The parts below do not have to be performed in the computation.
L
In[]:=
regpollight=ImplicitRegion[polar[poly,l]>0,{x,y,z}];(*separatingtheilluminatedpartwrt.thepolarsurface*)cppolarlight=ContourPlot3D{poly0},{x,y,z}∈boundary,;regpolshade=ImplicitRegion[polar[poly,l]<0,{x,y,z}];(*separatingtheshadedpartwrt.thepolarsurface*)cppolarshade=ContourPlot3D{poly0},{x,y,z}∈boundary,;Show[{cppolarlight,cppolarshade,Graphics3D[{Orange,PointSize[.01],Point[l]}]}]
Computing the Gröbner basis of the system
In this case, the tangent cone has the polynomial of degree 10. Plotting becomes a little more demanding and the visualization of the cone around the vertex is usually deformed, so we modified the plot region to omit the vertex neighbourhood. We do not necessarily need to visualize the cone, however it is illustrative.
Selection of self-shaded parts
Selection of self-shaded parts
From the picture above, we can see the part which is self-shaded by the surface. With the implicit representations we can use the cylindrical decomposition algorithm to decompose the surface to parts separated by the tangent cone. So, the conditions below give us the regions on the surface, separated by the first polar (illuminated part), and not on the tangent cone.
The table below shows the information about the algorithm results. The columns represent regions and the rows represent the rays. The position including the note: “min" are the closest parts for the given ray. “not” means that the ray has no intersection with this region. “dump” means that the region is already shaded by some other region.
See the output here: https://www.wolframcloud.com/obj/879b8352-03c2-4d3b-babe-d772c3930cd5
Now, the parts of the surface are sorted. We have two lists of indexes with positions in the list from the cylindrical decomposition.
Visualizing self-shaded regions
Visualizing self-shaded regions
The cylindrical decomposition represents the regions by many constraints. Therefore the standard functions such as ContourPlot3D with RegionFunction and ImplicitRegion collapse. To bypass this, we create the mesh using FindInstance (sorry for this).
The final visualization
The final visualization
For variations with more surfaces, we can multiply their polynomial forms and use the procedure above. We can also conveniently use some information about the positions of surfaces with respect to the light source. See the original paper for more information.
CITE THIS NOTEBOOK
CITE THIS NOTEBOOK
Geometric illumination of implicit algebraic surfaces
by Michal Zamboj, Jakub Řada
Wolfram Community, STAFF PICKS, September 25, 2024
https://community.wolfram.com/groups/-/m/t/3283344
by Michal Zamboj, Jakub Řada
Wolfram Community, STAFF PICKS, September 25, 2024
https://community.wolfram.com/groups/-/m/t/3283344