Figure 1 gives an overview of our algorithm. Our algorithm composes of two passes: a shadow pass and a lighting pass. First, we present our main idea and describe the details of the shadow pass in “Shadow pass”. Later, we describe the lighting pass in “Lighting pass”. Throughout the presentation, we use the term triangle, but it can naturally extend to a general geometry which might have animation data defined by Myeong-Won et al. [14].

### Shadow pass

We assume a triangle linearly moves from the beginning (*t* = 0) to the end (*t* = 1) of a frame. The position of this triangle at *t* = 0 and *t* = 1 is *ABC* and *A′B′C′*, respectively. To generate motion blurred shadows for this triangle, a brute force method renders this triangle many times and averages all rendered images. The goal is to find a visible time range of this triangle at each pixel and compute an average color along this time range. At the pixel *P*, this triangle is visible through five intersection points at five times *t*
_{
1
}, *t*
_{
2
}, *t*
_{
3
}, *t*
_{
4
}, and *t*
_{
5
}, in Fig. 2a. From this observation, our main idea is to render this triangle only once and get a visible time range of this triangle by finding the first and the last intersection points (*F*
_{
1
} and *F*
_{
2
}) at the first time (*t*
_{
1
}) and the last time (*t*
_{
5
}), respectively. So at the pixel *P*, we can compute the visible time range of this triangle and know a depth range from *F*
_{
1
} to *F*
_{
2
}.

To implement our main idea, we assign a time to each vertex of two triangles *ABC* (*t* = 0) and *A′B′C′* (*t* = 1). Next, we use *ABC* and *A′B′C′* to form a prism, in Fig. 2b, and then triangulate this prism. For each pixel, GPU generates two points (*F*
_{
1
} and *F*
_{
2
}), with each point having an interpolated time and a depth value. These two points form a visible time range of the triangle which can be computed as |*t*
_{
1
} − *t*
_{
5
}|.

With this main idea, we render a scene from the light to generate a temporal shadow map. For each pixel in the temporal shadow map, we store a list of tuples with five values in the form: (*t*
_{
1
}
*_t*
_{
2
}, *z*
_{
1
}
*_z*
_{
2
}
*, id*), where (*t*, *z*) is an interpolated time, a depth value of a generated point such as *F*
_{
1
}. “*id”* is an *id* of a triangle in which the current fragment belongs to, and this triangle *id* is used to address self-shadow artifacts in the lighting pass.

### Lighting pass

In this pass, we use the stochastic rasterization [5] to render a scene from the camera. A triangle covers a set of pixels when moving from the start (*t* = 0) to the end (*t* = 1) of a frame. We use two positions of this triangle at *t* = 0 and *t* = 1 to make a convex hull to cover all such pixels. There are multi-samples per pixel and each sample has a random time. To check whether the current sample is visible or not, we shoot a ray from the camera through the current sample and then perform a ray-triangle intersection. If there is an intersection, the current sample is visible.

To perform the shadow lookup at a visible sample, we do as follows. First, we project this sample to the temporal shadow map and load each tuple (*t*
_{
1
}
*_t*
_{
2
}, *z*
_{
1
}
*_z*
_{
2
}, *id*). If the visible sample’s time (*t*
_{
s
}) is inside the visible time range [*t*
_{
1
}, *t*
_{
2
}], we find a depth value at *t*
_{
s
} using the linear interpolation along the depth range [*z*
_{
1
}, *z*
_{
2
}] and compare the interpolated depth with the sample’s depth. Finally, we perform shading and average all samples’ color in a pixel. To address the self-shadow artifacts in TSM, we check if the current sample does not belong to the current triangle prior the shadow test.