Page 1 of 1

[SOLVED] OpenGL alpha blending problem

Posted: Mon Jul 09, 2012 12:24 pm
by GroundUpEngine
Hey guys, first of all awesome new look for the website... very trendy! ;)

My projects been dead for a while yet again lol... But I've restarted it for the last time in the form of a graphics engine instead of a game engine that I'll work on bit by bit through the holidays and through uni while trying to do a video at least every month or so. The project name for now is GroundUpEngine reborn, and I'm using the OpenGL SuperBible 4th Edition to refresh my memory so I can write the engine better than ever.

Anywhore... I have a problem with alpha blending trees to be specific, in the screenshot below you can see that in Blender the modelling software I'm using renders the tree and its leafs fine but in the engine their depth appears incorrect relative to the camera.
Image

I've tried and failed so far:
  • Disabling the depth buffer when drawing the tree
  • Modelling the tree with less geometry

Re: OpenGL alpha blending problem

Posted: Mon Jul 09, 2012 12:56 pm
by TheBuzzSaw
Sanity checks!

Are you rendering back to front?

Did you glEnable(GL_BLEND) and glBlendFunc?

Re: OpenGL alpha blending problem

Posted: Mon Jul 09, 2012 1:00 pm
by bbguimaraes
Thank you guys from the forum for the
esforum wrote: At least one new post has been made to this topic. You may wish to review your post in light of this.
Anyway, my guess is glBlendFunc too.

Re: OpenGL alpha blending problem

Posted: Mon Jul 09, 2012 1:03 pm
by GroundUpEngine
TheBuzzSaw wrote:Sanity checks!

Are you rendering back to front?

Did you glEnable(GL_BLEND) and glBlendFunc?
setup:

Code: Select all

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

Code: Select all

glDisable(GL_DEPTH_TEST);

    ...

glEnable(GL_DEPTH_TEST);
Back to front? :P

Re: OpenGL alpha blending problem

Posted: Mon Jul 09, 2012 1:13 pm
by bbguimaraes
You need to draw solid objects before blended objects. Think of rendering as real painting. You draw something solid, then draw a "thin" object on top of it.

Re: OpenGL alpha blending problem

Posted: Mon Jul 09, 2012 1:31 pm
by GroundUpEngine
The tree branch and leafs are now separate models, and the leafs are drawn in front of the tree branch..

depth testing disabled:
Image

depth testing enabled, hmm I thought disabling depth testing helped alpha blending... it seems the branch vertices are causing the depth buffer to freak out:
Image

Re: OpenGL alpha blending problem

Posted: Tue Jul 10, 2012 1:08 pm
by qpHalcy0n
Generally if you don't have many other passes that need to happen you'll separate opaque geometry from transparent geometry.

1) (Optional)Render opaque geometry w/ color writes disabled (z-write enabled, z-test enabled)
2) Render your opaque geometry front to back (improves fast z-reject) w/ z-test enabled, (z-write disabled if you did step 1)
3) Do whatever other rendering things you might need to do
4) Set your blend state, in this case your blend functions look pretty typical.
5) Render transparent geometry back to front (z-test should be on...opaque geometry can occlude transparent geom. However, z-writes should be off)

What is likely happening is that you have to realize you fully control the process here. You CAN disable and enable both z-reads and z-writes independently. If you have z-test enabled, you also have z-write enabled (by default) so that as you render transparent faces you're testing against the z-buffer and writing to it if they pass. This is not correct for transparent faces. You simply want the test for opaque faces.

Re: OpenGL alpha blending problem

Posted: Tue Jul 10, 2012 4:24 pm
by GroundUpEngine
I'm so rusty with OpenGL it's terrible, thanks for the advice I understand the depth buffer a bit better now. A better output was produced by these changes but the tree trunk is still sticking out through the leaves, I have two separate OBJ meshes rendered in this order: tree trunk -> leaves.

code, which is called twice:

Code: Select all

