Search code examples
c#opentk

opentk multiple textures on cube don't work


So in my program there is a function for drawing a cube. I am using c# with monodevelop on linux. Here is the function:

private int DrawCube(float x, float y, float z, float ori, int SideTexture, int TopTexture, int BottomTexture)
{
    GL.PushMatrix();

    GL.Translate(x, y, z);
    GL.Rotate(ori, 0, 1, 0);

    GL.BindTexture(TextureTarget.Texture2D, SideTexture);

    GL.Begin(BeginMode.Quads);

    GL.Color3(Color.White);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    //Top
    //GL.ActiveTexture(TextureUnit.Texture0);
    GL.BindTexture(TextureTarget.Texture2D, TopTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    //Bottom
    GL.BindTexture(TextureTarget.Texture2D, BottomTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, 0);
    GL.BindTexture(TextureTarget.Texture2D, SideTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);

    GL.End();
    GL.PopMatrix();

return 6;   // Return number of faces drawn
}

As you may have guessed this function draws a cube with position x, y, z. Direction ori and SideTexture on the sides as well as TopTexture and BottomTexture on the top and bottom. Now the problem is that it draws the cube with only one texture! the side texture. I don't know what is the problem. Do I have to unbind the textures? everything else in the code works fine just as I said already there is this nuisance with the textures. Any help is appreciated.


Solution

  • You cannot call GL.BindTexture() within a begin-end region. From the documentation:

    Only a subset of GL commands can be used between glBegin and glEnd. The commands are glVertex, glColor, glSecondaryColor, glIndex, glNormal, glFogCoord, glTexCoord, glMultiTexCoord, glVertexAttrib, glEvalCoord, glEvalPoint, glArrayElement, glMaterial, and glEdgeFlag. Also, it is acceptable to use glCallList or glCallLists to execute display lists that include only the preceding commands. If any other GL command is executed between glBegin and glEnd, the error flag is set and the command is ignored.

    If you check GL.GetError() you will see that you are getting an InvalidOperation error. In fact GL.GetError() should be your first reaction when something does not render as expected in OpenGL.

    The solution:

    private int DrawCube(float x, float y, float z, float ori, int SideTexture, int TopTexture, int BottomTexture)
    {
        GL.PushMatrix();
    
        GL.Translate(x, y, z);
        GL.Rotate(ori, 0, 1, 0);
    
        GL.BindTexture(TextureTarget.Texture2D, SideTexture);
        GL.Begin(BeginMode.Quads);
        GL.Color3(Color.White);
        GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
        GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
        GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
        GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
        GL.End();
    
        //Top
        GL.BindTexture(TextureTarget.Texture2D, TopTexture);
        GL.Begin(BeginMode.Quads);
        GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
        GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
        GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
        GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
        GL.End();
    
        //Bottom
        GL.BindTexture(TextureTarget.Texture2D, BottomTexture);
        GL.Begin(BeginMode.Quads);
        GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
        GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
        GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, -20);
        GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, 0);
        GL.End();
    
        GL.BindTexture(TextureTarget.Texture2D, SideTexture);
        GL.Begin(BeginMode.Quads);
        GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
        GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
        GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
        GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
    
        GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 20, 0);
        GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 20, 0);
        GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
        GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
    
        GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
        GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
        GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
        GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
        GL.End();
    
        GL.PopMatrix();
    
        return 6;   // Return number of faces drawn
    }