Search code examples
vb.nettexturesopentk

Why does a texture in OpenTK not show properly? (Wrong colors/Rotated)


I've made a list of my own texture objects so that I can access them accordingly. These are the two bitmap images I'm using:

enter image description here enter image description here

Every time I load my program, it reads from the two bitmap files and stores their texture data into my global texture list. The grass tile one loads first and then the checkerboard with the 1.0 loads after it. The grass tile texture renders. Here is how it looks like in my program:

enter image description here

It appears as if It's rotated 180 degrees and flipped horizontally. I've checked my 2d projection, coordinates and they're alright. Up goes towards positive Y, right towards positive X which, is fine. Also, the colors are alright, the texture works!

However, if I choose to render the second texture, which is the black/magenta checkerboard, it looks like this in my program:

enter image description here

It's rotated and flipped as well, but the colors aren't being rendered properly either. Why does this happen? Here is my code:

Loading the texture from Bitmap:

Private Function LoadFromBitmap(ByVal Bitmap As Bitmap) As Integer

    Dim Tex As Integer
    GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest)

    GL.GenTextures(1, Tex)
    GL.BindTexture(TextureTarget.Texture2D, Tex)

    Dim Data As BitmapData = Bitmap.LockBits(New Rectangle(0, 0, Bitmap.Width, Bitmap.Height), ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb)
    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Data.Width, Data.Height, 0, OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, Data.Scan0)
    Bitmap.UnlockBits(Data)

    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureMagFilter.Nearest)
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureMinFilter.Nearest)

    Return Tex
End Function

Rendering:

GL.MatrixMode(MatrixMode.Modelview)
GL.LoadIdentity()

GL.Viewport(0, 0, ControlWidth, ControlHeight)

For X As Byte = 0 To EZSize(0) - 1

    For Y As Byte = 0 To EZSize(1) - 1

        GL.Enable(EnableCap.Texture2D)

        GL.BindTexture(TextureTarget.Texture2D, TextureList.Item(1).IntData)

        GL.Begin(PrimitiveType.Quads)

        GL.TexCoord2(X, Y) : GL.Vertex2(X, Y)
        GL.TexCoord2(X + 1, Y) : GL.Vertex2(X + 1, Y)
        GL.TexCoord2(X + 1, Y + 1) : GL.Vertex2(X + 1, Y + 1)
        GL.TexCoord2(X, Y + 1) : GL.Vertex2(X, Y + 1)

        GL.End()

        GL.Disable(EnableCap.Texture2D)
    Next
Next

GL.LoadIdentity()
GL.Flush()

GraphicsContext.CurrentContext.SwapInterval = True
GlControl1.SwapBuffers()

Solution

  • If texturing is enabled, then by default the color of the texel is multiplied by the current color, because by default the texture environment mode (GL_TEXTURE_ENV_MODE) is GL_MODULATE. See glTexEnv.

    This causes that the color of the texels of the texture is "mixed" by the last color which you have set by glColor.

    Set a "white" color before you render the texture, to solve your issue:

    GL.Color3(Color.White)
    

    The texture is flipped, because the lower left window coordinate is (0,0), but in the texture the upper right coordinate is (0, 0). You've to compensate that by flipping the v-component of the texture coordinate:

    e.g.:

    GL.Enable(EnableCap.Texture2D)
    GL.BindTexture(TextureTarget.Texture2D, TextureList.Item(1).IntData)
    
    GL.Color3(Color.White)
    
    GL.Begin(PrimitiveType.Quads)
    
    GL.TexCoord2(X,     Y + 1)  : GL.Vertex2(X,     Y)
    GL.TexCoord2(X + 1, Y + 1)  : GL.Vertex2(X + 1, Y)
    GL.TexCoord2(X + 1, Y)      : GL.Vertex2(X + 1, Y + 1)
    GL.TexCoord2(X,     Y)      : GL.Vertex2(X,     Y + 1)
    
    GL.End()
    
    GL.Disable(EnableCap.Texture2D)
    

    Likewise you can change the environment mode to GL_REPLACE, instead by glTexEnv:

    GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, GL_REPLACE)