deferred par ticle shading

21
Deferred Particle Shading Cooler Looking Smoke For Games • (yeehaa)

Upload: others

Post on 03-Feb-2022

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Deferred Par ticle Shading

Deferred Particle

Shading

• Cooler Looking Smoke For Games

• (yeehaa)

Page 2: Deferred Par ticle Shading

Typical Game Particles

So Far

• Bunch of quads rendered on top of each other

• The e!ect comes from this (semi)-random representation of a volume e!ect...

• This works ok in practice - Player can't tell each particle apart.

Page 3: Deferred Par ticle Shading

Limitations

• All well and good, but smoke can be a very solid thing:

• Typically, we use 3 blend modes to do our particles:

• Multiply (dark smoke), Additive (fiery things), Blending (grayish smoke)

Page 4: Deferred Par ticle Shading

A volume effect

• Smoke really is a volume e!ect. We cannot treat each particle by itself...

• Hence deferred shading:

• We use one (or more) o!screen bu!ers to accumulate the particles (accumulation pass)

• Finally we render a ‘fullscreen' quad onto the main bu!er. (Transfer pass)

Page 5: Deferred Par ticle Shading

Money Shot

Page 6: Deferred Par ticle Shading

Deferred - The Basics:

• We typically care about surface normal & 'amount' of smoke.

• RGB = Normal, A = amount

• Alphablend the normalmaps of particles into an o!screen bu!er.

• Do a transfer pass where we calculate lighting on the accumulated particles.

• Calculate a bumpmap style di!use lighting

• Add inscatter - faking extinction

• Add specular inscatter for light sources behind the smoke

Page 7: Deferred Par ticle Shading

Accumulating The

Particles

• Normal alphablending:

glBlend (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) RGB = Src.rgb * Src.a + Dst.rgb * (1 - Src.a) A = Src.a * Src.a + Dst.rgb * (1 - Src.a)

The particle

RGB

A

Page 8: Deferred Par ticle Shading

Accumulating The

Particles

• Normal alphablending:

glBlend (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) RGB = Src.rgb * Src.a + Dst.rgb * (1 - Src.a) A = Src.a * Src.a + Dst.rgb * (1 - Src.a)

• But we want to ADD the alpha, not blend it

Page 9: Deferred Par ticle Shading

Accumulating The

Particles

• Premultiply the particles RGB in a shader, then do

glBlend (GL_ONE, GL_ONE_MINUS_SRC_ALPHA)

• This gives

RGB = Src.rgb * Src.a + Dst.rgb * (1 - Src.a) A = Src.a * ONE + Dst.rgb * (1 - Src.a)

• RGB is still blended....

Page 10: Deferred Par ticle Shading

Accumulating The

Particles

• Premultiply the particles RGB in a shader, then do

glBlend (GL_ONE, GL_ONE_MINUS_SRC_ALPHA)

• This gives

RGB = Src.rgb * Src.a + Dst.rgb * (1 - Src.a) A = Src.a * ONE + Dst.rgb * (1 - Src.a)

• Alpha is now oldskool AddSmooth

Page 11: Deferred Par ticle Shading

Accumulating The

Particles

Accumulation Result

Silly Demonstration Particle

RGB A

Proper Ingame Particle

RGB A

Page 12: Deferred Par ticle Shading

Transfer & Lighting

Accumulated Normals Lit & Blended

Page 13: Deferred Par ticle Shading

Transfer & Lighting

• Surface lighting is just: surface normal • light direction

• But smoke is not just surface lighting - we got a lot of scattering going on:

• Self-illumination like scatter:

• If we have a light behind the particles, we can add some specular scattering.

Page 14: Deferred Par ticle Shading

Shade Tree

Di!use front-lit

Specular scatter

Soft Scatter & ambient

Combined lighting

Final E!ect

+

+

Page 15: Deferred Par ticle Shading

Transfer & Lighting

• Don’t do a fullscreen quad

• Render the particle system’s bounding box instead

• Slightly tighter fit

• Plays nicely with depth bu!er of other objects in your scene

• Needs special handling of near-plane clipping.

• To get per-particle depth testing going again, you have 2 options:

• Render depth of bbox-intersecting objects to o!screen bu!er

• Or use FBOs to only rebind the color bu!er & reuse existing scene depth.

Page 16: Deferred Par ticle Shading

Diffuse Lighting

• The normal map is in viewport space.

• Hence, we need to get the light direction in viewport space

• Need to normalize particle fragments.

• This is getting expensive... Do a cubemap lookup instead...

• Dynamically bake a cubemap for all your lights, and use that.

Page 17: Deferred Par ticle Shading

Soft Scattering

• Fake this with an alpha ramp & add it in

Page 18: Deferred Par ticle Shading

Specular Scattering

• Lights behind smoke tend to do a specular-like backlighting

• Add a quad around all lights, using a similar alpha ramp as above.

Page 19: Deferred Par ticle Shading

Speed

• How can this be fast?

• Particles are inherently overdraw-heavy - we're fillrate bound.

• We can keep the o!screen bu!ers at lower res to conserve fillrate. Clamp the resolution.

• We only do one fullscreen quad to get them on to the screen.

• This means the worst-case result (lots of particles right in front of the camera) gets much tighter shading & fill bounds.

Page 20: Deferred Par ticle Shading

Details

• Getting the normalmap right is a bitch.

• Grayscale heightmaps never get ‘curvy’ enough.

• Get your gfx artist to ZBrush you a wispy cloud.

• Or use metaballs, then add some procedural bump

• Handpaint noisy alpha in Photoshop

Page 21: Deferred Par ticle Shading

Details

• The hard part is getting the cubemap working

• Start simple: Get a di!use cubemapped particle to play nicely with your lighting system!