I know that the question was asked two years ago, but maybe another point of view could still be useful.
I try to mimic a ray-tracer to obtain the shading of the torus. The main elements in the code below are the two unitary vectors pointing towards the observer, I'll call it w, and towards the light source, s. (The sun position suggested by the image is not quite correct due to a certain reflection angle for the highlights, but this is not so important.)
The torus ("centered" at the origin of the coordinate system) is constructed using a quadrilateral mesh; the points of the mesh are given by a classical parametrization. The inner product of w with a point (more precisely, with its position vector) of the mesh decides if the point is visible. For a visible quadrilateral, the inner product of s with one of its vertices controls the color of the quadrilateral which eventually yields the shading.
Note that we need the three components of 3D points and vectors for various computations and we cannot recuperate them from a TikZ \path coordinate command.

\documentclass[margin=10pt]{standalone}
\usepackage{ifthen}
\usepackage[rgb]{xcolor}
\usepackage{tikz}
\usetikzlibrary{cd, arrows, matrix, intersections, math, calc}
\xdefinecolor{O}{RGB}{255, 102, 17}
\xdefinecolor{B}{RGB}{17, 87, 221}
\begin{document}
\tikzmath{%
real \slongit, \slatit, \sunx, \suny, \sunz; % towards the light source
real \ry, \rz, \longit, \latit, \tox, \toy, \toz;
real \newxx, \newxy, \newyx, \newyy, \newzx, \newzy;
integer \Ny, \Nz, \prevj, \prevk, \aj, \ak;
\slongit = -60; \slatit = 45;
\sunx = sin(\slongit)*cos(\slatit);
\suny = sin(\slatit);
\sunz = cos(\slongit)*cos(\slatit);
% j moves around Oy and k moves around Oz.
% They describe full circles of radii \ry and \rz respectively.
\ry = 4;
\rz = 1.5;
\longit = 25;
\latit = 35;
\tox = sin(\longit)*cos(\latit);
\toy = sin(\latit);
\toz = cos(\longit)*cos(\latit);
\newxx = cos(\longit); \newxy = -sin(\longit)*sin(\latit);
\newyy = cos(\latit);
\newzx = -sin(\longit); \newzy = -cos(\longit)*sin(\latit);
\Nz = 36; % 60;
\Ny = 84; % 120;
\ktmp = \Nz-1;
\jtmp = \Ny-1;
\aj = 10;
\ak = 0;
function isSeen(\j, \k) {
let \px = cos(360*(\k/\Nz))*cos(360*(\j/\Ny));
let \py = -sin(360*(\k/\Nz));
let \pz = cos(360*(\k/\Nz))*sin(360*(\j/\Ny));
let \res = \px*\tox + \py*\toy + \pz*\toz;
if \res>0 then {return 1;} else {return 0;};
};
function inLight(\j, \k) {%
let \px = cos(360*(\k/\Nz))*cos(360*(\j/\Ny));
let \py = -sin(360*(\k/\Nz));
let \pz = cos(360*(\k/\Nz))*sin(360*(\j/\Ny));
return {\px*\sunx + \py*\suny + \pz*\sunz};
};
}
\begin{tikzpicture}[every node/.style={scale=.8},
z={(\newzx cm, \newzy cm)},
x={(\newxx cm, \newxy cm)},
y={(0 cm, \newyy cm)},
evaluate={%
int \j, \k;
real \tmp;
for \j in {0, 1, ..., \Ny}{%
for \k in {0, 1, ..., \Nz}{%
\test{\j,\k} = isSeen(\j, \k);
if \test{\j,\k}>0 then {%
\tmp{\j,\k} = int(100*inLight(\j,\k)));
if \tmp{\j,\k}>0 then {%
\tmpW{\j,\k}=int(100*inLight(\j,\k)^2);
}
else {%
\tmpK{\j,\k}=-int(100*inLight(\j,\k));
};
} else {};
};
};
}]
% coordinate system $Oxyz$; first layer
\draw[green!50!black]
(0, 0, 0) -- (\ry, 0, 0)
(0, 0, 0) -- (0, 0, \ry);
% points (P-\j-\k)
\foreach \j in {0, ..., \Ny}{%
\foreach \k in {0, ..., \Nz}{%
\path
( {( \ry+\rz*cos(360*(\k/\Nz)) )*cos(360*(\j/\Ny))},
{-\rz*sin(360*(\k/\Nz))},
{( \ry+\rz*cos(360*(\k/\Nz)) )*sin(360*(\j/\Ny))} )
coordinate (P-\j-\k);
}
}
% "squares"---the mesh
\foreach \k [remember=\k as \prevk (initially 0)] in {1, ..., \Nz}{%
\foreach \j [remember=\j as \prevj (initially 0)] in {1, ..., \Ny}{%
\ifthenelse{\test{\j,\k}=1}{
\ifthenelse{\tmp{\j,\k}>0}{
\filldraw[white!\tmpW{\j,\k}!B]
(P-\j-\prevk) -- (P-\prevj-\prevk)
-- (P-\prevj-\k) --(P-\j-\k) -- cycle;
}{%
\filldraw[black!\tmpK{\j,\k}!B]
(P-\j-\prevk) -- (P-\prevj-\prevk)
-- (P-\prevj-\k) --(P-\j-\k) -- cycle;
}
}{}
}
}
% longitude cycle
\foreach \k [remember=\k as \prevk (initially 0)] in {1, ..., \Nz}{%
\ifthenelse{\test{\aj,\k}=1}{
\draw[red, thick] (P-\aj-\k) -- (P-\aj-\prevk);
}{
\draw[red, very thin, opacity=.4] (P-\aj-\k) -- (P-\aj-\prevk);
}
}
% latitude cycle
\foreach \j [remember=\j as \prevj (initially 0)] in {1, ..., \Ny}{%
\ifthenelse{\test{\j,\ak}=1}{
\draw[red, thick] (P-\j-\ak) -- (P-\prevj-\ak);
}{
\draw[red, very thin, opacity=.3] (P-\j-\ak) -- (P-\prevj-\ak);
}
}
% coordinate system $Oxyz$; second layer
\draw[green!50!black, -{Latex[length=5pt, width=5pt]}]
(\ry+\rz, 0, 0) -- (8, 0, 0) node[right] {$x$};
\draw[green!50!black, -{Latex[length=5pt, width=5pt]}]
(0, 0, 0) -- (0, 6, 0) node[above] {$y$};
\draw[green!50!black, -{Latex[length=5pt, width=5pt]}]
(0, 0, \ry+\rz) -- (0, 0, 8) node[below left] {$z$};
\end{tikzpicture}
\end{document}
Some explanations about the code.
The components of w are \tox, \toy, and \toz, where
\tox = x_w = sin\longit cos\latit
\toy = y_w = sin\latit
\toz = z_w = cos\longit cos\latit
The angles \longit and \latit represent the longitude and the latitude, respectively. See also my answer at Drawing a wedge of a torus in Asymptote for more details .
The components of s are \sunx, \suny, and \sunz. They are computed similarly using \slongit and \slatit.
Note that for these two vectors, zero longitude corresponds to the plane x=0 in the coordinate system Oxyz.
The mesh on the torus is defined by the points (P-\j-\k)
constructed from seeing the torus as the surface of revolution around the Oy axis of a circle of radius \rz in the plane Oxy. The distance from the center of the circle to Oy is \ry>\rz.
isSeen and inLight are the functions based on inner products I was referring to above.
The hidden part of the cycles is controlled manually based on isSeen output.
Of course, if the number of points of the mesh is increased, the result is smoother. But the compilation asks for a large amount of patience. The image below is obtained setting \Nz = 60 and \Ny = 120. I also set \slongit=-110.
