3
$\begingroup$

I'm getting a plot which is mostly fine with Lighting->Automatic, but a bit too dark. How do I go about getting the Lighting specification used in the plot so I could make it explicit and tweak it?

IE, need a utility which extracts lighting and related specs from a Graphics3D object.

f1[x_, y_] = 
  x (3/16 (9 - Sqrt[17]) x + 1/8 (9 - Sqrt[17]) y) + 
   y (1/8 (9 - Sqrt[17]) x + 3/4 (9 - Sqrt[17]) y);
f2[x_, y_] = 2 x^2 + 4 y^2;
Plot3D[{f1[x, y], f2[x, y]}, {x, -2, 2}, {y, -2, 2}, 
 BoxRatios -> {1, 1, 1}]

enter image description here

$\endgroup$
5
  • $\begingroup$ Cases[plot, HoldPattern[Lighting -> _], All]? $\endgroup$
    – kglr
    Aug 11, 2021 at 14:00
  • 2
    $\begingroup$ Use SetSystemOptions["VisualizationOptions" -> {"Verbose" -> True}] before plotting, then search for Lightning in the output: Lighting -> {{"Ambient", RGBColor[0.19699838300000003, 0.252204821, 0.33320940200000004]}, {"Directional", RGBColor[0.15473514000000002, 0.21284718000000002, 0.29811516000000005], ImageScaled[{0, 2, 2}]}, {"Directional", RGBColor[0.15473514000000002, 0.21284718000000002, 0.29811516000000005], ImageScaled[{2, 2, 2}]}, {"Directional", RGBColor[0.15473514000000002, 0.21284718000000002, 0.29811516000000005], ImageScaled[{2, 0, 2}]}}. $\endgroup$
    – Domen
    Aug 11, 2021 at 14:00
  • $\begingroup$ @Domen that doesn't fully reproduce the graph above...I guess there are some extra options I need besides Lighting? $\endgroup$ Aug 11, 2021 at 14:08
  • 1
    $\begingroup$ You are correct. To reproduce the original plot, setting the Lighting is not enough, you also have to include the option PlotStyle, which can also be found in the verbose output. $\endgroup$
    – Domen
    Aug 11, 2021 at 14:37
  • 1
    $\begingroup$ Cases[plot, {d__, _GraphicsGroup} :> {d}, All] to get the directives (including Lighting) used for each surface. $\endgroup$
    – kglr
    Aug 11, 2021 at 18:20

1 Answer 1

4
$\begingroup$

Due to this bug, setting Lighting for Graphics3D as an option directly (e.g. via Show) doesn't work, and we must specify it individually for every object (or a group of objects) on the scene like a usual graphics directive. Starting at least from Mathematica 10 the built-in 3D plotting functions like Plot3D take the Lighting specifications from the absolute/resolved value of the PlotStyle option (which they generate from your input), and then build them into the list of graphics primitives (the first argument of Graphics3D). One can turn on verbose logging for this process by setting the system option "VisualizationOptions" -> {"Verbose" -> True}.

We can obtain the default styles with Lighting specifications included, as the value of "DefaultPlotStyle" suboption of Method option, via Charting`ResolvePlotTheme:

defaultplotstyle = "DefaultPlotStyle" /. 
   (Method /. Charting`ResolvePlotTheme[$PlotTheme, Plot3D])

screenshot

We can obtain the actual (absolute) value of PlotStyle (generated by Plot3D for your particular input) from the output generated during evaluation of Plot3D after setting the system option "VisualizationOptions" -> {"Verbose" -> True} as Domen recommends in the comments. The code below automatizes this:

f1[x_, y_] = x (3/16 (9 - Sqrt[17]) x + 1/8 (9 - Sqrt[17]) y) + 
             y (1/8 (9 - Sqrt[17]) x + 3/4 (9 - Sqrt[17]) y);
f2[x_, y_] = 2 x^2 + 4 y^2;

Internal`WithLocalSettings[
  SetSystemOptions["VisualizationOptions" -> {"Verbose" -> True}],
  reap = Reap[Block[{Print = (Sow[{##}] &)},
      Plot3D[{f1[x, y], f2[x, y]}, {x, -2, 2}, {y, -2, 2}, 
       BoxRatios -> {1, 1, 1}]]];,
  SetSystemOptions["VisualizationOptions" -> {"Verbose" -> False}] 
  ];

Cases[reap, HoldPattern[PlotStyle -> _], {1, Infinity}] /. x_Real :> Round[x, .01]
{PlotStyle -> {Directive[Specularity[GrayLevel[1], 3], RGBColor[0.88, 0.61, 0.14], 
    Lighting -> {{"Ambient", RGBColor[0.3, 0.22, 0.09]},
       {"Directional", RGBColor[0.26, 0.18, 0.04], ImageScaled[{0, 2, 2}]}, 
       {"Directional", RGBColor[0.26, 0.18, 0.04], ImageScaled[{2, 2, 2}]}, 
       {"Directional", RGBColor[0.26, 0.18, 0.04], ImageScaled[{2, 0, 2}]}}], 
   Directive[Specularity[GrayLevel[1], 3], RGBColor[0.37, 0.51, 0.71],
     Lighting -> {{"Ambient", RGBColor[0.2, 0.25, 0.33]}, 
       {"Directional", RGBColor[0.15, 0.21, 0.3], ImageScaled[{0, 2, 2}]}, 
       {"Directional", RGBColor[0.15, 0.21, 0.3], ImageScaled[{2, 2, 2}]}, 
       {"Directional", RGBColor[0.15, 0.21, 0.3], ImageScaled[{2, 0, 2}]}}]}}

Having this, you can play with the directives to get the lighting you wish.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.