[solved]Blend two textures for one vbo

Hi! This is my first post so I’m not sure if I’m posting this in the right place :confused:

So I’m trying two blend two textures(earth surface, clouds) onto a simple sphere created using an obj file that I exported from blender. I’m using 4 buffer objects for the vertices, textureCoords, normals and faces. Before adding the second material(clouds) my result looked fine:

Then I added the second material to the rendering code which now looks like this:


public void render()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, handles.get(VERTEX));
    glVertexPointer(3, GL_FLOAT, 0, 0);

    material.bind(); // the earth's surface texture
    glBindBuffer(GL_ARRAY_BUFFER, handles.get(TEXTURE));
    glTexCoordPointer(2, GL_FLOAT, 0, 0);

    material2.bind(); // the semi transparent cloud texture
    glBindBuffer(GL_ARRAY_BUFFER, handles.get(TEXTURE));
    glTexCoordPointer(2, GL_FLOAT, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, handles.get(NORMAL));
    glNormalPointer(GL_FLOAT, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handles.get(FACE));
    glDrawElements(GL_TRIANGLES, modelScheme.getIndices().size(),    GL_UNSIGNED_INT, 0);

    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
}

And enabled blending in the opengl initializing code:


glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);

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

glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);

And the result I’m getting now is this:

Does anyone know why this effect happens instead of the two materials blend together nicely? If anyone is interested the two textures I use for the materials are these:

(In the cloud texture for some reason the transparent parts are not showing here)

I Apologise for the big post and I wish you all the best

Cheers,

Alex

You aren’t rendering the vbo when you have the earth texture bound. It’s getting “overwritten” when you’re setting up the clouds material.

Edit: Look at SHC’s for a better alternative because it only requires a single pass.

Use two textures at the same time. Bind one texture to texture unit 0 and another to unit 1. And use uniforms to send them to the shaders. In the shader,


vec4 mapTexel = texture(texMap, texCoords);
vec4 cloudTexel = texture(texCloud, texCoords);

// Final texture color is a blend of both
vec4 texelColor = mapTexel * cloudTexel

That should solve the problem.

Thanks for the fast replies! I appreciate it!

While obviously SHC’s is pointing me toward the right direction, I admit I’m unfamiliar with shaders and I wanted to keep it shader-less for just this example before I move on into more complex examples.

Longarmx I followed your advice but I still can’t seem to get it working! (I’m probably doing something silly). I changed the rendering method so it renders the mesh 2 times with the 2 different textures, and now the result has only the earth’s surface texture showing!

The rendering method looks like this following your directions


    public void render()
    {
        ....
        glBindBuffer(GL_ARRAY_BUFFER, handles.get(VERTEX));
        glVertexPointer(3, GL_FLOAT, 0, 0);
        
        glBindBuffer(GL_ARRAY_BUFFER, handles.get(NORMAL));
        glNormalPointer(GL_FLOAT, 0, 0);

        glBindBuffer(GL_ARRAY_BUFFER, handles.get(TEXTURE));
        glTexCoordPointer(2, GL_FLOAT, 0, 0);

        material.bind(); // the earth's surface texture
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handles.get(FACE));
        glDrawElements(GL_TRIANGLES, modelScheme.getIndices().size(),    GL_UNSIGNED_INT, 0);
        
        material2.bind();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handles.get(FACE));
        glDrawElements(GL_TRIANGLES, modelScheme.getIndices().size(),    GL_UNSIGNED_INT, 0);
   
        ...
    }

You may be experiencing an issue where some z-fighting is going on. The cloud texture would be rendered, but the earth texture would be obstructing the cloud texture. Try to move the camera around and see if parts of the cloud texture flashes intermittently.

I’ll play around with my code and see if I can find the source of the issue.
It appears that only the first glDrawElements call actually happens. It is not a texturing issue.

Anyway many thanks for your interest in helping me :slight_smile:

One last thing to try is to setup all the pointers before each of the draw calls. I don’t know why it would do anything (maybe pointers are reset in special conditions?), but it’s worth a shot :point:

Wow I finally did it :smiley:

It was as Longarmx proposed! The earth’s surface texture was obstructing the clouds’ one.

With a quick scaling fix the rendering code is now functional :slight_smile:

 
    public void render()
    {
        ....
        glBindBuffer(GL_ARRAY_BUFFER, handles.get(VERTEX));
        glVertexPointer(3, GL_FLOAT, 0, 0);
        
        glBindBuffer(GL_ARRAY_BUFFER, handles.get(NORMAL));
        glNormalPointer(GL_FLOAT, 0, 0);

        glBindBuffer(GL_ARRAY_BUFFER, handles.get(TEXTURE));
        glTexCoordPointer(2, GL_FLOAT, 0, 0);

        material.bind(); // the earth's surface texture
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handles.get(FACE));
        glDrawElements(GL_TRIANGLES, modelScheme.getIndices().size(), GL_UNSIGNED_INT, 0);
        
        
        MatrixUtils.pushMatrix();
        {
            MatrixUtils.scalef(1.02f);
      
            material2.bind();
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handles.get(FACE));
            glDrawElements(GL_TRIANGLES, modelScheme.getIndices().size(), GL_UNSIGNED_INT, 0);
        }
        MatrixUtils.popMatrix();
        .....
    }

And the evidence ^-^