PDA

View Full Version : Practical multipass rendering


Shirakana
04-08-2008, 05:00 AM
Hi all !
I think I know the theory about multipass rendering but I still couldn't see what the implementation should look like (in OpenGl for me).

Should this be like:

void draw() {

/* pass 1 */
-- special instructions for pass 1 --
for each object {
drawObject(); /* = Gl instructions */
}

/* pass 2 */
-- special instructions for pass 2 --
for each object {
drawObject(); /* = Gl instructions */
}

}


Or something like:

void draw() {

for each object {

/* pass 1 */
-- special instructions pass 1 --
drawObject(); /* = Gl instructions */

/* pass 2 */
-- special instructions pass 2 --
drawObject(); /* = Gl instructions */
}
}

or maybe two calls to draw() with a pass number as parameter ?

or something really different ?

What about culling, raterising and other fixed pipeline stuff for multipass rendering ? Done for each object each pass ?

Thanks for giving me some clues !

Reedbeta
04-08-2008, 08:30 AM
The first one.

You want to minimize state changes since they take time, and so you want to do the state changes between pass 1 and pass 2 just once per frame, rather than once per object.

Shirakana
04-08-2008, 08:37 AM
Another question is when do the GPU render pipeline (vertex transformation - culling - rasterisation...) is called:
- at the end of each glBegin()...glEnd() block ?
- or at the end of the of each draw() call when all geometry have been sent to CG ?

Thanks

.oisyn
04-08-2008, 08:57 AM
Depends on the implementation, really. The driver can even decide to queue the commands several frames ahead.

JarkkoL
04-08-2008, 11:27 AM
I prefer the latter myself as you can get quite flexible architecture that way. You don't necessarely get less state changes with the first option either as you have to more frequently be switching between objects which requires quite some updates to the states.

Shirakana
04-09-2008, 12:57 AM
Ok so if I'd like to make ssao for instance, I could do like that:

void draw() {

// Pass 1 = normal rendering
for each object
drawObject();

// So now I can consider that CG has computed all the geometry ??
zbuffer = getCurrentZBuffer();
colorBuffer = getCurrentColorBuffer();
setShaderAttribute(ssao,zbuffer);
setShaderAttribute(ssao,colorBuffer);
activateShader(ssao);
drawFullScreeQuad();

}

Reedbeta
04-09-2008, 01:15 AM
If the GPU does not render the geometry immediately, it will queue up the rendering commands and state changes (or rather the driver will)...so yes, you can set whatever state you need to do SSAO, without worrying too much about precisely when the commands are executed.

JarkkoL
04-09-2008, 10:12 AM
Usually you first have depth pass over all the objects, which is followed by rendering the actual lighting/shading pass. The result from depth pass can be used for various things, such as for SSAO computation. You actually have to compute SSAO before rendering the lighting/shading pass because that result from SSAO is used in the lighting/shading pass.

mmakrzem
04-11-2008, 05:04 AM
On my website you will find a two pass render implementation (VMK27) that shows you how to sort your objects by depth so that transparent objects always get rendered last in the correct order to show objects that are behind them correctly.

Shirakana
04-14-2008, 01:08 AM
Many thanks for all of you