blending and animation

hi,

i’m a newbie in opengl. i want to rotate an object which is transparent and within in an opaque object. i read the red book but couldn’t understand it well. could any one link me to a better explanation with a working example.

also i tried an example program of blending from superbible and i found that the transparent object rendered very slowly and the object refused to rotate as i coded.

could any one point me the error in the code. there is no compilation or linker error. i use visual studio 6(VC++).

heres the code:

#include <GL/glut.h>

static float xRot=0.0f,yRot=0.0f;

int Width; /* Width of window /
int Height; /
Height of window */

void init()
{

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

gluLookAt(0.0,0.0,15.0, 0.0, 0.0, 0.0 , 0.0,1.0,0.0);	

}

void specialKeys(int key,int x,int y)
{
if(key==GLUT_KEY_UP)
xRot +=5.0f;

if(key==GLUT_KEY_DOWN)
	xRot -= 5.0f;

if(key==GLUT_KEY_RIGHT)
	yRot += 5.0f;

if(key==GLUT_KEY_LEFT)
	yRot -= 5.0f;

if(key&lt;0.0f)
	xRot=359.0f;

if(key&gt;359.0f)
	xRot=0.0f;

if(key&gt;359.0f)
	yRot=0.0f;

if(key&lt;0.0f)
	yRot=359.0f;

glutPostRedisplay();

}

void Redraw(void);
void Resize(int width, int height);

int /* O - Exit status /
main(int argc, /
I - Number of command-line arguments */
char argv[]) / I - Command-line arguments */
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(792, 573);
glutCreateWindow(“Transparent Teapots”);
glutReshapeFunc(Resize);
glutSpecialFunc(specialKeys);
glutDisplayFunc(Redraw);
init();
glutMainLoop();
return (0);
}

void
Redraw(void)
{
static GLfloat red_light[4] = { 1.0, 0.0, 0.0, 1.0 };
static GLfloat red_pos[4] = { 1.0, 1.0, 1.0, 0.0 };
static GLfloat blue_light[4] = { 0.0, 0.0, 1.0, 1.0 };
static GLfloat blue_pos[4] = { -1.0, -1.0, -1.0, 0.0 };

/* Clear the window to black */
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/* Enable drawing features that we need... */
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);

glShadeModel(GL_SMOOTH);


glLightfv(GL_LIGHT0, GL_DIFFUSE, red_light);
glLightfv(GL_LIGHT0, GL_POSITION, red_pos);

glLightfv(GL_LIGHT1, GL_DIFFUSE, blue_light);
glLightfv(GL_LIGHT1, GL_POSITION, blue_pos);

glEnable(GL_COLOR_MATERIAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);



glPushMatrix();
glRotatef(xRot,1.0f,0.0f,0.0f);
glRotatef(yRot,0.0f,1.0f,0.0f);

glDisable(GL_BLEND);
glColor3f(1.0, 1.0, 0.0);
glutSolidTeapot(1.0);

glEnable(GL_BLEND);
glColor4f(1.0, 1.0, 1.0, 0.75);
glutSolidTeapot(2.0);
glPopMatrix();

glFinish();
}

/*

  • ‘Resize()’ - Resize the window…
    */

void
Resize(int width, /* I - Width of window /
int height) /
I - Height of window /
{
/
Save the new width and height */
Width = width;
Height = height;

/* Reset the viewport... */
glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(22.5, (float)width / (float)height, 0.1, 1000.0);
glMatrixMode(GL_MODELVIEW);
}

thanx

hi,

sorry what i meant was that i want to rotate a transparent object and within that transparent should be an opaque object. both the objects must rotate together.

What’s the problem? You see nothing aka. “Black Screen Of Death”?
Adjust your gluPerspective parameters, bigger angle, zNear = 1.0, zFar = 9.0.
Modelview matrix to
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f);

That is avoid gluLookAt in the beginning.

Your lighting and other state never changes, you could put it into the init function. Note that the light position is transformed by the current modelview matrix. You may want to specify the position while the modelview matrix is identity.
(Not necessary here, but make sure you enable GL_NORMALIZE if you scale your objects and use lighting.)

For nicer transparenecy you need to draw the opaque object first with depth buffering and depth write mask on.
Then switch on blending, set glDepthMask(GL_FALSE) to be able to compare the transparent object against the opaque, but to avoid that nearer transparent faces drawn first will reject the farer transparent ones. (You’ll see what I mean when you rotate it with your current version.)
To get a simple back to front sorting for a nicer blending you can draw the transparent teapot twice once with glCullFace(GL_FRONT) then with glCullFace(GL_BACK).

