PDA

View Full Version : Yet Another Blending Question.



Spock
12-05-2008, 07:57 PM
Hi Everybody! :D

Heres a slight variation of the common blending question.

Im working with 2D only, and need some simple colour descriminant transparancy. Thats is, anything on a texture that is of colour, say (1.0, 1.0, 1.0)RGB becomes transparent. Is this possible?

...And if so, who do I implement this? -Ive been looking over the glBlendFunc and its options, but a lot of the documentation is over my head, or just not applicable. My textures do not have an alpha channel..

Thank you!

trinitrotoluene
12-05-2008, 08:23 PM
Thats is, anything on a texture that is of colour, say (1.0, 1.0, 1.0)RGB becomes transparent. Is this possible?

Yes,you can convert the RGB texture to a RGBA texture.



//Convert an RGB image to RGBA (GL_UNSIGNED_BYTE data type)
for( j = 0, k = 0,l = 0 ; j < sizeY ; j++)
{
for( i = 0 ; i < sizeX ; i++)
{
//Transparent
if( (rgb_image[k] == 255) &amp;&amp; (repeat for green and blue component))
{
rgba_image[l++] = rgb_image[k++];
rgba_image[l++] = rgb_image[k++];
rgba_image[l++] = rgb_image[k++];
rgba_image[l++] = 0;
}
else //opaque
{
rgba_image[l++] = rgb_image[k++];
rgba_image[l++] = rgb_image[k++];
rgba_image[l++] = rgb_image[k++];
rgba_image[l++] = 255;
}
}
}


Try with the following blending equation glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA). For texture wrap mode use GL_CLAMP_TO_EDGE for S and T.

ZbuffeR
12-06-2008, 02:02 AM
If you see a slight white border around your sprites, come back here for ways to solve this.

Spock
12-06-2008, 05:25 AM
Right-o, will try this now...

Thank you very much for the quick reply!! :)

Spock
12-06-2008, 07:29 AM
Hmmm, well I store my data as char, so that doesnt seem to work :s

-- even with (char) type coercion

zeoverlord
12-06-2008, 08:12 AM
it should, GLubyte is basically char, if you can't convert, then you have to make both of them the same type.

Spock
12-06-2008, 10:19 AM
Okay, check mah code, and your right, works better now :)

However, there still isnt any transparency :s



/* reverse colours */
for ( i=0; i< size; i+=3 )
{
temp = data[i];
data[i] = data[i+2];
data[i+2] = temp;
}

/* white - transparent conversion */
for( i=0, l=0, k=0; i<globuiHeight; i ++ )
{
for( j=0; j<globuiWidth; j ++ )
{
if(( data[l] == (GLubyte)256 )&amp;&amp;( data[l+1] == (GLubyte)256 )&amp;&amp;( data[l+2] == (GLubyte)256 ))
{
dataRGBA[k++] = (GLubyte)data[l++]; //R
dataRGBA[k++] = (GLubyte)data[l++]; //G
dataRGBA[k++] = (GLubyte)data[l++]; //B
dataRGBA[k++] = (GLubyte)0; //A
} else {
dataRGBA[k++] = (GLubyte)data[l++];
dataRGBA[k++] = (GLubyte)data[l++];
dataRGBA[k++] = (GLubyte)data[l++];
dataRGBA[k++] = (GLubyte)256;
}
}
}

....

gluBuild2DMipmaps( GL_TEXTURE_2D, 4, globuiWidth, globuiHeight, GL_RGBA, GL_UNSIGNED_BYTE, dataRGBA );


Hope this makes it easier, where am I going wrong?

Thanks guys :)

Rosario Leonardi
12-06-2008, 10:42 AM
if(( data[l] == (GLubyte)256 )&amp;&amp;( data[l+1] == (GLubyte)256 )&amp;&amp;( data[l+2] == (GLubyte)256 ))
255.. not 256. :)

256 is a number on 9 bit.

Spock
12-06-2008, 11:05 AM
Haha! what a basic mistake, yhea, cant belive I didnt spot that! :p

