0
\$\begingroup\$

I am trying to draw a simple 32x32 PNG image using SharpGL and OpenGL 2.1. Despite many hours of searching, reading answers to similar questions, nothing could solve my issue. The image is showed as a white square.

I tried debugging OpenGL using glGetError() but it always returns 0. I have no idea of what could be the problem.

Some help would be very appreciated!

Loading method

public static GLImage LoadImagePNG(OpenGL gl, Bitmap bmp)
{
    bmp = ResizeTo(bmp, 32, 32);

    uint[] textures = new uint[1];
    gl.GenTextures(1, textures);

    uint texture = textures[0];

    gl.Enable(OpenGL.GL_TEXTURE_2D);

    BitmapData data = bmp.LockBits(
        new Rectangle(0, 0, bmp.Width, bmp.Height),
        ImageLockMode.ReadOnly,
        PixelFormat.Format32bppArgb
    );

    gl.BindTexture(OpenGL.GL_TEXTURE_2D, texture);

    gl.TexImage2D(
        OpenGL.GL_TEXTURE_2D,
        0,
        4,
        bmp.Width,
        bmp.Height,
        0,
        OpenGL.GL_RGBA,
        OpenGL.GL_UNSIGNED_BYTE,
        data.Scan0
    );

    Console.WriteLine(gl.GetError());

    bmp.UnlockBits(data);

    gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_S, OpenGL.GL_CLAMP_TO_EDGE);
    gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_T, OpenGL.GL_CLAMP_TO_EDGE);
    gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR);
    gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR);

    // not disposing the Bitmap on purpose (for now)

    return new GLImage(texture, bmp);
}

Render method

public static void DrawImage(OpenGL gl, GLImage img, double x, double y)
{
    gl.PushMatrix();
    gl.Translate(x, y, 0.0D);

    gl.ActiveTexture(OpenGL.GL_TEXTURE0);
    gl.BindTexture(OpenGL.GL_TEXTURE_2D, img.TextureID);
    gl.Enable(OpenGL.GL_TEXTURE_2D);

    gl.Begin(BeginMode.Quads);
        gl.TexCoord(0.0f, 0.0f); gl.Vertex(0, 0);
        gl.TexCoord(1.0f, 0.0f); gl.Vertex(img.Width, 0);
        gl.TexCoord(1.0f, 1.0f); gl.Vertex(img.Width, img.Height);
        gl.TexCoord(0.0f, 1.0f); gl.Vertex(0, img.Height);
    gl.End();

    gl.Disable(OpenGL.GL_TEXTURE_2D);

    gl.PopMatrix();
}

and GLImage being a custom class

GLImage

public class GLImage
{
    public uint TextureID { get; private set; }

    public Bitmap Bitmap { get; private set; }

    public double Width
    {
        get
        {
            return this.Bitmap.Width;
        }
    }

    public double Height
    {
        get
        {
            return this.Bitmap.Height;
        }
    }

    public GLImage(uint textureID, Bitmap bmp)
    {
        this.TextureID = textureID;
        this.Bitmap = bmp;
    }
}

Thank you!

\$\endgroup\$
0
\$\begingroup\$

I'm the OP. As I posted as a visitor and registered afterwards, I don't seem to be able to answer any comment or edit my post. So I am going to answer here.


EDIT: Solution !

Alright, I finally made it work. The issue was quite simple (as always, right?). I did only one little thing differently between home and work: I was loading the image in a different thread. Just that. Now it works.


Thanks for your answers ebv and justix. Concerning justix, as Maximus Minimus said, I'm using OpenGL 2.1 so your answer doesn't apply to my case. I still appreciate your help!

I had the issue at work, got home and tried the same code there. It didn't work at first and then figured that my resizing method ResizeTo wasn't working properly: it was returning a full transparent image. It doesn't really explain why it showed a white square at work, because it drew a black square here at home which made more sense to me (R, G, B and A at 0 and blending disabled).

I fixed my method ResizeTo, enabled OpenGL's blending and it worked! I will try that code tomorrow at work and keep you guys updated.


New method ResizeTo

private static Bitmap ResizeTo(Bitmap bmp, int width, int height)
{
    return new Bitmap(bmp, new Size(width, height));
}

Drawing

gl.Enable(OpenGL.GL_BLEND);
gl.BlendFunc(OpenGL.GL_SRC_ALPHA, OpenGL.GL_ONE_MINUS_SRC_ALPHA);
DrawImage(img, 20, 20);
gl.Disable(OpenGL.GL_BLEND);

@ebv: I checked the internal format which I set to 4, and changed it to the constant GL_RGBA8. Both worked just as well.

\$\endgroup\$
0
\$\begingroup\$

And check the "internal format" parameter of glTexImage2D() (now 4). Should be something like GL_RGBA8 if it is a 4 channel texture with byte values.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.