The problem is that glBlend allows backside polygons to be seen so to stop the problem of seeing a ghost image of the back surface thru the cylinder backface culling had to be enabled – causing you to see half the cylinder. One way around that is to generate the mixed texture on a flat rectangle FIRST then copy that texture to be mapped on the cylinder later.
Step 1 generate mixed texture logoM (see new function CreateMultiTexture())
Step 2 use logoM without blending mapped onto the cylinder
// on linux with gcc: gcc main.c -lGL -lglut -lIL -lGLEW
// on win+mingw: gcc main8.c -lglut32 -lglu32 -lopengl32 -lwinmm -lgdi32 -lglew32 -lIL -L/usr/local/lib -I/usr/local/include
//
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <IL/il.h>
GLfloat gAngle = 0.0;
GLUquadricObj *IDquadric;
GLuint gState = 0;
struct TextureHandle
{
ILubyte *p;
ILuint id;
ILint w;
ILint h;
ILenum DestFormat;
ILenum DestType;
GLuint genID;
};
struct TextureHandle logo;
struct TextureHandle logo2;
struct TextureHandle logoM;
ILuint LoadImageDevIL (const char *szFileName, struct TextureHandle *T)
{
ilEnable(IL_ORIGIN_SET);
ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
ILuint ImageNameID;
ilGenImages(1, &ImageNameID);
ilBindImage(ImageNameID);
if (!ilLoadImage(szFileName)) return 0;
ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
T->id = ImageNameID;
T->p = ilGetData();
T->w = ilGetInteger(IL_IMAGE_WIDTH);
T->h = ilGetInteger(IL_IMAGE_HEIGHT);
T->DestFormat = ilGetInteger(IL_IMAGE_FORMAT);
T->DestType = ilGetInteger(IL_IMAGE_TYPE);
glGenTextures(1, &T->genID);
glBindTexture(GL_TEXTURE_2D, T->genID);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, T->DestFormat, T->w, T->h, 0, T->DestFormat, T->DestType, T->p);
printf("%s %d %d %d
",szFileName,T->id,T->w,T->h);
return 1;
}
void timer(int value)
{
const int desiredFPS=120;
glutTimerFunc(1000/desiredFPS, timer, ++value);
GLfloat dt = 1./desiredFPS;
gAngle += dt*360./8.;
glutPostRedisplay();
}
void draw_cylinder()
{
glPushMatrix();
glTranslatef(-5.,0,-100);
glRotatef(gAngle,1.,1.,0.);
gluCylinder(IDquadric,10.0f,10.0f,10.0f,32,32);
glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
if (gState) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR,GL_DST_COLOR);
//glBlendFunc (GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
glBlendColor(.5,.5,.5,.5); // set blend constants to 0.5
glBindTexture ( GL_TEXTURE_2D, logo.genID);
draw_cylinder();
glBindTexture ( GL_TEXTURE_2D, logo2.genID);
draw_cylinder();
glDisable(GL_BLEND);
} else {
glBindTexture ( GL_TEXTURE_2D, logoM.genID);
draw_cylinder();
}
glutSwapBuffers();
}
void CreateMultiTexture()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// store values to return to when done
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
// Temporarily set Viewport to Match Texture Size
glViewport(0,0,logoM.w,logoM.h);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR,GL_DST_COLOR);
//glBlendFunc (GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
glBlendColor(.5,.5,.5,.5);
glBindTexture ( GL_TEXTURE_2D, logo.genID);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex2f(-1,-1);
glTexCoord2f(1,0); glVertex2f( 1,-1);
glTexCoord2f(1,1); glVertex2f( 1, 1);
glTexCoord2f(0,1); glVertex2f(-1, 1);
glEnd();
glBindTexture ( GL_TEXTURE_2D, logo2.genID);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex2f(-1,-1);
glTexCoord2f(1,0); glVertex2f( 1,-1);
glTexCoord2f(1,1); glVertex2f( 1, 1);
glTexCoord2f(0,1); glVertex2f(-1, 1);
glEnd();
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D,logoM.genID); // Bind To The Mixed Texture
// Copy mixed texture to logoM
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, logoM.w, logoM.h, 0);
// Finally, logoM is now 0.5*logo + 0.5*logo2
//return to state before generating mixed texture
glViewport(viewport[0], viewport[1], viewport[2] ,viewport[3]);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glutSwapBuffers();
glutDisplayFunc(display); // now that you have mixed texture, do real display
}
void cleanupQuadric(void)
{
gluDeleteQuadric(IDquadric);
printf( "cleanupQuadric completed
" );
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
//glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
IDquadric=gluNewQuadric();
gluQuadricNormals(IDquadric, GLU_SMOOTH);
gluQuadricTexture(IDquadric, GL_TRUE);
atexit(cleanupQuadric);
GLdouble Vol = 10*1.8;
GLdouble Left=-Vol;
GLdouble Right=Vol;
GLdouble Bottom=-Vol;
GLdouble Top=Vol;
GLdouble Near=0;
GLdouble Far=2*Vol;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(Left, Right, Bottom, Top, Near, Far);
GLdouble eyeX=0;
GLdouble eyeY=0;
GLdouble eyeZ=-100+Vol;
GLdouble centerX=0;
GLdouble centerY=0;
GLdouble centerZ=-100;
GLdouble upX=0;
GLdouble upY=1;
GLdouble upZ=0;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX,eyeY,eyeZ,
centerX,centerY,centerZ,
upX,upY,upZ);
ilInit();
//LoadImageDevIL ("/localhome/user/Temp/sample/bird.bmp", &logo);
LoadImageDevIL ("logo.jpg", &logo);
LoadImageDevIL ("logo.jpg", &logoM); // make room for Multi-texture
LoadImageDevIL ("logo2.jpg", &logo2);
glEnable (GL_TEXTURE_2D);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
default:
gState++;
gState %= 2;
printf("%d
",gState);
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH);
glutCreateWindow("Multipass texturing Demo");
glewInit();
glutTimerFunc(0,timer,0);
glutDisplayFunc(CreateMultiTexture);
glutKeyboardFunc(keyboard);
init();
glutMainLoop();
return 0;
}