[SOLVED] OpenGL alpha blending problem

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
GroundUpEngine
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 835
Joined: Sun Nov 08, 2009 2:01 pm
Current Project: mixture
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: UK

[SOLVED] OpenGL alpha blending problem

Post 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
Last edited by GroundUpEngine on Fri Jul 13, 2012 4:48 pm, edited 1 time in total.
User avatar
TheBuzzSaw
Chaos Rift Junior
Chaos Rift Junior
Posts: 310
Joined: Wed Dec 02, 2009 3:55 pm
Current Project: Paroxysm
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Contact:

Re: OpenGL alpha blending problem

Post by TheBuzzSaw »

Sanity checks!

Are you rendering back to front?

Did you glEnable(GL_BLEND) and glBlendFunc?
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: OpenGL alpha blending problem

Post 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.
User avatar
GroundUpEngine
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 835
Joined: Sun Nov 08, 2009 2:01 pm
Current Project: mixture
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: UK

Re: OpenGL alpha blending problem

Post 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
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: OpenGL alpha blending problem

Post 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.
User avatar
GroundUpEngine
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 835
Joined: Sun Nov 08, 2009 2:01 pm
Current Project: mixture
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: UK

Re: OpenGL alpha blending problem

Post 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
qpHalcy0n
Respected Programmer
Respected Programmer
Posts: 387
Joined: Fri Dec 19, 2008 3:33 pm
Location: Dallas
Contact:

Re: OpenGL alpha blending problem

Post 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.
User avatar
GroundUpEngine
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 835
Joined: Sun Nov 08, 2009 2:01 pm
Current Project: mixture
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: UK

Re: OpenGL alpha blending problem

Post 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:
Last edited by GroundUpEngine on Fri Jul 13, 2012 4:40 pm, edited 3 times in total.
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re: OpenGL alpha blending problem

Post by superLED »

I can't help, but I have a little question: What are you using to load in the models?
User avatar
GroundUpEngine
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 835
Joined: Sun Nov 08, 2009 2:01 pm
Current Project: mixture
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: UK

Re: OpenGL alpha blending problem

Post 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();
CC Ricers
Chaos Rift Regular
Chaos Rift Regular
Posts: 120
Joined: Sat Jan 24, 2009 1:36 am
Location: Chicago, IL

Re: OpenGL alpha blending problem

Post 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.
User avatar
GroundUpEngine
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 835
Joined: Sun Nov 08, 2009 2:01 pm
Current Project: mixture
Favorite Gaming Platforms: PC
Programming Language of Choice: C++
Location: UK

Re: OpenGL alpha blending problem

Post 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
Post Reply