# How to write graffiti, i.e., text on a polygon surface in Graphics3D?

Is there a relatively easy way to place Text[] on Polygon[] in Graphics3D? For example, I want my text to appear as if written on the light gray "wall" in the attached image, such that it will remain fixed to the wall as the viewpoint is changed.

I would take a look at the Wolfram-U video for Advanced 3D Graphics in the Wolfram Language and download the notebook. Look at slide 22 and the billboard3D function as I will adapt the code to include "graffiti" on the six faces below:

Clear[billboard3D];
billboard3D[s_,
width_, {x_, y_, z_}, {nx_, ny_, nz_}, {hx_, hy_, hz_}] :=
Module[{img = Rasterize[s, "Image", Background -> None], height},
height = width ImageAspectRatio[img];
{
FaceForm[White], EdgeForm[],
Texture[ImageData[img]],
GeometricTransformation[
Polygon[{{-.5 width, .5 height, 0}, {.5 width, .5 height,
0}, {.5 width, -.5 height, 0}, {-.5 width, -.5 height, 0}},
VertexTextureCoordinates -> {{0, 1}, {1, 1}, {1, 0}, {0, 0}}],
Quiet@
Composition[TranslationTransform[{x, y, z}],
RotationTransform[{{0, 1, 0}, {hx, hy, hz}}],
RotationTransform[{{0, 0, 1}, {nx, ny, nz}}]]]
}
];

Framed[
Graphics3D[{

(* Add a Plot3D Object *)
Plot3D[
0.9 Exp[-9 ((x - 1/2)^2 + (y - 1/2)^2)], {x, 0, 1}, {y, 0, 1},
PlotRange -> {0, 2}, ColorFunction -> "TemperatureMap",
PlotStyle -> Directive[Opacity[0.5], Red]][[1]],
(* View frustum *)
FaceForm[], EdgeForm[GrayLevel[.25]], Cuboid[],

(* Camera *)
FaceForm[GrayLevel[.25]], EdgeForm[], Specularity[White, 30],
Cuboid[{.45, -1, .4}, {.55, -1.3, .6}],
Cylinder[{{.475, -1.1, .65}, {.525, -1.1, .65}}, .05],
Cylinder[{{.475, -1.2, .65}, {.525, -1.2, .65}}, .05],
Cylinder[{{.5, -1, .5}, {.5, -.9, .5}}, .05],
Cylinder[{{.5, -1.15, .5}, {.5, -.9, 0}}, .01],
Cylinder[{{.5, -1.15, .5}, {.35, -1.3, 0}}, .01],
Cylinder[{{.5, -1.15, .5}, {.65, -1.3, 0}}, .01],
billboard3D[
Style["ViewPoint", 24, Bold,
FontFamily -> "Courier"], .4, {.5, -1.15, .8}, {1, 0, 0}, {0, 0,
1}],

(* View span *)
GrayLevel[.25],
With[{p = {.5, -.9, .5}},
Line[{{p, {0, 0, 0}}, {p, {1, 0, 0}}, {p, {0, 0, 1}}, {p, {1, 0,
1}}}]],

(* View angle *)
Gray, Dashed,
With[{p = {.5, -.9, .5}}, Line[{{p, {.5, 0, 1}, {.5, 0, 0}, p}}]],
Arrow[BezierCurve[{{.5, -.5,
0.28}, {.5, -.4, .5}, {.5, -.5, .72}}]],
billboard3D[
Style["ViewAngle", 24, Bold,
FontFamily -> "Courier"], .3, {.5, -.4, .45}, {1, 0, 0}, {0, 0,
1}],

(* View vertical *)
billboard3D[
Style["ViewVertical", 24, Bold,
FontFamily -> "Courier"], .35, {.5, -.05, .75}, {1, 0,
0}, {0, -1, 0}],

(* View center *)
PointSize[Large], Point[{{.5, .5, .5}, {.5, 0, .5}}],
Arrowheads[.015], Arrow[{{.5, .5, .5}, {.5, 0, .5}}],
billboard3D[
Style["ViewCenter", 24, Bold,
FontFamily -> "Courier"], .25, {.5, .25, .55}, {1, 0, 0}, {0, 0,
1}],

(* View range *)
Gray,
Line[{{{1, 0, 0}, {1, 0, -.1}}, {{1, 1, 0}, {1, 1, -.1}}}],
Arrowheads[{-.02, .02}], Arrow[{{1, 0, -0.05}, {1, 1, -.05}}],
billboard3D[
Style["ViewRange", 24, Bold,
FontFamily -> "Courier"], .4, {1.075, .5, -.1}, {1, 0, 0}, {0, 0,
1}],

(* View left wall *)
billboard3D[
Style["Left Wall", 24, Bold, FontFamily -> "Courier"], .35, {0,
0.5, .5}, {1, 0, 0}, {0, 0, 1}],

(* View right wall *)
billboard3D[
Style["Right Wall", 24, Bold, FontFamily -> "Courier"], .35, {1,
0.5, .5}, {1, 0, 0}, {0, 0, 1}],

(* View top wall *)
billboard3D[
Style["Top Wall", 24, Bold, FontFamily -> "Courier"], .35, {0.5,
0.5, 1}, {0, 0, 1}, {0, 1, 0}],

(* View bottom wall *)
billboard3D[
Style["Bottom Wall", 24, Bold,
FontFamily -> "Courier"], .35, {0.5, 0.5, 0}, {0, 0, 1}, {0, 1,
0}],

(* View front wall *)
billboard3D[
Style["Front Wall", 24, Bold, FontFamily -> "Courier"], .35, {0.5,
0, 0.5}, {0, 0, 1}, {0, 0, 1}],

(* View back wall *)
billboard3D[
Style["Back Wall", 24, Bold, FontFamily -> "Courier"], .35, {0.5,
1, 0.5}, {0, 0, 1}, {0, 0, 1}]

},
Boxed -> False, ImageSize -> 750, Lighting -> "Neutral",
ViewPoint -> {5, -2, 1.5}
],
FrameMargins -> 20, FrameStyle -> GrayLevel[.75]]


• I will have to study this later, but it clearly answers my question satisfactorily. One observation I will make regarding the use of Clear[]. I have taken to enclosing everything in an outer Module[] and placing everything I would Clear[] in the variable declaration list of the Module[{variable declaration}]. It's a long story, but it seems to keep things cleaner. Aug 19, 2020 at 11:26