void RenderingSystem::draw(MeshOBJ* drawable)
{
    // If mesh is transparent temporarily disable depth buffer write.
    if(drawable->mTransparent)
    {
        glDepthMask(false);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    glPushMatrix();
        glTranslatef(drawable->mPosition.x, drawable->mPosition.y, drawable->mPosition.z);
        // Texture
        drawable->mTexture->bind();
        glColor3f(1.0f, 0.0f, 0.0f);
        // 3D OBJ mesh
        if(GRAPHICS_LEVEL >= 1)
        {
            glCallList(drawable->mDL);
        }
        glColor3f(1.0f, 1.0f, 1.0f);
        drawable->mTexture->unbind();
    glPopMatrix();

    if(drawable->mTransparent)
    {
        glDisable(GL_BLEND);

        glDepthMask(true);
    }

    /// DEBUGGING
    getError();
}
depth read on + depth write off:
Image

p.s. My instinct now is be hacky and shorten the tree trunk so it rests just underneath the leaves, but these days I want to better myself and make clean operational applications :lol:

Re: OpenGL alpha blending problem

Posted: Tue Jul 10, 2012 6:32 pm
by superLED
I can't help, but I have a little question: What are you using to load in the models?

Re: OpenGL alpha blending problem

Posted: Wed Jul 11, 2012 5:30 am
by GroundUpEngine
superLED wrote:I can't help, but I have a little question: What are you using to load in the models?
No prob, I used my own simple OBJ mesh parser. I can give you a rough idea of the code being used but there's a few things you need to know first though:
  • C/C++ basics e.g. loops, STL strings, STL vectors, file IO, etc.
  • OpenGL basics (OpenGL 1 in this case) e.g. building gemometry, drawing with gemometric primitives, etc.
Below is an example of a simple triangle with no shading or textures, first the modelling software (blender in this case) would export the OBJ mesh to a file e.g. 'triangle.obj':

Code: Select all

v 0.0 0.0 0.0
v 0.0 0.0 10.0
v 10.0 0.0 0.0
f 1 2 3
initialise:

Code: Select all

class vec3
{
  public:  
    float x, y, z;
};
string vertexToken = "v";
string faceToken = "f";
vector<vec3> vertices;
vector<vec3> tempVertices;

ifstream i("triangle.obj");
while(!i.eof())
{
  string temp;
  i >> temp;

  if(temp == vertexToken)
  {
    vec3 vec;
    i >> vec;
    tempVertices.push_back(vec);
  }
  if(temp == faceToken)
  {
    int a, b, c;
    i >> a >> b >> c;
    vertices.push_back( tempVertices[a] );
    vertices.push_back( tempVertices[b] );
    vertices.push_back( tempVertices[c] );
  }
}
i.close();
draw:

Code: Select all

glPushMatrix();
  glBegin(GL_TRIANGLES);
  for(unsigned int i = 0; i < vertices.size(); i++)
  {
    glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
  }
  glEnd();
glPopMatrix();

Re: OpenGL alpha blending problem

Posted: Thu Jul 12, 2012 4:04 pm
by CC Ricers
bbguimaraes wrote:You need to draw solid objects before blended objects. Think of rendering as real painting. You draw something solid, then draw a "thin" object on top of it.
This, pretty much. In fact there's something call the Painter's Algorithm that solves this exact problem. The API's own depth sort works well enough without transparent objects, but adding transparent objects in your scene can drive you mad :P

The tree trunk is showing through the leaves because it's actually correct with the depth sort, now it's time to make a better looking tree ;) Make the "leaves" part of the OBJ branches, actually, even if they're just as a texture. Draw a transparent texture with branches and paste tiny versions of those leaves over it, and the tree will already look a lot better.

Re: OpenGL alpha blending problem

Posted: Fri Jul 13, 2012 4:47 pm
by GroundUpEngine
CC Ricers wrote:
bbguimaraes wrote:You need to draw solid objects before blended objects. Think of rendering as real painting. You draw something solid, then draw a "thin" object on top of it.
This, pretty much. In fact there's something call the Painter's Algorithm that solves this exact problem. The API's own depth sort works well enough without transparent objects, but adding transparent objects in your scene can drive you mad :P

The tree trunk is showing through the leaves because it's actually correct with the depth sort, now it's time to make a better looking tree ;) Make the "leaves" part of the OBJ branches, actually, even if they're just as a texture. Draw a transparent texture with branches and paste tiny versions of those leaves over it, and the tree will already look a lot better.
That solves the problem indeed, but then I figured to optimize the model and since you can't see the branches inside the leafs (even when the branches are part of the leafs model), so I took the geometry out all together giving the same affect! I'll keep that idea of a better tree model in mind though ;)
Image