3

I've got a problem in that I'm trying to draw a solar system using textures (one texture for each planet) and as I draw my textures, only the 1st one appears. None of the rest do.

My init function iterates through my files, saves the textures into an object, and then iterates through the objects. As it's iterating, it generates the textures and binds them to a name using the OpenGL calls.

        SharpGL.OpenGL gl = args.OpenGL;
        gl.Enable(SharpGL.OpenGL.GL_BLEND);
        gl.Enable(SharpGL.OpenGL.GL_TEXTURE_2D);
        gl.BlendFunc(SharpGL.Enumerations.BlendingSourceFactor.SourceAlpha, SharpGL.Enumerations.BlendingDestinationFactor.OneMinusSourceAlpha);                        
        gl.ClearColor(0, 0, 0, 1);

        foreach (ImageWrapper iw in m_images)
        {                            
            uint[] texNames = new uint[1];

            gl.GenTextures(1, texNames);
            gl.BindTexture(SharpGL.OpenGL.GL_TEXTURE_2D, texNames[0]);

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

            gl.TexImage2D(SharpGL.OpenGL.GL_TEXTURE_2D,
                          0,
                          3,
                          iw.BitmapSource.PixelWidth,
                          iw.BitmapSource.PixelHeight,
                          0,
                          SharpGL.OpenGL.GL_BGRA,
                          SharpGL.OpenGL.GL_UNSIGNED_BYTE,
                          iw.Pixels);

            iw.TextureHandle = texNames;

        }

Here is my function that draws everything. I iterate through all my objects that have the texture data and try to draw them one at a time. I also want to execute some rotations and transformations to get my solar system to spin. That part works fine for the texture that appears.

        SharpGL.OpenGL gl = args.OpenGL;
        gl.Clear(SharpGL.OpenGL.GL_COLOR_BUFFER_BIT | SharpGL.OpenGL.GL_DEPTH_BUFFER_BIT );
        gl.LoadIdentity();

        float[] data = new float[4];
        foreach (ImageWrapper iw in m_images)
        {
            //gl.MatrixMode(SharpGL.Enumerations.MatrixMode.Modelview);                

            gl.Ortho2D(0, this.Width, 0, this.Height);                
            gl.Enable(OpenGL.GL_TEXTURE_2D);                
            gl.BindTexture(OpenGL.GL_TEXTURE_2D, iw.TextureHandle[0]);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_WRAP_S, SharpGL.OpenGL.GL_REPEAT);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_WRAP_T, SharpGL.OpenGL.GL_REPEAT);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_MAG_FILTER, SharpGL.OpenGL.GL_LINEAR);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_MIN_FILTER, SharpGL.OpenGL.GL_LINEAR);


            gl.PushMatrix();
            //gl.Translate(this.Width / 2, this.Height / 2, 0);               

            //gl.Rotate(iw.RotationAboutSun, 0, 0, 1);
            //gl.Translate(iw.X + 1 * this.Width / 2, iw.Y + 1 * this.Height / 2, 0);
            gl.Translate(32,32, 0);
            //gl.Rotate(iw.RotationAboutAxis, 0, 0, 1);  
            //

            gl.Begin(SharpGL.Enumerations.BeginMode.Quads);
            gl.Color(new float[] { 1f,1f,1f});                                          
            gl.TexCoord(0,0);
            gl.Vertex(new double[] { 0 - iw.PixelWidth / 2, 0 - iw.PixelHeight / 2});                
            gl.TexCoord(0,1);
            gl.Vertex(new double[] { 32 - iw.PixelWidth / 2, 0 - iw.PixelHeight / 2 });               
            gl.TexCoord(1,1);
            gl.Vertex(new double[] { 32 - iw.PixelWidth / 2, 32 - iw.PixelHeight / 2 });
            gl.TexCoord(1,0);
            gl.Vertex(new double[] { 0 - iw.PixelWidth / 2, 32 - iw.PixelHeight / 2 });                            
            gl.End();

            gl.PopMatrix();

            gl.Disable(OpenGL.GL_TEXTURE_2D);                

        }

I'm using the SharpGL library in C# to do this.

shekhar
  • 1,372
  • 2
  • 16
  • 23
mj_
  • 6,297
  • 7
  • 40
  • 80
  • I don't see anything untoward. Are you sure the Pixels member is filled in properly for all of the elements in m_images? – Nathan Monteleone Mar 13 '13 at 13:46
  • Yeah, I just checked. It looks okay. – mj_ Mar 13 '13 at 14:01
  • Seems like you forgot the [`glActiveTexture`](http://www.opengl.org/sdk/docs/man/xhtml/glActiveTexture.xml) calls. They need to get called before the texture binding. – danijar Mar 13 '13 at 14:14

2 Answers2

2

gluOrtho2D() doesn't issue a glLoadIdentity() like you seem to expect.

Generally you only set your projection matrix once per frame.

Try something like this:

void DrawFrame()
{
    ...

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluOrtho2D(0, this.Width, 0, this.Height);

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    // "camera" transform(s)

    foreach object
    {
        glPushMatrix();
        // per-object matrix transform(s)

        // draw object

        glPopMatrix();
    }
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • hip hip hooray! that did it! – mj_ Mar 13 '13 at 14:32
  • @mj_: Glad it was an easy fix :) – genpfault Mar 13 '13 at 14:32
  • 1
    @genpfault: Just nitpicking, you set your projection matrix once per render pass, i.e. once for 3D scene, once for HUD and so on. – datenwolf Mar 13 '13 at 14:38
  • @datenwolf Why is setting the projection matrix multiple times in a frame bad practice? Wouldn't that become necessary if you want to draw some 2D stuff, then 3D stuff and then some other 2D stuff that should appear on top of everything else? – Maghoumi Sep 11 '15 at 04:36
  • 1
    @M2X: I never said, setting it multiple times was bad practice. On the contrary, I'm one of the proponents of setting OpenGL state whenever it seems necessary, to make sure you don't trip about state you didn't pin down. With modern OpenGL you've to set the uniforms for each shader program anyway. – datenwolf Sep 11 '15 at 08:11
0

Just had to deal with this problem so I thought I'd chip in as well.
I saw the accepted answer and in my case, I did reset everything correctly in the pipeline. In my pipeline, I need to render both 3D and 2D objects. For 3D objects I would switch to 3D projection/model view and for 2D objects would switch to orthographic projection.

However, when I wanted to render a couple of text blocks (using quads and textures), only the first texture was rendered. Depth testing was the root of my problem. So I've modified the code above to work for my situation.

void DrawFrame()
{
    foreach object
    {
        drawObject();   // Is an abstract method
    }
}


void _3DObject::drawObject() {
    switchTo3D();

    // Camera transform

    glPushMatrix();
    .
    . // Draw
    .
    .glPopMatrix();
}

void _2DObject::drawObject() {
    switchTo2D();

    // Having depth testing enabled was causing
    // problems when rendering textured quads.
    glDisable(GL_DEPTH_TEST);

    // Camera transform

    glPushMatrix();
    .
    . // Draw
    .
    .glPopMatrix();

    glEnable(GL_DEPTH_TEST);
}

PS: "Just" refers to exactly 1 month ago! Don't know why I forgot to post this answer sooner :(

Maghoumi
  • 3,295
  • 3
  • 33
  • 49