Can you calculate something per instance, not per vertex?

Viewed 253

I’m using instancing to render millions of quads in opengl, and it works okay. The base quad has 6 vertices, and each instance has a vec3 for its position. However, for each instance I need to calculate some vectors based on the instance’s position. If I do this in the vertex shader, I would calculate these vectors 6 times for each instance. Is there a way to calculate them only once per instance?

Before anyone mentions the geometry shader, I used the geometry shader before but I switched to instancing because it was slow. Perhaps there’s a way to use both? And is it beneficial?

2 Answers

Preamble: do not render quads with instancing. Instancing, on various hardware, works best when the size of the instance is not exceedingly small. Small instances can throw away lots of performance on such hardware.

Also... why would your instanced base quad have 6 distinct vertices (as opposed to 4 vertices where 2 are shared)? If you're going to use instancing, it would be better to use a triangle strip with each instance being a 4-element strip.

As for the main thrust of your question... no. There is no instance shader, and there is no way to make the VS execute some of its code per-instance rather than per-vertex.

However, you really shouldn't stress about this. If the computation is "based on the instance's position", then that means the primary performance concern is reading the per-instance data, not the computation. And GPUs have to be able to efficiently deal with multiple invocations reading the same memory addresses, so you can assume that having 4 invocations read from that address will be not much slower than having 1 invocation read from that address.

So just accept it and move on.

If I do this in the vertex shader, I would calculate these vectors 6 times for each instance. Is there a way to calculate them only once per instance?

Not in the same draw call. You can run a compute shader pre-pass with one invocation per instance, and write the per-instance data to an SSBO which you later use as an additional VBO with per-instance attributes in the draw call.

However, you might be optimizing for the wrong thing here. Using only 6 vertices per instance can result in a very bad usage of the GPU resources, and it is not clear if doing your per-instance calculations per vertex is really worse than having some second pass.

Related