Do not set clear color alpha to 1.0, use 0.0. You don’t need it with this blending anyway.

hi,

this is a very late response from me and i apologize. well, i reconstructed the program and brought up with another code. everything fine except the blending. if i change the apha value, i get the object to be drawn in a darker shade but still not transparent. can you tell me the problem with the below code:

#include<windows.h>
#include<GL/glut.h>
#include<math.h>
#include<stdio.h>
#include"Texture.h"

static float xRot=0.0f,yRot=0.0f;
float bottom_normal[3],back_normal[3],lside_normal[3],front_normal[3],out[3];
GLfloat all_normals[12];
int i;
GLubyte *bits;
BITMAPINFO *info;

bool bp, blend;

void renderScene(void);

float bottom_vertices[][3] = { 20.0f,0.0f,0.0f , 0.0f,0.0f,60.0f , -20.0f,0.0f,0.0f};

float back_vertices[][3] = {20.0f,0.0f,0.0f , -20.0f,0.0f,0.0f , 0.0f,40.0f,30.0f};

float lside_vertices[][3] = {-20.0f,0.0f,0.0f , 0.0f,0.0f,60.0f , 0.0f,40.0f,30.0f};

float front_vertices[][3] = {0.0f,0.0f,60.0f , 20.0f,0.0f,0.0f , 0.0f,40.0f,30.0f};

void setupRC()
{

glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);

bits = (GLubyte*)TextureLoadBitmap("pyramid.bmp");

GLfloat ambient[] = {0.3f,0.3f,0.3f,1.0f};
GLfloat diffuse[] = {0.7f,0.7f,0.7f,0.0f};
GLfloat specular[]= {1.0f,1.0f,1.0f,1.0f};
GLfloat specRef[] = {1.0f,1.0f,1.0f,1.0f};
GLfloat	lightPos[] = { -50.f, 50.0f, 100.0f, 1.0f };

glEnable(GL_LIGHTING);

glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);

glEnable(GL_COLOR_MATERIAL);

glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

glMaterialfv(GL_FRONT,GL_SPECULAR,specRef);;
glMateriali(GL_FRONT,GL_SHININESS,128);


glShadeModel(GL_SMOOTH);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);

//glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
ShowCursor(FALSE);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

//glColor4f(1.0f, 1.0f, 1.0f, 0.5);
//glBlendFunc(GL_SRC_ALPHA,GL_ONE);
	


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glOrtho(-30.0f,30.0f,-10.0f,60.0f,-100.0f,100.0f);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();


glClearColor(0.0f,0.0f,0.0f,0.0f);

}

void calcUnitNormals(float out[3])
{
float length;

length = (float)sqrt((out[0]*out[0]) + (out[1]*out[1]) + (out[2]*out[2]));

if(length==0.0f)
	length=1.0f;

out[0] /= length;
out[1] /= length;
out[2] /= length;

//printf("norm0: %f 

norm1: %f
norm2: %f
",out[0],out[1],out[2]);
}

void calcNormals(GLfloat v[3][3],GLfloat out[3])
{

GLfloat v1[3],v2[3];
static const int x=0,y=1,z=2;

v1[x] = v[0][x] - v[1][x];
v1[y] = v[0][y] - v[1][y];
v1[z] = v[0][z] - v[1][z];

v2[x] = v[1][x] - v[2][x];
v2[y] = v[1][y] - v[2][y];
v2[z] = v[1][z] - v[2][z];

out[x] = v1[y]*v2[z] - v2[y]*v1[z];
out[y] = v1[z]*v2[x] - v1[x]*v2[z];
out[z] = v1[x]*v2[y] - v1[y]*v2[x];

calcUnitNormals(out);

}

void specialKeys(int key,int x,int y)
{
if(key==GLUT_KEY_UP)
xRot +=5.0f;

if(key==GLUT_KEY_DOWN)
	xRot -= 5.0f;

if(key==GLUT_KEY_RIGHT)
	yRot += 5.0f;

if(key==GLUT_KEY_LEFT)
	yRot -= 5.0f;

if(key&lt;0.0f)
	xRot=359.0f;

if(key&gt;359.0f)
	xRot=0.0f;

if(key&gt;359.0f)
	yRot=0.0f;

if(key&lt;0.0f)
	yRot=359.0f;

glutPostRedisplay();

}

/*void combineNormals(float xNormal[])
{
static int x=0;

	for(int i=0;i&lt;=2;i++)
	{
		all_normals[x] = xNormal[i];
		x=x+1;
	}

}*/

