Rama physically-based lighting
Direct paths

1 Introduction

In this section we want to compute the light which goes directly from the Rama light sources into the camera. We first assume there is no atmosphere, and then take the atmosphere into account.

2 Direct light without atmosphere

Each "linear" light source in Rama is in fact a very thin and very long area light source. By hypothesis, each patch of this area light emits the same radiance $L_0$, in all directions. Thus the radiance received directly from a light source at a given screen pixel is $L_{LE}=fL_0$ where $f$ is the fraction of the pixel covered by light source elements. Simple geometric considerations (see Fig. 1) show that $f$ is inversely proportional to the distance $l$ between the camera and the light source (as expected for a linear light), and proportional to the cosine of the angle $\theta$ between the light source normal and the view direction.



Figure 1: Direct paths.

However, we don't need to compute $f$ explicitly in order to get the direct light at each pixel. Instead, we can take advantage of the GPU rasterization, texturing and mipmapping capabilities to compute this automatically for us. For this we simply need to store $L_0$ in a lightmap, where the light sources are, and 0 elsewhere. Rendering the model textured with this lightmap will then give us the desired result.

The only remaining step is to compute $L_0$. Our low resolution 3D Rama model has a total inner surface of $2410.71\,km^2$ and, as computed in the physics section, we want each square meter to absorb $I_0=133\,W.m^{-2}$, in average, to get a similar illuminance as on Earth. This gives a total power of $320\,GW$. The north light sources are $10.8\,km$ long, while the south light sources are $11.3\,km$ long. We assume that both are $100\,m$ wide. Also, since the south plain cylinder has a radius of $7.5\,km$ (instead of $8\,km$ for the north plain cylinder), we want the south light sources to be $8.0/7.5$ times less intense than the north light sources, in order to get a similar illuminance in the south and north plains. The radiance $L_0$ for each north light source must therefore satisfy $3\times 1.08\,10^6(1+\frac{7.5}{8.0})\pi L_0=320\,10^9$, from which we deduce $L_0=16.226\,W.m^{-2}$. And the radiance for each south light source is then $\frac{7.5}{8.0}\frac{1.08}{1.13}L_0=14.538\,W.m^{-2}$.

2 Direct light with atmosphere

Due to the atmosphere, the light going from a light source to the camera can be scattered in another direction by air molecules between these two points. This means that less light will arrive directly from the light source than in the vaccum case. This fraction is exactly the transmittance $\mathfrak{t}$ of the atmosphere, that we computed in the physics or Rama. The result is \begin{align*} \mathfrak{t}(\bp,\bq)&=\exp\left(-k_s(0)\int_\bp^\bq \exp\left(Kr^2\right) \diff x\right)\quad\mathrm{where}\quad K\eqdef\frac{\omega^2}{2R_sT_a}\\ &\approx\exp\left(-k_s(0)\Vert\bq-\bp\Vert\left[1+c+\frac{b+bc+c^2}{2}+\frac{a}{3}+\frac{ab}{4}+\frac{b^2+2ac}{6}+\frac{a^2}{10}\right]\right) \end{align*} where $k_s(0)$ is the scattering coefficient on the rotation axis, depending on the wavelength, and where \begin{align*} a&=K((q_y-p_y)^2+(q_z-p_z)^2)\\ b&=2K((q_y-p_y)p_y+(q_z-p_z)p_z)\\ c&=K(p_y^2+p_z^2)\\ \end{align*} in Rama coordinates, a coordinate system where the Rama axis is equal to the $x$-axis.

3 Implementation

The implementation of the above equations is straightforward:
// Specific gas constant of air (J.kg^-1.K^-1).
const float Rs = 287.68;
// Rama's surface radius (km).
const float rs = 8.0;
// Rama's angular speed (rad.s^-1).
const float omega = 2.0 * PI / 180.0;
// Rama's atmosphere temperature (K).
const float Ta = 15.0 + 273.15;

// Inverse atmosphere "scale height" (km^-2).
const float K = omega * omega * 1e6 / (2.0 * Rs * Ta);
// Scattering coefficient on the rotation axis, for the RGB channels (km^-1).
const vec3 ks0 = vec3(5.8e-3, 13.5e-3, 33.1e-3) / exp(K * rs * rs);

// Return the transmittance of the atmosphere, in the RGB channels, between
// the two given points (which must be given in Rama coordinates with km units).
vec3 transmittance(vec3 p, vec3 q) {
  q -= p;
  float a = K * dot(q.yz, q.yz);
  float b = 2.0 * K * dot(q.yz, p.yz);
  float c = K * dot(p.yz, p.yz);
  float v = 1.0 + c + (b + c * (b + c)) / 2.0 + a / 3.0 + (a * b) / 4.0 +
      (b * b + 2.0 * a * c) / 6.0 + (a * a) / 10.0;
  return exp(-ks0 * length(q) * v);
}

4 Results

Here is the result without atmosphere (the result with atmosphere looks the same, because in both cases the light source pixels are over exposed):



Figure 1: Direct light from the light sources to the camera.