Imposter Rendering

GPU Skinning speeds up simulating skinning technique, but it’s still not enough to rendering 10k+ animating objects.

Simulation might can be shared same objects, but rendering animating object is totally different story.

For example, if we render object which has 5000+ vertices 100 times, our GPU needs to simulate 500000 vertices which is very heavy work

How this work?

The Overall Idea is capture animating object and use that capture as texture of quad which always facing towards camera.

First, we need to capture animating object to Frame Buffer in every frames.

Texture Example

Capturing could get with these following steps.

1 : Initialize camera which placed in front of animating object, and facing toward object.

2 : Bind frame buffer which we want capturing.

3 : Render object with initialized camera.

4 : Unbound the frame buffer (Set to default frame buffer).

Implement Quad

We need to make quad so we can apply our textures.

Making quad is very easy, just initialize with vertices like,

(-1, -1, 0) ,(-1, 1, 0) ,(1, 1, 0) ,(1, -1, 0)

And multiply those with object’s world matrix

Now we have quad, but, it’s just a quad, it’s not a 3D object, it’s just 2D object.

People might notice this as they move camera.

So, we need to make this quad Always facing toward camera.

It’s very easy, since every object’s rotation was setted via multiplication of Camera Matrix and Model Matrix

All we need to do is initialize rotation parts as identity matrix.

Initialize Rotation part as Identity matrix

Almost done! All we need to do is just texturing.

Rotating successfully done, but something’s wrong

When capturing to framebuffer, the background color also captured.

We need only character part, we need to discard background color.

So check the texture Color’s alpha value, if it’s smaller than normal value, discard it

Good!

Extra Work

Imposter Rendering is done, but when rendering quad, passing quad vertices & texture coordinates is take costs a lot, cause we have to render 10k+ quads.

What we could do is utilize geometry shader, we could pass position data of the billboard, and enlarge that point into quads.

Which can done just one draw call glDrawArrays(GL_POINTS, 0, 1)

Geometry Shader, enlarge our point input to quad