void keyboard(unsigned char key, int x, int y)
{printf(“within function”);
switch(key)
{
case 27:
exit(0);
break;

case 'b':
	blend = TRUE;

	if(blend)
	{
		printf("this is in blen");
	
		glEnable(GL_BLEND);			// Turn Blending On
		glDisable(GL_DEPTH_TEST);	// Turn Depth Testing Off
		blend = !blend;	
	}
	else
	{
		glDisable(GL_BLEND);		// Turn Blending Off
		glEnable(GL_DEPTH_TEST);	// Turn Depth Testing On
		blend = !blend;	
	}
  break;
  	
default:        // Now Wrap It Up
  break;
	
}

}

void renderScene()
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColor4f(1.0f, 1.0f, 1.0f, 0.2);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
glDepthMask(GL_FALSE);

glEnable(GL_TEXTURE_2D);
glTexImage2D(GL_TEXTURE_2D,0,3,256,256,0,GL_RGBA,GL_UNSIGNED_BYTE,bits);


GLfloat pyramid_vertex_colors[][3] = {{1.0f,0.0f,0.0f},
{0.0f,1.0f,0.0f},
{0.0f,0.0f,1.0f},

{1.0f,1.0f,0.0f},
{1.0f,0.0f,1.0f},
{0.0f,1.0f,1.0f},

{0.25f,0.25f,0.25f},
{0.75f,0.75f,0.75f},
{0.60f,0.40f,0.12f},

{0.98f,0.625f,0.12f},
{0.98f,0.04f,0.7f},
{0.60f,0.40f,0.70f}};



glPushMatrix();
glRotatef(xRot,1.0f,0.0f,0.0f);
glRotatef(yRot,0.0f,1.0f,0.0f);

//glColor3ub(128,128,128);			
glBegin(GL_TRIANGLES);

calcNormals(bottom_vertices,out);




// Bottom Triangle
glNormal3fv(out);
glTexCoord2f(1.0f,0.0f);
glVertex3fv(bottom_vertices[0]);
glTexCoord2f(0.5f,1.0f);
glVertex3fv(bottom_vertices[1]);
glTexCoord2f(0.0f,0.0f);
glVertex3fv(bottom_vertices[2]);


calcNormals(back_vertices,back_normal);
/*for(int j=0;j&lt;=2;j++);
printf("back_normal: %f

",back_normal[j]);*/

// Back triangle
glNormal3fv(back_normal);
glTexCoord2f(0.0f,0.0f);
glVertex3fv(back_vertices[0]);
glTexCoord2f(1.0f,0.0f);
glVertex3fv(back_vertices[1]);
glTexCoord2f(0.5f,1.0f);
glVertex3fv(back_vertices[2]);


calcNormals(lside_vertices,lside_normal);
/*for(int k=0;k&lt;=2;k++);
printf("lside_normal: %f

",lside_normal[k]);*/

//LSide triangle
glNormal3fv(lside_normal);
glTexCoord2f(0.0f,0.0f);
glVertex3fv(lside_vertices[0]);
glTexCoord2f(1.0f,0.0f);
glVertex3fv(lside_vertices[1]);
glTexCoord2f(0.5f,1.0f);
glVertex3fv(lside_vertices[2]);


calcNormals(front_vertices,front_normal);
/*for(int l=0;l&lt;=2;l++);
printf("front_normal: %f

",front_normal[l]);*/

glNormal3fv(front_normal);
glTexCoord2f(0.0f,0.0f);
glVertex3fv(front_vertices[0]);
glTexCoord2f(1.0f,0.0f);
glVertex3fv(front_vertices[1]);
glTexCoord2f(0.5f,1.0f);
glVertex3fv(front_vertices[2]);

glEnd();

glDisable(GL_TEXTURE_2D);

glPopMatrix();

glutSwapBuffers();

}

void changeSize(GLsizei w, GLsizei h)
{
glViewport(0,0,w,h);

if(h==0)
	h=1;

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho(-30.0f,30.0f,-10.0f,60.0f,-100.0f,100.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

}

void main()
{
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(“Hello”);
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutSpecialFunc(specialKeys);
glutKeyboardFunc(keyboard);
setupRC();

glutMainLoop();

}

thanx a lot

You have to draw the opaque object first. This is a common misunderstanding, but OpenGL can’t just tuck the opaque object under a translucent object it’s already drawn. There are papers about how things like this could be done, but it’s surprisingly non-trivial.

hi,

thanx, i got it to work