22
$\begingroup$

I would like to color some objects in metallic shades like gold and silver. Various web sources suggest that the gold is a variant of yellow with RGB values 83.14% red, 68.63% green, and 21.57% blue. Similarly, silver is claimed to be a variant of grey with 75.3% of each red, green, and blue. However, when I try to color disks with these values, the representation is more dull-yellow and flat-grey than metallic silver or gold:

gold = RGBColor[0.8314, 0.6863, 0.2157];
silver = RGBColor[0.753, 0.753, 0.753]; 
Graphics[{gold, Disk[{0, 0}, 0.5], silver, Disk[{1, 0}, 0.5]}]

enter image description here

How can I get the colors to glitter like gold and sparkle like silver?

$\endgroup$
2

3 Answers 3

45
$\begingroup$

Here is a possible approach using MaterialShading new in version 12.3.

It is easier to get nice results on curved surfaces like a sphere without too much input. To get a flat surface to give the results you want may require you to play with the material shade and parameters.

We will modify the example from the documentation to give an interesting result by modifying the "SurfaceNormals" and "MetallicCoefficient"to give a textured surface with variable reflection properties.

Surface normals

SurfaceNormals

Metallic coefficient

MetallicCoefficient

We need to work in 3D for the lighting to work so your disk becomes a cylinder.

sn = Import["https://i.sstatic.net/Bfcrl.png"];
mc = Import["https://i.sstatic.net/DF9Fs.png"];
Graphics3D[{MaterialShading[<|"BaseColor" -> {Hue[0.125, 1, 1], 1}, 
        "SurfaceNormals" -> Texture[sn], 
    "RoughnessCoefficient" -> 0.65,
         "MetallicCoefficient" -> Texture[mc] |>], Cylinder[]}, 
  Lighting -> "ThreePoint", Boxed -> False, ViewPoint -> Top]

Gold disk image

Something fancier

I found this tutorial and how to create a surface normal map for a coin.

Surface normals for a coin

Coin

We can use the same technique from above to create a gold and silver coin.

sn = Import["https://i.sstatic.net/DhDI7.png"];
mc = Import["https://i.sstatic.net/DF9Fs.png"];
Graphics3D[{MaterialShading[<|"BaseColor" -> {Hue[0.125, 1, 1], 1}, 
        "SurfaceNormals" -> Texture[sn], 
    "RoughnessCoefficient" -> 0.65,
         "MetallicCoefficient" -> Texture[mc] , 
    "SpecularAnisotropyCoefficient" -> {0.3, 0}|>], Cylinder[]}, 
  Lighting -> "ThreePoint", Boxed -> False, ViewPoint -> Top]
Graphics3D[{MaterialShading[<|"BaseColor" -> {GrayLevel[1], 1}, 
        "SurfaceNormals" -> Texture[sn], 
    "RoughnessCoefficient" -> 0.65,
         "MetallicCoefficient" -> Texture[mc] , 
    "SpecularAnisotropyCoefficient" -> {0.3, 0}|>], Cylinder[]}, 
  Lighting -> "ThreePoint", Boxed -> False, ViewPoint -> Top]

Gold and silver coin

$\endgroup$
1
  • $\begingroup$ I clicked out of curiosity and I have to say that this is a beautiful presentation of what one could do in mathematica. well done. $\endgroup$
    – alex
    Commented Oct 9, 2021 at 14:56
22
$\begingroup$

You could build up your own procedural texture from random stripy patterns, specks from a power-law distribution and a linear gradient:


SeedRandom[1];
d = 1024;
gold = RGBColor[0.8314, 0.6863, 0.2157];

stripes = GaussianFilter[ImageResize[
  RandomImage[{1, 1.2}, {1, d}], {d, d}], 3];

specks = ImageAdjust@GaussianFilter[
  Image@RandomVariate[ParetoDistribution[0.01, 5.0], {d, d}], 3];

gradient = LinearGradientImage[{Gray, White, Gray}, {d, d}];

goldtexture = ImageAdjust[
  ImageAdd[
     ImageMultiply[
      gradient,
      Image[ConstantArray[gold, {d, d}]], 
      stripes],
    specks]
 , 0.25];

Graphics[{
  SurfaceAppearance["TextureShading", Texture[goldtexture]], Disk[]
}]

gold texture

$\endgroup$
1
  • $\begingroup$ Tim Laska's answer, which requires working in 3D is probably the "right" way to do this, but your answer is very useful because it can be applied to 2D graphics. So while I ended up accepting Tim's answer, this is the one I ended up using so that I didn't have to redo all the already coded graphics. Thanks! $\endgroup$
    – bill s
    Commented Jun 21, 2021 at 11:41
7
$\begingroup$

I wonder if one could do a pretty simple workaround for the limits of applying a Texture to Disk.

Maybe something as simple as:

Graphics3D[{
  Darker[gold],
  Glow[Darker[gold]],
  Sphere[]},
 Boxed -> False]

You could then fool around with other Graphics3D properties like Lighting, or Opacity.

enter image description here

Or...

enter image description here

ParametricPlot3D[
 0.99 {Cos[u] Sin[v], Sin[u] Sin[v], Cos[v]}, {u, 0, 2 \[Pi]}, {v, 
  0, \[Pi]},
 Mesh -> None,
 TextureCoordinateFunction -> ({#4, 1 - #5} &),
 PlotStyle -> Directive[
   Specularity[gold, 500],
   Texture[texture]],
 Lighting -> "Neutral",
 Axes -> False,
 Boxed -> False]

enter image description here

$\endgroup$
1
  • $\begingroup$ Your last picture looks more like the basis of a wooden ball or a simple planet than like gold to me. $\endgroup$
    – Mast
    Commented Jun 19, 2021 at 8:39

Your Answer

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

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