Title: Special Effects
1 Special Effects Blending
- Color blending in OpenGL allows you to introduce
special effects such as transparency into your
scenes - This is accomplished by using the alpha value (ie
RGBA) - Here we combine the color of the incoming
color(the one being written) with the one already
in the buffer. - an alpha of 0 is full transparency and an alpha
of 1 is completely opaque.
2Blending
- Call glEnable(GL_BLEND) to prepare OpenGL
- Call glBlendFunc() to define the source and
destination blending functions - Default arguments are GL_ONE for the source and
GL_ZERO for the destination.
3Source Blending Functions
- GL_ZERO The source color is equal to
(0,0,0,0) - GL_ONE Use the current color
- GL_DST_COLOR Multiply the source by the dest.
- GL_ONE_MINUS_DST_ALPHA Mult. Src by 1-dest.
- GL_SRC_ALPHA Multiply the source by the source
alpha value. - ---- there are others ---
4Destination Blending Functions
- GL_ZERO Dest is equal to (0,0,0,0)
- GL_ONE Use the current dest color.
- GL_SRC_COLOR Mult. the dest by the source
- GL_ONE_MINUS_SRC_COLOR Mult. the dest. by
(1,1,1,1)-source color - GL_SRC_ALPHA Mult. the dest by the source alpha
- --- there are others -----
5Transparency Example
The following sets up blending for
transparency void Initialize() glEnable(GL_BLE
ND) glBlendFunc(GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA) glShadeModel(GL_SMOOTH)
glClearColor(1.0f, 1.0f, 1.0f, 0.0f)
Note
6Drawing Two Polys
void DrawLeftPoly() glColor4f(0.8f, 0.9f,
0.7f, 0.6) // Note alpha of .6
here glBegin(GL_QUADS) glVertex3f(-10.0f,
-10.0f, 0.0f) glVertex3f(0.0f, -10.0f,
0.0f) glVertex3f(0.0f, 10.0f,
0.0f) glVertex3f(-10.0f, 10.0f,
0.0f) glEnd()
7Second Poly
void DrawRightPoly() glColor4f(0.0f, 0.5f,
0.5f, 0.6) // Note alpha of .6 glBegin(GL_QUADS)
glVertex3f(0.0f, -10.0f, 0.0f) glVertex3f(1
0.0f, -10.0f, 0.0f) glVertex3f(10.0f, 10.0f,
0.0f) glVertex3f(0.0f, 10.0f,
0.0f) glEnd()
8The Render Function
void Render() glClear(GL_COLOR_BUFFER_BIT
GL_DEPTH_BUFFER_BIT) glLoadIdentity() if
(angle gt 359.9f)angle 0.0f angle 0.1//
increase rotation angle glTranslatef(0.0f, 0.0f,
-40.0f) glPushMatrix() // rotate and draw the
opaque polygon glRotatef(angle, 0.0f, 0.0f,
1.0f) if (leftFirst) DrawLeftPoly()else DrawRi
ghtPoly() glPopMatrix() glPushMatrix() //
rotate and draw the transparent
polygon glRotatef(angle, 0.0f, 0.0f,
-1.0f) if (leftFirst) DrawRightPoly()else Draw
LeftPoly() glPopMatrix() glFlush() SwapBuffe
rs(g_HDC)
9Blending with Depth Buffer
Your normally want to render both opaque and
translucent object in the same scene You also
want to use the Depth Buffer to eliminate the
more distant objects that are behind opaque
objects whether they be opaque or translucent. If
the translucent object is closest the you want to
blend it with the underlying opaque object. The
solution is to enable depth-buffering but make
the depth buffer read-only while drawing
translucent objects.
10 Depth Testing ??
The correct way to do blending in OpenGL involves
turning the depth buffer on and off when you are
drawing a scene. 1. Depth testing on, depth
buffer in normal mode 2. Draw opaque objects 3.
Set glDepthMask(GL_FALSE) to read-only 4. Draw
translucent objects
11 Billboarding
- Reduce geometric complexity by replacing geometry
with textures - Games may require many copies of similar
backgound objects such as trees and clouds - Objects with axial or point symmetry approximated
with 1 or 2 polygons - Rotate textured polygon to keep facing the
viewer. - Very useful for particle engines
12 Rendering Trees
We can intersect two trees with transparent
backgrounds.
13Face Billboard toward viewer
The way we do this is to align the billboarded
polygon so that its surface normal is parallel to
and opposite the players viewing direction. We
can accomplish this by reversing the effect of
the rotations performed by the view
matrix. GLfloat viewMatrix16 // get the
matrix glGetFloatv(GL_MODELVIEW_MATRIX,
viewMatrix) Now how do we reverse this matrixs
effect??
by Multiplying by the inverse matrix?
14Obtaining the inverse
- The inverse of an orthogonal matrix is its
transpose! - The first row of the MT is the right vector and
the second row is the up vector
Vector right(viewMatrix0. viewMatrix4,
viewMatrix8) Vector up(viewMatrix1.
viewMatrix5, viewMatrix9)
right ---gt up ---gt
15So Lets Render the Quad
- // Assume centerPoint is center of quad. So
generate four corner points - // using a similar method to the following
- newPoint centerPoint up hScale right
wScale - // bottom left corner
- glTexCoord2f(0.0, 0.0) glVertex3fv((pos
(right up) -size).v) - // bottom right corner
- glTexCoord2f(1.0, 0.0) glVertex3fv((pos
(right - up) size).v) - // top right corner
- glTexCoord2f(1.0, 1.0) glVertex3fv((pos
(right up) size).v) - // top left corner
- glTexCoord2f(0.0, 1.0) glVertex3fv((pos
(up - right) size).v)
16The BMP File Cacti
The cacti bmp file is shown at the right. Note
its black background. This is the transparent
part. It is made invisible by
glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA) glEnable(GL_ALPHA_TEST
)// Enable alpha value testing(redbook)
glAlphaFunc(GL_GREATER, 0)// Accept those that
are gt zero
17How do we load this bmp?
void LoadTexture(char filename, GLuint
texture) // get a texture object
glGenTextures(1, texture) glBindTexture(GL_TEXT
URE_2D, texture) // load the bitmap
BITMAPINFOHEADER bitmapInfoHeader unsigned
char buffer LoadBitmapFileWithAlpha(filename,
bitmapInfoHeader) // set up the texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
GL_REPEAT) glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILT
ER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST)
glTexImage2D(GL_TEXTURE_2D, 0, 4,
bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeigh
t, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer)
gluBuild2DMipmaps(GL_TEXTURE_2D, 4,
bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeigh
t, GL_RGBA, GL_UNSIGNED_BYTE, buffer) free(buffer
) // end LoadTexture()
Note this function
18Load BMP with Alpha
(See Handout)
unsigned char LoadBitmapFileWithAlpha(char
filename, BITMAPINFOHEADER bitmapInfoHeader)
unsigned char bitmapImage LoadBitmapFile(filen
ame, bitmapInfoHeader) // What does the
following do? unsigned char bitmapWithAlpha
(unsigned char ) malloc(bitmapInfoHeader-gtbiSiz
eImage 4 / 3) if (bitmapImage NULL
bitmapWithAlpha NULL) return NULL //
Drop out if error
19 Second Part of loader
// loop through the bitmap data for (unsigned
int src 0, dst 0 src lt bitmapInfoHeader-gtbiSi
zeImage src 3, dst 4) // if the
pixel is black, set the alpha to 0. Otherwise,
set it to 255. if (bitmapImagesrc 0
bitmapImagesrc1 0 bitmapImagesrc2
0) bitmapWithAlphadst3 0 else
bitmapWithAlphadst3 0xFF // copy
pixel data over bitmapWithAlphadst
bitmapImagesrc bitmapWithAlphadst1
bitmapImagesrc1 bitmapWithAlphadst2
bitmapImagesrc2
20 And dont forget this
glTexImage2D(GL_TEXTURE_2D, 0, 4, bitmapWidth,
bitmapHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
buffer) glTexImage(target, level,
internalFormat, width,height, border, format,
type,texels)
Format of image data in BMP file
21Particle Systems
A Particle system is a collection of a number of
individual elements, or particles. Each particle
has individual attributes such as Position,
Velocity, Life span, Size, Color etc Particle
systems generally work by creating thousands of
particles and sending them randomly in different
directions. As each particle moves it is acted
upon by a variety of forces. Essentially these
are physics simulators.
22The particles themselves
Particles may be rendered in a variety of ways.
The most common is probably via billboarding
while individual(single) vertex or line segment
display could also be used. The billboard is
usually a texture-mapped quad. In our case we
will use a base particle-system class and derive
new classes from that. This allows us to
incorporate common code in the base class.
23Base Class CParticleSystem
The following methods will be used in the base
class Initialize- create space for particles and
init several vars Update- This function will
update the time with a small value. Generates
new particles as needed. Render- Displays the
particles Move - Move the particles as a function
of their velocity. Force- modify the forces that
apply on all the particles.
24The code for ParticleSystem
struct Particle Point pos Point
pastPos Vector velocity float size float
weight float color4
Almost anything could be here
25The base class
class CParticleSystem protected int
m_maxParticles int m_numParticles float
m_accumulatedTime Point m_origin Particle
m_particleList Vector m_accel //
gravity virtual void InitializeParticle(int
index)0
public CParticleSystem()// default
constructor CParticleSystem(int maxParticles,
Point origin) virtual void Update(float
elapsedTime) 0 virtual void Render()
0 // regular methods virtual int Emit(int
numParticles) virtual void InitializeSystem()
virtual void KillSystem() virtual
CParticleSystem()// destroy system
Abstract Funcs
26Initialize the System
void CParticleSystemInitializeSystem() // if
this is just a reset, free the memory if(m_partic
leList) delete m_particleList m_particle
ListNULL // Allocate particle
array m_particleList new Particlem_maxParticle
s // reset the number of particles and
accumulated time m_numParticles
0 m_accumulatedTime0.0f m_accelACC_DUE_TO_G
RAV
27 Emit new particles as needed
// Create the number of new particles
specified int CParticleSystemEmit(int
numParticles) // note that InitializeParticle
is abstract so must be // implemented by the
user of this class while(numParticles
(m_numParticles lt m_maxParticles)) Initialize
Particle(m_numParticles) --numParticles
return numParticles
28 Construction and Cleanup
//Initialize the parameters CParticleSystemCPart
icleSystem(int maxParticles, Point
origin) m_maxParticles maxParticles m_origi
n origin m_particleList NULL void
CParticleSystemKillSystem() if(m_particleList
) // if there are particles left delete
m_particleList m_particleList
NULL m_numParticles0
constructor