Still no transparency though :(

..If it did work, would I see the texure drawn before the transparent one? - in effect 'behind it', or just the colour of the primitive that textures bound to?

Atm, im just still seeing the white... :(

trinitrotoluene
12-06-2008, 11:18 AM
Do you enable blending with glEnable(GL_BLEND)? Can you post some source code to see if your texture setting is right.



If it did work, would I see the texure drawn before the transparent one? - in effect 'behind it', or just the colour of the primitive that textures bound to?

See this thread (http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Main=48618&Number=249937) for an example with transparency texture. Look at the screen shot.

zeoverlord
12-06-2008, 02:23 PM
a quick test to see if transparency and blending is working, set the color to (1,1,1,0.3), if it goes transparent then the blending mode works.
In that case it's the whole creation of the texture that doesn't.
My guess would be that the internal format (the second parameter in gluBuild2DMipmaps and third in glTexImage2D) is set to GL_RGB or 3, make sure it says GL_RGBA.

Spock
12-09-2008, 11:26 AM
Hmm... Thanks for the links and color test advise. It seems that after attempting it, its the whole texture creating process that doesnt work! :s

Ive tried via extensive use of printf(); 's to get down to what im doing wrong, but everything seems to be working right, format loaded correctly, and all variables go to the right values, except this part.

Heres the code for my load image function, its quite long, but silly simple :p



GLuint globLoadImage( char* globsFileName, unsigned int globuiWidth, unsigned int globuiHeight, int globiTrans )
{
/*Some nice var */
FILE *imageFile;
GLubyte *data, *dataRGBA; /* Holds data, as we load it. &amp;One for transparency */
unsigned long size, i, j, k, l; /* For da claculizzle */
unsigned short int planes; /* number of planes in image (must be 1) */
unsigned short int bpp; /* number of bits per pixel (must be 24) */
unsigned int chkDimension; /* Var to check dimensions & make sure standard */
char temp; /* temporary color storage for bgr-rgb conversion. */
GLuint texture; /* holds the texture ID that we send back. */

/* does file exist? */
if(( imageFile = fopen( globsFileName, "rb" )) == NULL )
{
globLog( "[globLoadImage@globEng]: File Not Found! %s \n\
Does it exist?\n", globsFileName );
return FALSE; //Cant go any further tbh
}

/* get width height from header, seek to. */
fseek( imageFile, 18, SEEK_CUR );

if(( i = fread( &amp;chkDimension, 4, 1, imageFile )) != TRUE )
{
globLog( "[globLoadImage@globEng]: Error reading width of: %s \n\
File could be corrupt.\n", globsFileName );
return FALSE;
}
if( chkDimension != globuiWidth )
{
globLog( "[globLoadImage@globEng]: Wrong image width: is %d, should be %u; from %s\n",
chkDimension, globuiWidth, globsFileName );

return FALSE;
}

if(( i = fread( &amp;chkDimension, 4, 1, imageFile )) != TRUE )
{
globLog( "[globLoadImage@globEng]: Error reading height of: %s \n\
File could be corrupt.\n", globsFileName );
return FALSE;
}
if( chkDimension != globuiHeight )
{
globLog( "[globLoadImage@globEng]: Wrong image height: is %d, should be %u; from %s\n",
chkDimension, globuiHeight, globsFileName );

return FALSE;
}
printf( "Dimensions: %ux%u\n", globuiWidth, globuiHeight );

/* Get the # planes from file */
if(( i = fread( &amp;planes, 2, 1, imageFile )) != TRUE)
{
globLog( "[globLoadImage@globEng]: Unable to read #planes from: %s \n\
File could be corrupt.\n", globsFileName );
return FALSE;
}
if( planes != 1 ) /* check for errors */
{
globLog( "[globLoadImage@globEng]: Planes not 1 in: %s", globsFileName );
return FALSE;
}

/* And now bbp data */
if(( i = fread( &amp;bpp, 2, 1, imageFile )) != TRUE )
{
globLog( "[globLoadImage@globEng]: Could not read bpp from %s\n\
File could be corrupt.", globsFileName );
return FALSE;
}
if( bpp != 24 )
{
globLog( "[globLoadImage@globEng]: Invalid bpp (!24) in: %s\n\
File could be corrupt.", globsFileName );
return FALSE;
}

/* Get to the data, allocate memory and load :) */
fseek( imageFile, 24, SEEK_CUR );

/* Calculate image size, */
size = globuiWidth * globuiHeight * (bpp/8);
data = ( GLubyte* ) malloc( size );
i = globuiWidth * globuiHeight * (32/8);
dataRGBA = ( GLubyte* ) malloc( i );

printf( "bpp: %d bits or %d bytes, size: %d \n", bpp, bpp/8, size );
if(( data == NULL )||( dataRGBA == NULL )) //Has it worked?
{
globLog( "[globLoadImage@globEng]: Could not allocate memory for image.\n" );
return FALSE;
}

if (( i = fread( data, size, 1, imageFile )) != 1 )
{
globLog( "[globLoadImage@globEng]: Error reading image data from %s.\n", globsFileName );
return FALSE;
}

/* reverse colours */
for ( i=0; i< size; i+=3 )
{
temp = data[i];
data[i] = data[i+2];
data[i+2] = temp;
}

if( globiTrans ) /* If transparency conversion, white == transparent */
{
for( i=0, l=0, k=0; i<globuiHeight; i++ )
{
for( j=0; j<globuiWidth; j++ )
{
if(( data[l] > 200 )&amp;&amp;( data[l+1] > 200 )&amp;&amp;( data[l+2] > 200 ))
{
printf( " :: %lu, %lu, %lu, %lu", i, j, k, l );
dataRGBA[k++] = data[l++]; //R
dataRGBA[k++] = data[l++]; //G
dataRGBA[k++] = data[l++]; //B
dataRGBA[k++] = 0; //A
} else {
dataRGBA[k++] = data[l++];
dataRGBA[k++] = data[l++];
dataRGBA[k++] = data[l++];
dataRGBA[k++] = 255;
}
}
}
} else { /* Otherwise, build RGBA image anyway, but full alpha ;P */
for( i=0, l=0, k=0; i<globuiHeight; i++ )
{
for( j=0; j<globuiWidth; j++ )
{
dataRGBA[k++] = data[l++];
dataRGBA[k++] = data[l++];
dataRGBA[k++] = data[l++];
dataRGBA[k++] = 255;
}
}
}

/*
* And now convert to GL texture, straight away
*/
glGenTextures( 1, &amp;texture );
glBindTexture( GL_TEXTURE_2D, texture );

/* Set up environement var, tweak these, want white == transparent I say :D */
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

/* And now, finally build it */
gluBuild2DMipmaps( GL_TEXTURE_2D, 4, globuiWidth, globuiHeight, GL_RGBA, GL_UNSIGNED_BYTE, dataRGBA );
//glTexImage2D( GL_TEXTURE_2D, 0, 4, globuiWidth, globuiHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, dataRGBA );

free( data );
free( dataRGBA );

return texture;
}

trinitrotoluene
12-09-2008, 03:34 PM
but everything seems to be working right, format loaded correctly, and all variables go to the right values, except this part.
I have tried your code and it work well. I have made minor modification like changing min and mag filter mode to take advantage of mipmap.

Try with the following drawing function:


GLvoid display(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL _STENCIL_BUFFER_BIT);

glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,texID);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_REPLACE);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0,0.0);
glVertex4f(-1.0,-1.0,0.0,1.0);
glTexCoord2f(1.0,0.0);
glVertex4f(1.0,-1.0,0.0,1.0);
glTexCoord2f(0.0,1.0);
glVertex4f(-1.0,1.0,0.0,1.0);
glTexCoord2f(1.0,1.0);
glVertex4f(1.0,1.0,0.0,1.0);
glEnd();

glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glutSwapBuffers();
}

Spock
12-10-2008, 09:44 AM
Hehe :D

Thanks, I tried it, but to no avail, however, then after Ctrl-Z ing back to original code I got it working! :)

Not sure how really... The code though is _exactly_ the same as my original! heh :D

Thank you anyhow!