Shadow

I implemented to render shadow from 15, July 2020 to 26, Jully 2020. I had two options to render shadow.

The way to render shadow

  1. shadow mapping.
  2. shadow volumes.

shadow mapping

It uses depth value from light source. The depth value is the distance from near plane of 6 plane box. When you render 3d object, the library kept depth value each pixels to decide which pixel was writen over other pixel from another primitive shape. You need to render 2 times to create one scene.

shadow volume

It creates 3d objects to render shadow which are named shadow volumen. The shadow volume was made from original rendering object which you want to produce shadow. The shadow volume was created by extending light direction away each coordinates. You need to render 4 times to create one scene.

Using shadow mapping

I used shadow mapping to render shadow. Because It seems to be firster processing than shadow volumes.

shadow mapping argorithm

Shadow mapping way is followings.

  1. create offscreen buffer from light source point.
  2. render scene agaist offscreen buffer
  3. store depth into offscreen buffer
  4. render scene from eye point agaist normal screen.
  5. read shadow-depth at the render point from offscreen buffer.
  6. make the pixel darker if the depth value is greater than shadow-depth.

Create depth buffer

I used sun lighting model to render shadow rather than interior lighting. You could think the sun ray is almost parallel light. The shadow shape on objects would be same size becase of parallel light. To calculate these kind of shadow, you use orthographic projection rather than perspective projection. The orthographic project matrix is following.

$$ \begin{equation} P = \left(\matrix{2\over{ right - left } & 0 & 0 & {-(right + left)}\over{right - left} \cr 0 & 2 \over{top - bottom} &0 & {-(top + bottom)}\over{top - bottom}\cr 0 & 0 & -2\over{far - near} & {-(far + near)} \over { far - near }\cr 0 & 0 & 0 & 1}\right) \end{equation} $$

You apply 6 planes bounding box into each 6 parameters. 6 planes value is calculated by every vertex coordinates going to be when you play this game. It was easy for me to give followings.

$$ (left, right, bottom, top) = (x_{min}, x_{max}, y_{min}, y_{max}) $$

near and far

It tooks some minutes to give rest of 2 parameters(near and far). I had each depth values as minus. It likes followings.

$$ (-0.0034, -3.5) $$
If you sort these values in number order.
$$ \begin{equation} (z_{min}, z_{max}) = (-3.5, -0.0034) \label{eq:numodr0} \end{equation} $$
If you sort these values in distance order from origin.
$$ \begin{equation} (z_{min}, z_{max}) = (-0.0034, -3.5) \label{eq:disorder0} \end{equation} $$
I read some Open-GL specifications. I have to choose \eqref{eq:disorder0}. And you should be careful the \(P(3,3)\) signature. The parameter was processed with minus sign. To make z value in box be in range \([-1, 1]\), you pass parameter followings. $$ (near, far) = (- z_{min}, - z_{max}) $$

Open-GL window system coordinate

Why do you have to pass value in range \([-1, 1]\)? It is another open-gl specification. Each coordiates from vertices are clipped in range \([-1, 1]\).

Rendering result

That is all for me to render game scene with shadow. Here is the result with shadow.

game scene with shadow

I noticed the aliasing at some pixels, I would like to improve scene with anti-aliasing someday.