Gamasutra is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Gamasutra: The Art & Business of Making Gamesspacer
Tutorial: Simple, High-Performance Particles for Mobile
View All     RSS
December 14, 2019
arrowPress Releases
December 14, 2019
Games Press
View All     RSS







If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 

Tutorial: Simple, High-Performance Particles for Mobile


May 20, 2013 Article Start Previous Page 2 of 4 Next
 

Blend Modes

For our effects to look right, we need to use the appropriate blend mode. I'll focus on OpenGL, but everything stated here holds for DirectX or any other low-level 3D API.

The last stage of the OpenGL 1 pipeline is to combine the current color at the pixel buffer with the color of the incoming fragment. The examples for glBlendFunc in OpenGL ES 1.1 docs states that:

Transparency is best implemented using glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) with primitives sorted from farthest to nearest.

This is unfortunate, as compositing images with this blend mode is limited and error prone. (Working naïvely with this blend mode might cause dark halos around objects)

Consider a pixel represented by: (Rs,Gs,Bs,As) which we would like to blend with the existing pixel: (Rd,Gd,Bd,Ad) where each pixel component is in the [0,1] range.

OpenGL suggests the following blending: (using the red channel as an example)

Rout = As*Rs + (1-As)*Rd

Notice that all components are always lower than or equals to one -- We cannot lighten the scene, only darken it. This blending mode is good for occluding (see the world through pink glasses), but cannot be used to lighten a scene.

To illuminate (use a flashlight over something for example), we might have chosen to do:

glBlendFunc(GL_SRC_ALPHA, GL_ONE)

That blends as follows:

Rout = As*Rs + Rd

Where we only add light to scene and control the amount of light added with the source's alpha channel. However, again, as all components are always non-negative we can only lighten the scene, disallowing occlusion.

To accommodate for both needs, Porter & Duff in a 1984 paper (Computer Graphics Volume 18, Number 3 July 1984 pp 253-259) suggest using:

Rout = Rs + (1-As)*Rd

or:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)

That allows us achieve both occlusion and illumination:

  • Occlusion is achieved by premultiplying the RGB channels with the alpha channel: Rs=Rs*As for every pixel in the original texture. This makes the above method identical to the method suggested in the OpenGL docs, and saves a runtime multiplication.
  • Illumination is achieved by not premultiplying the texture, and using the alpha channel as the amount of light to add to the scene

A picture is worth a thousand words. In the following example both particles are rendered with the same alpha channel (shown on the right) in the same blend mode (mentioned at the bottom). Notice how we're able to achieve smooth occlusion on the right particle, while being able to lighten the background on the circumference of the left particle:

If I would have had to guess why OpenGL authors chose the less useful blending equation as their example, I would guess that it's because most (if not all) graphic editors don't premultiply alpha, and this is the correct way to achieve the expected particle (on the right). 


Article Start Previous Page 2 of 4 Next

Related Jobs

Deep Silver Volition
Deep Silver Volition — Champaign, Illinois, United States
[12.12.19]

Principal Writer
Sucker Punch Productions
Sucker Punch Productions — Bellevue, Washington, United States
[12.11.19]

Producer
Sanzaru Games Inc.
Sanzaru Games Inc. — Dublin, California, United States
[12.11.19]

Producer
Digital Extremes Ltd.
Digital Extremes Ltd. — London, Ontario, Canada
[12.11.19]

Senior Project Manager





Loading Comments

loader image