\section{Lighting, Styling, and Filters}
\label{sec:lighting-filters}

The package keeps geometry generation separate from visual styling. Geometry keys
determine what simplices exist; style keys determine how those simplices are drawn
once the visibility pipeline is complete.

\subsection{TikZ styling keys}

Triangles use \verb|fill options|. Curves use \verb|draw options|. Labels use the
literal node body given by \verb|text|. Because the package ultimately emits
ordinary TikZ paths and nodes, these styling strings are plain TikZ option lists.

\begin{Verbatim}
fill options = {fill=ltdtbrightness, draw=black, line join=round}
draw options = {draw=blue!70!black, ultra thick}
\end{Verbatim}

For triangles there is one package-specific convention worth remembering: if you
want lights to affect a face, the fill style must actually reference
\verb|ltdtbrightness|. The renderer computes that color dynamically from the
current lights and the face normal.

\subsection{Directional lights}

Lights are appended by \verb|\appendlight| and supplied as vectors. The package
normalizes those directions and computes a linear brightness factor from the angle
between the light direction and the face normal. Multiple lights are averaged.

\begin{Verbatim}
\appendlight[
  v = {return Vector:new{0.3, -0.2, 1, 1}}
]

\appendlight[
  v = {return Vector:new{-0.5, 0.4, 0.7, 1}}
]
\end{Verbatim}

The falloff is linear in the angle from $0^\circ$ to $90^\circ$, not cosine-based
radiometry. That choice is intentional: it gives predictable illustrative shading
without demanding a physically based material model.

\input{figures/08-lighting-diagram.tex}

\subsection{Filters}

Every geometric append command accepts a \verb|filter| key. The filter is evaluated
after partitioning, so it sees the pieces that will actually participate in the
sort. That makes the filter mechanism more powerful than a simple pre-check on the
original source geometry.

The bound names depend on the simplex type:

\begin{itemize}[leftmargin=2em]
\item point-like and label entries bind \verb|A|;
\item line segments bind \verb|A| and \verb|B|;
\item triangles bind \verb|A|, \verb|B|, and \verb|C|.
\end{itemize}

Typical uses include removing back-facing slices, hiding geometry below a plane,
or discarding pieces outside a region of interest.

\begin{Verbatim}
filter = {
  local normal = (B:hsub(A)):hhypercross(C:hsub(A)):hnormalize()
  return normal[3] > 0
}
\end{Verbatim}

\begin{Verbatim}
filter = {return A[3] >= 0 and B[3] >= 0}
\end{Verbatim}

Because the filter sees the partitioned pieces, it can be used as a clean visual
cutting tool without forcing the user to pre-split the source geometry manually.
When a cut should land exactly on a visible boundary, a practical trick is to
append an auxiliary surface that lies on the intended slicing boundary, let the
partitioner split the target geometry against that surface, and then give the
auxiliary surface \verb|filter = {return false}| so it disappears from the final
render.

\subsection{A style strategy that scales}

For larger figures, it is usually best to settle on a small style vocabulary and
reuse it consistently:

\begin{itemize}[leftmargin=2em]
\item triangles: \verb|fill=ltdtbrightness, draw=...|;
\item curves: \verb|draw=...| through \verb|draw options|;
\item special overlays: embedded surface curves with their own \verb|drawoptions|;
\item annotations: labels without lighting.
\end{itemize}

This keeps the visual language clear and makes it easier to tune the lighting
later without rewriting the geometry descriptions.