Home Robotics C++ Physics II AP Physics B Electronics AP Java Astronomy Independent Study Summer Session Contests  About
                                                       

Blending

 

 

Introduction

Source and Destination Blending Factors

Generating Blending Factors

Table of Blending Factors

Example 1

Example 2

Exercises

 

 

 

Introduction

 

What is the difference between transparent, translucent, and blended primitives?

 

A transparent physical material shows objects behind it as unobscured and doesn't reflect light off its surface. Clear glass is a nearly transparent material. Although glass allows most light to pass through unobscured, in reality it also reflects some light. A perfectly transparent material is completely invisible.

 

A translucent physical material shows objects behind it, but those objects are obscured by the translucent material. In addition, a translucent material reflects some of the light that hits it, making the material visible. Physical examples of translucent materials include sheer cloth, thin plastic, and smoked glass.

 

Transparent and translucent are often used synonymously

 

An opaque material is one that is neither transparent nor translucent. It obscures everything behind it.

 

Blending is OpenGL's mechanism for combining color already in the framebuffer with the color of the incoming primitive. Blending is frequently used to simulate translucent physical materials. One example is rendering the smoked glass windshield of a car. The driver and interior are still visible, but they are obscured by the dark color of the smoked glass.

 

"Blending" allows us to specify a blending function that combines color values from a source and a destination. The final effect is that parts of the scene appear translucent.

 

We have already seen alpha values (alpha is the A in RGBA), but they've always been 1.0 (opaque) and they haven't been discussed. Alpha values are specified with glColor*(), when using glClearColor() to specify a clearing color, and when specifying certain lighting parameters such as a material property or light-source intensity.

 

When blending is enabled, the alpha value is used to combine the color value of the fragment being processed (referred to as the source) with that of the pixel already stored in the framebuffer (referred to as the destination). Blending lpha values can also be used in the alpha test to accept or reject a fragment based on its alpha value.

 

Without blending, each new fragment overwrites any existing color values in the framebuffer, as though the fragment is opaque. With blending, you can control how much of the existing color value should be combined with the new fragment's value.

 

The most natural way to think of blending operations is to view the RGB components of a fragment as representing its color, and the alpha component as representing opacity. Thus, transparent or translucent surfaces have lower opacity than opaque ones.

 

For example, if you're viewing an object through green glass, the color you see is partly green from the glass and partly the color of the object. The percentage varies depending on the transmission properties of the glass: If the glass transmits 80 percent of the light that strikes it (that is, has an opacity of 20 percent), the color you see is a combination of 20 percent glass color and 80 percent of the color of the object behind it. You can easily imagine situations with multiple translucent surfaces. If you look at an automobile, for instance, its interior has one piece of glass between it and your viewpoint; some objects behind the automobile are visible through two pieces of glass.

 

Source and Destination Factors

 

During blending, color values of the incoming fragment (the source) are combined with the color values of the corresponding currently stored pixel (the destination) in a two-stage process. First, you specify how to compute source and destination factors. These factors are RGBA quadruplets that are multiplied by each component of the R, G, B, and A values in the source and destination, respectively. Then, the corresponding components in the two sets of RGBA quadruplets are added. To show this mathematically, let the s and d subscripts specify the source and destination pixels. The S and D components are the blend factors. 

 

     Sr, Sg, Sb, Sa and Dr, Dg, Db, Da               Source red, source green, source blue, source alha et

 

where  S denotes source (new entry) and D denotes destination (already there)

 

Then, the final, blended RGBA values are given by

 

      RsSr+RdDr, GsSg+GdDg, BsSb+BdDb, AsSa+AdDa     (red source)x(red source blending factor) + (red destination)x(red destination blending factor) etc

                                                                                         (alpha source)x(alpha source blending factor) + (alpha destination)x(alpha destination blending factor)

Each component of this quadruplet is eventually clamped to [0,1].

 

Generating Blending Factors

 

How are the the source and destination blending factors are generated. You use glBlendFunc() to supply two constants: one that specifies how the source factor should be computed, and one that indicates how the destination factor should be computed. Also, to have blending take effect, you need to enable it:

   

glEnable(GL_BLEND);

 

Use glDisable() with GL_BLEND to disable blending.

 

Also, note that using the constants GL_ONE (source) and GL_ZERO (destination) gives the same results as when blending is disabled; these values are the default.void glBlendFunc(GLenum sfactor, GLenum dfactor)

 

Controls how color values in the fragment being processed (the source) are combined with those already stored in the framebuffer (the destination). The argument sfactor indicates how to compute a source blending factor; dfactor indicates how to compute a destination blending factor. The possible values for these arguments are explained below . The blend factors are assumed to lie in the range [0,1]; after the color values in the source and destination are combined, they're clamped to the range [0,1].

 

In the following table , the RGBA values of the source and destination are indicated with the subscripts s and d, respectively. Also, division of an RGBA quadruplet by a scalar means dividing each component by that value. Similarly, subtraction of quadruplets means subtracting them componentwise. The Relevant Factor column indicates whether the corresponding constant can be used to specify the source or destination blend factor.

 

Table of Blending Factors

 

Source and Destination Blending Factors

Constant

Relevant Factor

Computed Blend Factor

GL_ZERO

source or destination

(0, 0, 0, 0)

GL_ONE

source or destination

(1, 1, 1, 1)

GL_DST_COLOR

source

(Rd, Gd, Bd, Ad)

GL_SRC_COLOR

destination

(Rs, Gs, Bs, As)

GL_ONE_MINUS_DST_COLOR

source

(1, 1, 1, 1)-(Rd, Gd, Bd, Ad)

GL_ONE_MINUS_SRC_COLOR

destination

(1, 1, 1, 1)-(Rs, Gs, Bs, As)

GL_SRC_ALPHA

source or destination

(As, As, As, As)

GL_ONE_MINUS_SRC_ALPH A

source or destination

(1, 1, 1, 1)-(As, As, As, As)

GL_DST_ALPHA

source or destination

(Ad, Ad, Ad, Ad)

GL_ONE_MINUS_DST_ALPH A

source or destination

(1, 1, 1, 1)-(Ad, Ad, Ad, Ad)

GL_SRC_ALPHA_SATURATE

source

(f, f, f, 1); f=min(As, 1-Ad)

 

 

 

Example 1: alpha.c

Blending Example

 

This program draws several overlapping filled polygons to demonstrate the effect order has on alpha blending results. Use the 't' key to toggle the order of drawing polygons.   Which one was drawn first?

 

 

 

 

 

#include <GL/glut.h>

#include <stdlib.h>

 

static int leftFirst = GL_TRUE;

 

//Initialize alpha blending function.

 

static void init(void)

{

   glEnable (GL_BLEND);

   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   glShadeModel (GL_FLAT);

   glClearColor (0.0, 0.0, 0.0, 0.0);

}

 

static void drawLeftTriangle(void)

{

   /* draw yellow triangle on LHS of screen */

 

   glBegin (GL_TRIANGLES);

      glColor4f(1.0, 1.0, 0.0, 0.75);                  //what is the purpose of this line of code (exercise 2)

      glVertex3f(0.1, 0.9, 0.0);

      glVertex3f(0.1, 0.1, 0.0);

      glVertex3f(0.7, 0.5, 0.0);

   glEnd();

}

 

static void drawRightTriangle(void)

{

   /* draw cyan triangle on RHS of screen */

 

   glBegin (GL_TRIANGLES);

      glColor4f(0.0, 1.0, 1.0, 0.75);        //what is the purpose of this line of code? (exercise 2)

      glVertex3f(0.9, 0.9, 0.0);

      glVertex3f(0.3, 0.5, 0.0);

      glVertex3f(0.9, 0.1, 0.0);

   glEnd();

}

 

void display(void)

{

   glClear(GL_COLOR_BUFFER_BIT);

 

   if (leftFirst)

   {

      drawLeftTriangle();

      drawRightTriangle();

   }

   else

  {

      drawRightTriangle();

      drawLeftTriangle();

   }

 

   glFlush();

}

 

