CheatCat's picture

[Solved] NeHe Lesson 9 - Cannot see the texture!

Well, I have tried to follow NeHe Lesson 9, but the program don't draw the texture! :( (I tried to draw only one "star", heh!) I use Objarni's TexUtil class instead of the InitGL, LoadGLTextures and LoadBMP functions. What is wrong?

using System;
using System.Drawing;
 
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Audio;
using OpenTK.Math;
using OpenTK.Input;
using OpenTK.Platform;
 
namespace StarterKit
{
    class Game : GameWindow
    {
        // Creates a new TextPrinter to draw text on the screen.
        TextPrinter printer = new TextPrinter(TextQuality.Medium);
        Font sans_serif = new Font(FontFamily.GenericSansSerif, 18.0f);
        int texture = 0;
 
        /// <summary>Creates a 800x600 window with the specified title.</summary>
        public Game()
            : base(800, 600, GraphicsMode.Default, "OpenTK Quick Start Sample")
        {
            VSync = VSyncMode.On;
        }
 
        /// <summary>Load resources here.</summary>
        /// <param name="e">Not used.</param>
        public override void OnLoad(EventArgs e)
        {
            TexLib.TexUtil.InitTexturing();
            GL.ClearColor(System.Drawing.Color.CornflowerBlue);
            texture = TexLib.TexUtil.CreateTextureFromFile("image.png");
            GL.Enable(EnableCap.DepthTest);
        }
 
        /// <summary>
        /// Called when your window is resized. Set your viewport here. It is also
        /// a good place to set up your projection matrix (which probably changes
        /// along when the aspect ratio of your window).
        /// </summary>
        /// <param name="e">Contains information on the new Width and Size of the GameWindow.</param>
        protected override void OnResize(ResizeEventArgs e)
        {
            GL.Viewport(0, 0, Width, Height);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            Glu.Perspective(45.0, Width / (double)Height, 1.0, 64.0);
        }
 
        /// <summary>
        /// Called when it is time to setup the next frame. Add you game logic here.
        /// </summary>
        /// <param name="e">Contains timing information for framerate independent logic.</param>
        public override void OnUpdateFrame(UpdateFrameEventArgs e)
        {
            if (Keyboard[Key.Escape])
                Exit();
        }
 
        /// <summary>
        /// Called when it is time to render the next frame. Add your rendering code here.
        /// </summary>
        /// <param name="e">Contains timing information.</param>
        public override void OnRenderFrame(RenderFrameEventArgs e)
        {
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
            Glu.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
 
            GL.BindTexture(TextureTarget.Texture2D, texture);
            GL.LoadIdentity();
            GL.Translate(0, 0, 15);
 
            GL.Begin(BeginMode.Quads);
              GL.TexCoord2(0, 0); GL.Vertex3(-1, -1, 0);
              GL.TexCoord2(1, 0); GL.Vertex3(1, -1, 0);
              GL.TexCoord2(1, 1); GL.Vertex3(1, 1, 0);
              GL.TexCoord2(0, 1); GL.Vertex3(-1, 1, 0);
           GL.End();
 
            SwapBuffers();
        }
 
        [STAThread]
        static void Main()
        {
            // The 'using' idiom guarantees proper resource cleanup.
            // We request 30 UpdateFrame events per second, and unlimited
            // RenderFrame events (as fast as the computer can handle).
            using (Game game = new Game())
            {
                game.Run(30.0, 0.0);
            }
        }
    }
}

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Change:

GL.Translate(0, 0, 15);

to

GL.Translate(0, 0, -15);

:)

CheatCat's picture

So easy! Thank you! :D But why does the texture appear upside-down?

objarni's picture

I think of it like this:

Bitmaps, Forms and Controls in general in .NET have a coordinate system that places the origo in the top-left corner of the object, and y-axis going down, x-axis going to the right.

So coordinate (1, 1) in texture/bitmap coordinate space means bottom-right pixel of the picture.

Try rewriting the Vertex/TexCoord calls with this in mind.

Update: I drew a picture to explain what I mean.

AttachmentSize
TextureCoordinates.png45.9 KB
the Fiddler's picture

Because texture coordinates define top-left as (0, 0), while vertex coordinates as (-1, 1). Edit: Beaten :)

CheatCat's picture

I understand! And it is different at C++?

The solution if someone are interested:

            GL.Begin(BeginMode.Quads);
              GL.TexCoord2(0, 0); GL.Vertex3(-1, 1, 0);
              GL.TexCoord2(1, 0); GL.Vertex3(1, 1, 0);
              GL.TexCoord2(1, 1); GL.Vertex3(1, -1, 0);
              GL.TexCoord2(0, 1); GL.Vertex3(-1, -1, 0);
           GL.End();

But when I add GL.Rotate(90.0f, 1, 0, 0); the texture disappears! Do the whole "view" turned then?
I also drawn a picture to explain what I mean:

objarni's picture

GL.Rotate rotates the "pen" in OpenGL, around the axis specified.

You specified (1,0,0) that is rotation around opengl's x-axis, which goes from left-to-right, through the center of the screen per default. Rotating 90 degrees around that axis places you quad in the xz-plane, which should basically means the quad is a line on the screen, or not anything at all, since the "thickness" of primitives in OpenGL is 0.

Try changing rotation axis to (0,0,1) that is rotation around the z-axis. The z-axis goes from screen towards your nose. :)

Update: Picture to explain added.

Update 2: Added even more pedagogical picture :)

AttachmentSize
CheatCatExplanation.png13.96 KB
OpenGLCoordinates.png7.23 KB
CheatCat's picture

Cool! :D And I move the texture by GL.Translate? Do the GL.BindTexture say what texture to move with GL.Translate?

objarni's picture

Rotate/Translate and other such matrix-modifying operations only affect the current matrix (Projection or ModelView).

What texture is active currently has nothing to do with this.

Think of it as a "structure" of OpenGL State:

GLState {
 Matrix3d ModelViewMatrix, ProjectionMatrix;
 MatrixMode CurrentMode; // this tells what matrix is affected by LoadIdentity/Rotate/Translate operations
 int CurrentTexture;
 Color3d CurrentColor;
 ... // and so on..
}

Hope I explain myself well ;)

Entropy's picture

In OpenGL, there's an important distinction between a texture and a primitive shape (i.e.the quad to which your texture is mapped).

GL.BindTexture(...) specifies which texture you're referring to when you call GL.TexCoord2 to map the texture coordinates to each corner if the quad you draw. Any texture-actions will be performed on the last texture you bound, until you call GL.BindTexture(TextureTarget.Texture2D, 0);.

If you loaded 2 different textures (let's say with int identifiers tex1 and tex2), you'd be able to select which texture to bind to the quad when you draw it by switching GL.BindTexture(TextureTarget.Texture2D, tex1) with GL.BindTexture(TextureTarget.Texture2D, tex2) just before you draw the quad.

In this case (as long as you've selected MatrixMode.ModelView), GL.Translate(...) only changes the position of the quad when you draw it. GL.BindTexture won't select any specific quad (or other primitive shape), no matter which texture has been mapped to it.

Hope that helps.

Edit: You're too quick, objarni ;-)

CheatCat's picture

Okey, now I almost understand! :D Thank you guys! Case closed!