|
| We are what we repeatedly do. |
| Excellence, then, is not an act, but a habit. |
| Aristotle |
then the alpha value will have meaning.
0 -- material completely transparent and cannot be seen
|
|
|
|||||||||||||||||||||
| destination color | = | ( Rd, Gd, Bd, Ad ) |
| polygon color | = | ( Rs, Gs, Bs, As ) |
| destination factor | = | ( Dr, Dg, Db, Da ) |
| source factor | = | ( Sr, Sg, Sb, Sa ) |
The blended color ( new destination color ) is
Each component is clamped to [0,1].
used to generate blending factors
| 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 in Table 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]. |
| void glBlendFuncSeparate(GLenum srcRGB, GLenum destRGB, GLenum srcalpha, GLenum destalpha ); |
| Still use the table below but blending factors of RGB and A are considered separately. |
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 | destination | (Rd, Gd, Bd, Ad) |
GL_SRC_COLOR | source | (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_ALPHA | 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_ALPHA | 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) |
GL_CONSTANT_COLOR |
source or destination |
( Rc, Gc, Bc, Ac ) |
GL_CONSTANT_ALPHA |
source or destination |
( Ac, Ac, Ac, Ac ) |
If you are using one of the GL*CONSTANT* blending functions, you need to use glBendColor() to specify the constant colors.
| void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); |
| Sets the current red, green, blue and alpha values for use as the constant color ( Rc, Gc, Bc, Ac ) in blending operations. |
Example: When we draw polygonal surfaces, the most common
choices for the source and destination factors are GL_SRC_ALPHA
and ONE_MINUS_SRC_ALPHA respectively.
Consider initially,
color of polygon to be blended = ( Rs, Gs, Bs, As )
Class exercise: What will be the resulted rendered destination color D?
Answer:
| D | = |
( AsRs +
( 1 - As)Rc,
AsGs +
( 1 - As)Gc,
AsBs + ( 1 - As)Bc, As2 + ( 1 - As)Ac ) |
| = | ( Rd, Gd, Bd, Ad ) |
| void glBlendEquation( GLenum mode ); |
|
Specifies how framebuffer and source colors are blended together.
GL_FUNC_ADD ( default ), GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MIN, GL_MAX |
|
Draw yellow triangle first.
Draw blue triangle first. |
blending factors are 0.75 ( source ) and 1 - 0.75 = 0.25 ( destination ),
because blending factor of source is larger, it has more effect on
the final color than do the destination color
When drawing three-dimensional translucent objects, you can get different appearances depending on whether you draw the polygons from back to front or from front to back.
To simplify rendering process, we enable depth buffering but make the depth buffer read-only ( controlled by glDepthMask() while drawing the translucent objects:
|
|
aliasing -- the jaggedness that appears when approximating an ideal line by a series of pixels that must lie on the pixel grid.
|
|
To turn on antialiasing
Use glHint() to provide a quality hint:
| void glHint(GLenum target, GLenum hint); |
| Controls certain aspects of OpenGL behavior. The target parameter indicates which behavior is to be controlled; its possible values are shown in Table below. The hint parameter can be GL_FASTEST to indicate that the most efficient option should be chosen, GL_NICEST to indicate the highest-quality option, or GL_DONT_CARE to indicate no preference. The interpretation of hints is implementation-dependent; an implementation can ignore them entirely. |
Parameter | Meaning |
|---|---|
GL_POINT_SMOOTH_HINT, GL_LINE_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT | Specify the desired sampling quality of points, lines, or polygons during antialiasing operations |
GL_FOG_HINT | Specifies whether fog calculations are done per pixel (GL_NICEST) or per vertex (GL_FASTEST) |
GL_PERSPECTIVE_CORRECTION_HINT | Specifies the desired quality of color and texture-coordinate interpolation |
Example: Antialiased Lines
|
|
You can use fog to make an entire image appear more natural by adding fog, which makes object fade into the distance.
Using the fog effect on points and lines is also called depth-cuing.
Enabled by
Fog blends a fog color with an object's color using a blending factor f ( in [0,1] ) computed according to:
| f = | e -(density . z ) | ( GL_EXP ) | |
| f = | e -(density . z )2 | ( GL_EXP2 ) | |
| f = | end - z
end - start |
( GL_LINEAR ) |
where z = distance between viewpoint and object
If Cf = color of fog, Ci = color of object, the final blended color is given by
|
void glFog{if}(GLenum pname, TYPE param);
void glFog{if}v(GLenum pname, TYPE *params); |
| Sets the parameters and function for calculating fog. If pname is GL_FOG_MODE, then param is either GL_EXP (the default), GL_EXP2, or GL_LINEAR to select one of the three fog factors. If pname is GL_FOG_DENSITY, GL_FOG_START, or GL_FOG_END, then param is (or points to, with the vector version of the command) a value for density, start, or end in the equations. (The default values are 1, 0, and 1, respectively.) In RGBA mode, pname can be GL_FOG_COLOR, in which case params points to four values that specify the fog's RGBA color values. The corresponding value for pname in color-index mode is GL_FOG_INDEX, for which param is a single value specifying the fog's color index. |
Example: Five fogged spheres
//fog.cpp
#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
static GLint fogMode;
static void init(void)
{
GLfloat position[] = { 0.5, 0.5, 3.0, 0.0 };
glEnable(GL_DEPTH_TEST);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
{
GLfloat mat[3] = {0.1745, 0.01175, 0.01175};
glMaterialfv (GL_FRONT, GL_AMBIENT, mat);
mat[0] = 0.61424; mat[1] = 0.04136; mat[2] = 0.04136;
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat);
mat[0] = 0.727811; mat[1] = 0.626959; mat[2] = 0.626959;
glMaterialfv (GL_FRONT, GL_SPECULAR, mat);
glMaterialf (GL_FRONT, GL_SHININESS, 0.6*128.0);
}
glEnable(GL_FOG);
{
GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1.0};
fogMode = GL_EXP;
glFogi (GL_FOG_MODE, fogMode);
glFogfv (GL_FOG_COLOR, fogColor);
glFogf (GL_FOG_DENSITY, 0.35);
glHint (GL_FOG_HINT, GL_DONT_CARE);
glFogf (GL_FOG_START, 1.0);
glFogf (GL_FOG_END, 5.0);
}
glClearColor(0.5, 0.5, 0.5, 1.0); /* fog color */
}
static void renderSphere (GLfloat x, GLfloat y, GLfloat z)
{
glPushMatrix();
glTranslatef (x, y, z);
glutSolidSphere(0.4, 60, 60);
glPopMatrix();
}
/* display() draws 5 spheres at different z positions.
*/
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderSphere (-2., -0.5, -1.0);
renderSphere (-1., -0.5, -2.0);
renderSphere (0., -0.5, -3.0);
renderSphere (1., -0.5, -4.0);
renderSphere (2., -0.5, -5.0);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-2.5, 2.5, -2.5*(GLfloat)h/(GLfloat)w,
2.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho (-2.5*(GLfloat)w/(GLfloat)h,
2.5*(GLfloat)w/(GLfloat)h, -2.5, 2.5, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case `f':
case `F':
if (fogMode == GL_EXP) {
fogMode = GL_EXP2;
printf ("Fog mode is GL_EXP2\n");
}
else if (fogMode == GL_EXP2) {
fogMode = GL_LINEAR;
printf ("Fog mode is GL_LINEAR\n");
}
else if (fogMode == GL_LINEAR) {
fogMode = GL_EXP;
printf ("Fog mode is GL_EXP\n");
}
glFogi (GL_FOG_MODE, fogMode);
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard);
glutDisplayFunc (display);
glutMainLoop();
return 0;
}
|
GL_EXP
GL_EXP2
GL_LINEAR
F( x, y ) = 0
Examples:
Straight line:
Ax + By + C = 0
F(x, y ) = Ax + By + C
Circle:
F(x, y) = x2 + y2 - R2
Parabola:
F(x, y) = y2 - 4ax
F(x, y) is also called inside-out function because:
F(x, y) > 0 for all ( x, y ) outside the curve
F(x, y) < 0 for all ( x, y ) inside the curve
based on the value of a parameter, e.g. time t
Exmples:
Straight line:
x(t) = a + bt
y(t) = c + dt
P(t) = ( x(t), y(t) )
Circle:
x(t) = cos ( t )
y(t) = sin ( t )
P(t) = ( x(t), y(t) )
Parabola:
x(t) = at2
y(t) = 2at
P(t) = ( x(t), y(t) )
For surfaces:
Implicit:
e.g. Sphere:
Parametric:
e.g. Sphere:
P( θ, φ ) = [ x(θ, φ), y(θ, φ), z(θ, φ ]
The normal is given by
|
∂P(s,t)
∂ s |
x |
∂P(s,t)
∂ t |
where
|
∂P(s,t)
∂ s |
= [ |
∂x(s,t)
∂ s |
, |
∂y(s,t)
∂ s |
, |
∂z(s,t)
∂ s |
] |
|
∂P(s,t)
∂ t |
= [ |
∂x(s,t)
∂ t |
, |
∂y(s,t)
∂ t |
, |
∂z(s,t)
∂ t |
] |
Example: P(s, t) = [s2, t3, 3 - st ]
We have
|
∂P(s,t)
∂ s |
= [ 2s, 0, -t] |
|
∂P(s,t)
∂ t |
= [ 0, 3t2, -s] |
| normal N = |
∂P(s,t)
∂ s |
x |
∂P(s,t)
∂ t |
= | [ 3t3, 2s2, 6st2 ]
|
If you want to highlight the edges of a solid object, you might try to draw the object with polygon mode GL_FILL and then draw it again, but in a different color with polygon mode GL_LINE. However, because lines and filled polygons are not rasterized in exactly the same way, the depth values generated for pixels on a line are usually not the same as the depth values for a polygon edge, even between the same two vertices. The highlighting lines may fade in and out of the coincident polygons, which is sometimes called .stitching. and is visually unpleasant.
The visual unpleasantness can be eliminated by using polygon offset, which adds an appropriate offset to force coincident z values apart to cleanly separate a polygon edge from its highlighting line.
You can either add a positive offset to the solid object ( push it away from you) or a negative offset to the wireframe (pull it towards you).
| void glPolygonOffset(GLfloat factor, GLfloat units); |
When enabled, the depth value of each fragment is added to a calculated offset value. The offset is added before the depth test is performed and before the depth value is written into the depth buffer. The offset value o is calculated by:
|
| depth of polygon slope m = | max | { | | |
∂P(s,t)
∂ s |
| | , | | |
∂P(s,t)
∂ t |
| | } |
For polygons that are parallel to the near and far clipping planes,
m = 0 . For the polygons in your scene with m near zero,
only a small, constant offset is needed. To create a small, constant offset,
you can pass factor=0.0 and units=1.0 to glPolygonOffset().
i.e. use glPolygonOffset( 0.0, 1.0 );
For polygons that are at a great angle to the clipping planes,
the depth slope can be significantly greater than zero,
and a larger offset may be needed. Small, non-zero values for factor,
such as 0.75 or 1.0, are probably enough to generate distinct depth values
and eliminate the unpleasant visual artifacts.
e.g.. use glPolygonOffset( 0.75, 1.0 );