void reshape(int w, int h)

{

   glViewport(0, 0, (GLsizei) w, (GLsizei) h);

   glMatrixMode(GL_PROJECTION);

   glLoadIdentity();

   if (w <= h)

      gluOrtho2D (0.0, 1.0, 0.0, 1.0*(GLfloat)h/(GLfloat)w);

   else

      gluOrtho2D (0.0, 1.0*(GLfloat)w/(GLfloat)h, 0.0, 1.0);

}

 

void keyboard(unsigned char key, int x, int y)

{

   switch (key)

   {

      case 't':

      case 'T':

         leftFirst = !leftFirst;

         glutPostRedisplay();

         break;

      case 27:  /*  Escape key  */

         exit(0);

         break;

      default:

         break;

   }

}

 

//Main Loop. Open window with initial window size, title bar, RGBA display mode, and handle input events.

 

int main(int argc, char** argv)

{

   glutInit(&argc, argv);

   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

   glutInitWindowSize (200, 200);

   glutCreateWindow (argv[0]);

   init();

   glutReshapeFunc (reshape);

   glutKeyboardFunc (keyboard);

   glutDisplayFunc (display);

   glutMainLoop();

   return 0;

 

Example 2: Rotating Cubes (smaller inside a larger)

 

 

 

#include <GL/glut.h>

#include <GL/gl.h>

 

GLfloat angle = 0.0;

void cube (void)

{

   //setting the axis about which to rotate

   glRotatef(angle, 1.0, 0.0, 0.0);   //x axis

   glRotatef(angle, 0.0, 1.0, 0.0);   //y axis

   glRotatef(angle, 0.0, 0.0, 1.0);   //z axis

   glColor4f(1.0, 0.0, 0.0, 0.2);      //set the color and alpha of the larger cube

   glutSolidCube(2);                     //draw larger solid cube

   glColor4f(0.0, 1.0, 0.0, 0.5);      //set the color and alpha of the smaller cube

   glutSolidCube(1);                     //draw smaller solid cube

}

void display (void)

{

   glClearColor (0.0,0.0,0.0,1.0);     //set the background color

   glClear (GL_COLOR_BUFFER_BIT);

   glEnable(GL_BLEND); //enable the blending

   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);         //set the blend function

   glLoadIdentity();                                                                                //clear the screen before rendering

   gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);                            //camera location: 5 along positive z, positive up

   cube();                                                                                             //call the above cube function

   glutSwapBuffers();

   angle ++;                                                                                          //increment the angle by 1

}

void reshape (int w, int h)

{

   glViewport (0, 0, (GLsizei)w, (GLsizei)h);

   glMatrixMode (GL_PROJECTION);

   glLoadIdentity ();                                                                    //clear the screen before rendering

   gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);

   glMatrixMode (GL_MODELVIEW);

}

int main (int argc, char **argv)

{

   glutInit (&argc, argv);

   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);             

   glutInitWindowSize (500, 500);

   glutInitWindowPosition (100, 100);

   glutCreateWindow ("Blending Example");

   glutDisplayFunc (display);

   glutIdleFunc (display);                                                              //function to be executed if no other events are pending

   glutReshapeFunc (reshape);

   glutMainLoop ();

   return 0;

}

 

 

Exercises

 

 

Exercise 1

Exercise 2

 

 

Exercise 1

 

Change Example 1 above as follows

 

      Change the background to light blue   

      Have a Red triangle overlapping a Green sphere 

    

      Part a: Run the program for  a constant (see above) of GL_DST_COLOR with the sphere being drawn first

   

      Part b: Run the program for  a constant  GL_SRC_COLOR with the sphere being drawn first

 

      Part c: Run the program for  a constant of GL_ONE_MINUS_DST_COLOR with the triangle being drawn first

 

 

Exercise 2

 

What is the purpose of the following lines of code used in the program?

 

    glColor4f(1.0, 1.0, 0.0, 0.75);     glColor4f(0.0, 1.0, 1.0, 0.75);