3
\$\begingroup\$

I'm trying to render a Texture via OpenGL. But instead of the texture black circles on a green background are rendered. (They scale, depending what the rotation of the texture is)

Example:

enter image description here

The texture I'm trying to render is the following:

enter image description here

This is the code I use to render the texture, it's located in my Sprite-class.

    public void Render()
    {
        Matrix4 matrix = Matrix4.CreateTranslation(-OriginX, -OriginY, 0) *
                        Matrix4.CreateRotationZ(Rotation) *
                        Matrix4.CreateTranslation(X, Y, 0);


        Vector2[] corners =
        {
            new Vector2(0,0), //top left
            new Vector2(Width ,0),//top right
            new Vector2(Width,Height),//bottom rigth
            new Vector2(0,Height)//bottom left
        };

        //copy the corners to the uv coordinates
        Vector2[] uv = corners.ToArray<Vector2>();

//transform the coordinates
        for (int i = 0; i < 4; i++) corners[i] = new Vector2(Vector3.Transform(new Vector3(corners[i]), matrix));
        //GL.Color3(TintColor);
        GL.BindTexture(TextureTarget.Texture2D, _ID);
        GL.Begin(BeginMode.Quads);
        {
            for (int i = 0; i < 4; i++)
            {
                GL.TexCoord2(uv[i]);
                GL.Vertex3(corners[i].X, corners[i].Y, _layerDepth);
            }
        }
        GL.End();

        if (EnableDebugDraw)
        {
            GL.Color3(Color.Violet);
            GL.PointSize(3);
            GL.Begin(BeginMode.Points);
            {
                for (int i = 0; i < 4; i++) GL.Vertex2(corners[i]);
            }
            GL.End();

            GL.Color3(Color.Green);
            GL.Begin(BeginMode.Points);
            GL.Vertex2(X, Y);
            GL.End();
        }

    }

This is how I setup OpenGL.

    public static void SetupGL()
    {
        GL.Enable(EnableCap.AlphaTest);
        GL.AlphaFunc(AlphaFunction.Greater, 0.1f);

        GL.Enable(EnableCap.Texture2D);
        GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);

    }

With this function I load the texture:

public static uint LoadTexture(string path)
    {
        uint id;
        GL.GenTextures(1, out id);
        GL.BindTexture(TextureTarget.Texture2D, id);

        Bitmap bitmap = new Bitmap(path);

        BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
            ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
            OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);

        bitmap.UnlockBits(data);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        return id;
    }

And here I call Sprite.Render()

protected override void OnRenderFrame(FrameEventArgs e)
    {
        GL.ClearColor(Color.MidnightBlue);
        GL.Clear(ClearBufferMask.ColorBufferBit);
        _sprite.Render();
        SwapBuffers();
        base.OnRenderFrame(e);
    }

As I stole this code from the Textures-Example from OpenTK, I don't understand why this doesn't work.

\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

First of all, your UVs look suspicious to me:

    Vector2[] corners =
    {
        new Vector2(0,0), //top left
        new Vector2(Width ,0),//top right
        new Vector2(Width,Height),//bottom rigth
        new Vector2(0,Height)//bottom left
    };

    //copy the corners to the uv coordinates
    Vector2[] uv = corners.ToArray<Vector2>();

Normally the UVs for a sprite would range from 0 to 1, not from 0 to width/height. This is probably why you've got a bunch of circles showing up; your UV mapping is accidentally squeezing the texture down to a tiny size and causing those circles to appear as an artifact.

Second, your texture loading logic looks suspicious. Your LockBits call specifies ARGB format, while your TexImage2D call specifies RGBA internal format. I'm not sure which is the correct one, but presumably they should match. This could be why the texture is turning green and black - the color channels are getting swapped around wrongly.

\$\endgroup\$
5
  • \$\begingroup\$ You're right. That's the reason there are multiple circles. The uv space is [0,1] and by default the sampler wraps around when the index is out of bounds. \$\endgroup\$
    – rootlocus
    Commented Nov 20, 2012 at 18:30
  • \$\begingroup\$ With the fixed uvs I now see my picture, however the colors are strange (white is green). According to this stackoverflow.com/questions/11645368/… the format is correct \$\endgroup\$
    – vinzBad
    Commented Nov 20, 2012 at 18:39
  • \$\begingroup\$ When I disable the debug-view, my texture gets rendered correctly :) \$\endgroup\$
    – vinzBad
    Commented Nov 20, 2012 at 18:42
  • 3
    \$\begingroup\$ @vinzBad Ahh, that's because the GL.Color3(Color.Green) in the debug-draw code is remaining in effect. You can cancel it by adding a call to set the color to white before drawing your sprites. \$\endgroup\$ Commented Nov 20, 2012 at 18:57
  • \$\begingroup\$ yep, this solved it :) \$\endgroup\$
    – vinzBad
    Commented Nov 20, 2012 at 18:57
1
\$\begingroup\$

Have a close look at this part of the code:

Bitmap bitmap = new Bitmap(path);

BitmapData data = bitmap.LockBits(
    new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
    ImageLockMode.ReadOnly, 
    System.Drawing.Imaging.PixelFormat.Format32bppArgb
);

GL.TexImage2D(
    TextureTarget.Texture2D, 
    0, PixelInternalFormat.Rgba, 
    data.Width, data.Height, 0,
    OpenTK.Graphics.OpenGL.PixelFormat.Bgra, 
    PixelType.UnsignedByte, data.Scan0
);

There seems to be a difference between the format of your BitmapData ( Format32bppArgb ) and the format you specify to GL.TexImage2D.

Also, having a quick look at the API page for glTexImage2D you can see that the internalformat and format parameters must have the same value. Yours differ: Rgba, Bgra. Make sure you use the same format everywhere ( namely Argb ).

Hope this helps.

\$\endgroup\$
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .