Sign in to follow this  
Bozebo

OpenGL Am I blending this correctly?

Recommended Posts

I am in the process of learning OpenGL. I have been using various resources (including the outdated NeHe tutorials - which are a good way to start otherwise I would not know how things used to work from the correct perspective) to figure everything out. At the moment I have a basic understanding of texturing, vertex manipulation and a few other vital techniques. My next step is to get to grips with blending: So, I took a look at the particles example which is nice looking and I understand what it is doing, but my problem is that it only blends properly with a black background. So, I took a look at the next tutorial which shows off masking. Now I have essentially got a circular gradiented disk which I can have blended infront of a textured/coloured opaque surface correctly, good. But to do so I need 2 textures and have to do a double pass as NeHe's masking tutorial does. Now, is that not bad practice? Shouldn't I be looking at other blending methods to get the job done, and if so can somebody point me in the right direction? I have had a play with the different values for glBlendFunc but I can't get it to appear correctly without a double pass like NeHe did. I am aware I could modify my texture loading routine to create a mask for the image, which would solve the problem of 2 source bitmaps but I want to understand fully what is going on so I can learn at a more stable rate and get to grips with things before I delve into the world of fragment shaders and other more complicated operations. Take a look at my current source (devcpp project, but it shouldn't be hard to get it working fine in something else). Tanks for your time so far.

Share this post


Link to post
Share on other sites
Try using glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). I think NeHe uses GL_ONE for destination blending, as otherwise you can get artifacts when particles aren't drawn in front to back order. It also depends on what effect you want to achieve. Explosions etc. often look good with additive blending (GL_ONE), as everything gets brighter where particle density is higher.

Share this post


Link to post
Share on other sites
I am not trying to freeload code off people or anything, but this is my frame's drawing code.

I tried a few adjustments and couldn't get any results I was happy with.

I tried having single pass with various different blending methods, none of them ended up looking correct while over the opaque background geometry, though a few had nice effects when over the black background. With double pass I tend to end up with bad looking blending unless I stick to GL_DST_COLOR,GL_ZERO for the mask and


//start of frame

//object step code etc

//enter the drawing phase
//clear the screen and z-buffer
GL_clear();

//draw events
glLoadIdentity();

//camera
//glTranslatef(0,-16,-128); (this is the same as -camera.x etc, just added a class to it below for ease)

//not working with the frustum yet, I will leave that for another time

glTranslatef(-camera.x,-camera.y,-camera.z); //basic camera implementation
glRotatef(camera.pitch,1,0,0);
glRotatef(camera.yaw,0,1,0);

//floor
glPushMatrix(); //don't really need this do I?
glCallList(ground); //coloured + checkered platform to test blending
glPopMatrix();

//draw particles
glDepthMask(false); //disable updating the z-buffer
glEnable(GL_BLEND); //enable blending

//test particle
glTranslatef(0,partY,0); //positioning (no rotation yet, make it "2d"?)

glBlendFunc(GL_DST_COLOR,GL_ZERO); //blend the mask
glBindTexture(GL_TEXTURE_2D,partOrbMask.texture);
glCallList(part); //draws the quad

//the next bit is sort of what I mean by double pass (the non-single pass bit being the mask above)

glColor4f(1,0,0,0.2); //translucent + red
glBindTexture(GL_TEXTURE_2D,partOrb.texture); //inverted form of the mask
glBlendFunc(GL_ONE,GL_ONE); //blend the particle
glCallList(part); //draws the quad

glDisable(GL_BLEND); //no blending (back to opaque)
glDepthMask(true); //did I need to change this? or is it causing issues?
glColor4f(1,1,1,1); //white,opaque

//end of frame
//get input etc








"orb" particle texture:

(the mask is an inverted form of this, ie: black in the centre radiation in a gradient to a white exterior)

What are your thoughts?

I have added different comments so If you want to say anything about my code it would help me a lot to hear it because most of my work is "blind" as I can't find any proper tutorials that combine effects together in a practical manner (eg, NeHe's particles don't work with something other than black behind them)

Share this post


Link to post
Share on other sites
Does your texture actually have an alpha channel, or are you using that image as the color?
If it's the color, you could try GL_ONE, GL_ONE_MINUS_SRC_COLOR. Usually you probably want that image to represent the alpha channel, and keep the RGB channel as all white, if you want to colorize it with glColor4f. How do you load your textures?
To use alpha you need a format that supports it, for example PNG. Alpha channels can be saved in BMPs but whether they're actually used depends on how you load the image, as there's no alpha in the BMP specification.

Share this post


Link to post
Share on other sites
There are no alpha channels, the images are loaded from raw format 24bpp.

So, opengl textures support alpha channels directly?

Here is my texture class:

class texture{
public:
GLuint texture;
int width,height;

bool loadRAW(char* path,int w = 128,int h = 128){
width = w;
height = h;

BYTE * data[width * height * 3]; //3 bytes per pixel
FILE * file;

//open and read texture data
file = fopen(path,"rb"); //attempt to open the file
if(!file) //check the file could be opened
return false;

fread(data, width * height * 3, 1, file); //copy file contents into the buffer
fclose(file); //close the file

//allocate a texture resource
glGenTextures(1,&texture);
/*
if(repeat){ //if it repeats
//set as repeating
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
}

//set filtering
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,filtering);
*/

//set as target
glBindTexture(GL_TEXTURE_2D,texture);
//set texture data
gluBuild2DMipmaps(GL_TEXTURE_2D,3,width,height,GL_RGB,GL_UNSIGNED_BYTE,data);

//free buffer
free(data);

return true;
}
};



(I think in some of my other workings I have a version of loadRAW which uses edge size instead of width/height as all the textures are going to be square)

I don't like using that buggy/dated/flawed glut library ^_^ so I opted for raw textures.

Would alpha channels solve my problems?

So where I use glColor4f(1,0,0,0.2);
it would render as the alpha of the pixel in the texture multiplied by 0.2?

So In the end I only need glColor3f? as the alpha is declared more sensibly.

The nature of NeHe's tutorials doesn't exactly help my understanding of other techniques.

Am I looking towards a different use of gluBuild2DMipmaps? Or another function for similar uses? I thought to implement an alpha map you had to use blending, and that was the idea behind the double pass.

Share this post


Link to post
Share on other sites
Use 4 instead of 3, and GL_RGBA instead of GL_RGB for gluBuild2DMipmaps, and specify a data array with 4 bytes per pixel, where the last will be the alpha.
You could do it in your load function, by setting the alpha channel to the RGB average and setting RGB to 255, or save a RAW with an alpha channel if the program you use supports it.

Quote:
So where I use glColor4f(1,0,0,0.2);
it would render as the alpha of the pixel in the texture multiplied by 0.2?

Yes this is correct.

Share this post


Link to post
Share on other sites
Great thanks for the help!

I think here I will make it form the alpha channel from the same image as the source one (find the "lightness" in an HSL fashion), considering that for particles the effect I want is basically a shape where it is coloured to the magnitude of an alpha.

[Edited by - Bozebo on March 13, 2010 10:18:20 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this