Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: Blending not yielding the results as expected, trying to make images overlap...

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Junior Member Newbie
    Join Date
    Feb 2018
    Posts
    6

    Question Blending not yielding the results as expected, trying to make images overlap...

    Basically I'm trying to avoid using depth sorting by using blending and I've tried the familiar

    Code :
    glEnable(GL_BLEND);
             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    but no luck.

    The goal I'm trying to get to is something I managed to solve in Irrlicht using the opengl driver so I know this should work. Here's the thread and the final image with blending enabled. http://irrlicht.sourceforge.net/foru...eb86385ff21b57



    Here's the source code for the GL version using GLUT and SOIL for image loading, I'm using Xubuntu ( not sure it matters).

    Code :
    #include <GL/glut.h>
    #include <GL/glu.h>
    #include <cmath>
    #include <iostream>
    #include <string>
    #include "SOIL.h"
    // angle of rotation for the camera direction
    float angle=0.0;
    // actual vector representing the camera's direction
    float lx=0.0f,lz=-1.0f;
    // XZ position of the camera
    float x=0.0f,z=35.0f;
    // all variables initialized to 1.0, meaning
    // the triangle will initially be white
    float red=1.0f, blue=1.0f, green=1.0f;
     
    GLuint TextureID = 0;
    GLuint GetTexture(std::string Filename)
    {
    	GLuint tex_ID;
     
    	tex_ID = SOIL_load_OGL_texture
    	(
    				Filename.c_str(),
    				SOIL_LOAD_AUTO,
                    SOIL_CREATE_NEW_ID,
                    SOIL_FLAG_MIPMAPS |
                    SOIL_FLAG_INVERT_Y |
                    SOIL_FLAG_NTSC_SAFE_RGB |
                    SOIL_FLAG_COMPRESS_TO_DXT
            );
     
    		if( tex_ID > 0 )
    		{
    			glEnable( GL_TEXTURE_2D );
    			glBindTexture( GL_TEXTURE_2D, tex_ID );
    			std::cout<<"texture loaded!"<<std::endl;
     
    			return tex_ID;
    		}
    		else
    			return 0;
    }
    void processNormalKeys(unsigned char key, int x, int y)
    {
    	if (key == 27)
    		exit(0);
    }
    void changeSize(int w, int h)
    {
    	// Prevent a divide by zero, when window is too short
    	// (you cant make a window of zero width).
    	if (h == 0)
    		h = 1;
    	float ratio =  w * 1.0 / h;
     
            // Use the Projection Matrix
    	glMatrixMode(GL_PROJECTION);
     
            // Reset Matrix
    	glLoadIdentity();
     
    	// Set the viewport to be the entire window
    	glViewport(0, 0, w, h);
     
    	// Set the correct perspective.
    	gluPerspective(45.0f, ratio, 0.1f, 100.0f);
     
    	// Get Back to the Modelview
    	glMatrixMode(GL_MODELVIEW);
    }
    void renderScene(void)
    {
    	// Clear Color and Depth Buffers
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	// Reset transformations
    	glLoadIdentity();
    	// Set the camera
    	gluLookAt(	x, 1.0f, z,
    			x+lx, 1.0f,  z+lz,
    			0.0f, 1.0f,  0.0f);
     
    			 glEnable(GL_BLEND);
     
    			 //tried a whole bunch of other stuff
      //glBlendFunc(GL_ONE, GL_ONE);
    //glEnable(GL_BLEND_COLOR);
    //glEnable(GL_DEPTH_TEST);
    //glBlendEquation( GL_FUNC_ADD);
    //glBlendFunc(GL_DST_ALPHA, GL_ZERO);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, TextureID);
    	glColor3f(0.9f, 0.9f, 0.9f);
    	glBegin(GL_QUADS);
            glTexCoord2d(0.0,0.0);
    		glVertex3f(-5.0f, -5.0f, 0.0f);
    		glTexCoord2d(1.0,0.0);
    		glVertex3f(-5.0f, 5.0f, 0.0f  );
    		glTexCoord2d(1.0,1.0);
    		glVertex3f( 5.0f, 5.0f, 0.0f);
    		glTexCoord2d(0.0,1.0);
    		glVertex3f( 5.0f, -5.0f, 0.0f );
    	glEnd();
     
    	glColor3f(0.9f, 0.9f, 0.9f);
    	glBegin(GL_QUADS);
            glTexCoord2d(0.0,0.0);
    		glVertex3f(-10.0f, -5.0f, 0.0f);
    		glTexCoord2d(1.0,0.0);
    		glVertex3f(-10.0f, 5.0f, 0.0f  );
    		glTexCoord2d(1.0,1.0);
    		glVertex3f( 5.0f, 5.0f, 0.0f);
    		glTexCoord2d(0.0,1.0);
    		glVertex3f( 5.0f, -5.0f, 0.0f );
    	glEnd();
        glDisable(GL_TEXTURE_2D);
     
    glDisable(GL_BLEND);
     
    	glutSwapBuffers();
    }
    void processSpecialKeys(int key, int xx, int yy)
    {
    	float fraction = 0.1f;
     
    	switch (key)
    	{
    		case GLUT_KEY_LEFT :
    			angle -= 0.01f;
    			lx = sin(angle);
    			lz = -cos(angle);
    			break;
    		case GLUT_KEY_RIGHT :
    			angle += 0.01f;
    			lx = sin(angle);
    			lz = -cos(angle);
    			break;
    		case GLUT_KEY_UP :
    			x += lx * fraction;
    			z += lz * fraction;
    			break;
    		case GLUT_KEY_DOWN :
    			x -= lx * fraction;
    			z -= lz * fraction;
    			break;
    	}
    }
    int main(int argc, char **argv)
    {
    	// init GLUT and create window
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    	glutInitWindowPosition(100,100);
    	glutInitWindowSize( 640, 640);
    	glutCreateWindow("SOIL image Test");
     
    	// register callbacks
    	glutDisplayFunc(renderScene);
    	glutReshapeFunc(changeSize);
    	glutIdleFunc(renderScene);
    	glutKeyboardFunc(processNormalKeys);
    	glutSpecialFunc(processSpecialKeys);
     
    	// OpenGL init
     
    	glEnable(GL_DEPTH_TEST);
        TextureID = GetTexture( "../../../textures/particlewhite.png");
    	// enter GLUT event processing cycle
    	glutMainLoop();
     
    	return 1;
    }

    and the png image Click image for larger version. 

Name:	particlewhite.png 
Views:	52 
Size:	15.4 KB 
ID:	2666
    Last edited by pandoragami; 02-11-2018 at 05:11 PM. Reason: removed unneeded code.

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,926
    Quote Originally Posted by pandoragami View Post
    Basically I'm trying to avoid using depth sorting by using blending and I've tried the familiar
    Code :
    	 glEnable(GL_BLEND);
             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    but no luck.
    You need to render from back to front with that function.

    If the images represent light sources, you might try additive blending, e.g.:
    Code :
             glBlendFunc(GL_SRC_ALPHA, GL_ONE);

    or, if the image uses pre-multiplied alpha:

    Code :
             glBlendFunc(GL_ONE, GL_ONE);

    More generally: if the destination factor uses the source alpha or the source factor uses the destination alpha, the function will be non-commutative, i.e. the order in which overlapping primitives are rendered matters.

  3. #3
    Junior Member Newbie
    Join Date
    Feb 2018
    Posts
    6
    Thanks for the reply. I intend to use these for billboards to render particles, so it's not about light sources. Basically the code I included is pretty much what it's supposed "to do" meaning that I want two polygon quads overlapping each other to sort of blend with each other and the background. I'm starting to realize though that if other objects are around these so called particles then I would have to blend these textures with other objects somehow?

    What do you mean by "You need to render from back to front with that function."?

    Do you mean depth sorting?

    Is there another way to blend polygons in the camera perspective regardless of distance ordering in which opengl somehow magically blends all visible textures into a blurry mess; in order to avoid depth sorting?

    Right now I'm wonder how irrlicht managed to run that code I had, basically I enabled blending with the material I used like so...

    Code :
    material.BlendOperation =  irr::video::EBO_ADD;

    which I'm guessing is equivalent to

    Code :
    glBlendEquation( GL_FUNC_ADD);

    and it worked in Irrlicht but not in GL. I don't think there was any depth sorting required, or at least I'm not aware of implicitly called any function to do such a thing.
    Maybe Irrlicht does depth sorting in these cases? Any suggestions please thanks!

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,926
    Quote Originally Posted by pandoragami View Post
    What do you mean by "You need to render from back to front with that function."?

    Do you mean depth sorting?
    Yes.

    Quote Originally Posted by pandoragami View Post
    Is there another way to blend polygons in the camera perspective regardless of distance ordering in which opengl somehow magically blends all visible textures into a blurry mess; in order to avoid depth sorting?
    Additive blending. Addition is commutative: A+B=B+A, so the order doesn't matter.

    With linear blending, if you blend two translucent colours <c1,a1> and <c2,a2> over an opaque background cb, you get either
    a1*c1+(1-a1)*(a2*c2+(1-a2)*cb) = a1*c1+(1-a1)*a2*c2+(1-a1)*(1-a2)*cb
    or
    a2*c2+(1-a2)*(a1*c1+(1-a1)*cb) = a1*(1-a2)*c1+a2*c2+(1-a1)*(1-a2)*cb

    depending upon the order in which the two textures are rendered. Their relative depth doesn't have any effect. Visually, the first texture rendered will appear to be behind the second texture rendered, so you need to order them accordingly.

    If you change the destination factor to GL_ONE (additive blending), the 1-a1 and 1-a2 terms disappear, giving
    a1*c1+a2*c2+cb
    regardless of the rendering order. This is appropriate for light sources, which add to the light coming from behind without occluding it. For translucent surfaces which both occlude light from behind and reflect light from in front, you have to depth-sort somehow. You can either depth-sort the primitives, or use techniques such as "depth peeling" to sort the fragments. Neither are entirely straightforward.

    Quote Originally Posted by pandoragami View Post
    Right now I'm wonder how irrlicht managed to run that code I had, basically I enabled blending with the material I used like so...

    Code :
    material.BlendOperation =  irr::video::EBO_ADD;

    which I'm guessing is equivalent to

    Code :
    glBlendEquation( GL_FUNC_ADD);
    GL_FUNC_ADD is the default. Prior to OpenGL 2.0, it was the only option.

    Additive blending refers to using the default blend equation (add) with either of
    Code :
             glBlendFunc(GL_SRC_ALPHA, GL_ONE);
             glBlendFunc(GL_ONE, GL_ONE);
    depending upon whether the textures use pre-multiplied alpha. I.e. the colours from the various overlapping primitives are simply added together (the destination factor is always one; the source factor weights the colour by the alpha value if it isn't already so weighted, i.e. pre-multiplied alpha).

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •