EFileTahi-A's picture

Why can't I simply draw an image on the screen?

I want to use OpenTK for 2D ONLY. Having said that, I require only to draw text, lines, images and rectangles on the screen.

My first challenge: to draw a simple image on the screen at a given location. Why I'm having a hard time doing this? I mean, ok, I'm new to openGL but once I was also new to GDI+, SDL and DirectX and I managed to the 2D drawing thingie in such blissfuly and flawlessly way... Unfortunately SDL .NET does not work on Win7 64bit so I was forced to seek another Cross-platform solution.

I'm about to give up on openTK because I'm loosing time doing something that should be the most easy thing to do. I've ready the docs but there is nothing dedicated to 2D drawing. I know OpenGL is mainly for 3D but so is DirectX. Why DirectX is so easy to used towards 2D? Too bad is not cross-platform.

Anyway I've managed to draw an image to the screen through the example that came with the openTK package but I simply can't handle it's positionating right. I'm also surprised (by the negative) by the amout of lines of code that it requires to load a simply image to the screen. Than I have this GL.Ortho thing to help me out.

I have the GL.Ortho(0,800,600,0,0,1) as suggested in some website for 2D drawing, but I'm not getting anything to the screen. I don't even know if the way the texture is loaded is the right one for 2D. I don't know if I need quads to render the image to the screen. I don't know anything at this moment... apart from being completely lost on openTK.

So, if no one manages to help me at this forum I will be forced to deny opentk and keep the slow GDI+


Comments

Comment viewing options

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

Can you post your current code?

EFileTahi-A's picture
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Graphics;
 
namespace KharmaSoul.Forms
{
    public partial class f_mainWindowOpenGL : Form
    {
        c_openGL OPENGL = new c_openGL();
        int iTexture = 0;
        Bitmap bmpBG;
 
        bool bOpenGLReady = false;
        public f_mainWindowOpenGL()
        {
            InitializeComponent();
        }
 
        #region EVENT - f_mainWindowOpenGL_Load
        private void f_mainWindowOpenGL_Load(object sender, EventArgs e)
        {
 
        }
        #endregion
 
        private void glControl_Load(object sender, EventArgs e)
        {
            bmpBG = new Bitmap(Application.StartupPath + "\\bg.bmp");
 
            bOpenGLReady = true;
 
            GL.ClearColor(Color.SkyBlue);
            GL.Enable(EnableCap.Texture2D);
            GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
            GL.GenTextures(1, out iTexture);
            GL.BindTexture(TextureTarget.Texture2D, iTexture);
 
            BitmapData data = bmpBG.LockBits(new System.Drawing.Rectangle(0, 0, bmpBG.Width, bmpBG.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);
 
            bmpBG.UnlockBits(data);
 
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
 
           // OPENGL.Sys_SetViewPort(this.glControl.Width, this.glControl.Height);
        }
 
        private void glControl_Resize(object sender, EventArgs e)
        {
            if (!bOpenGLReady)
                return;
 
            GL.Viewport(0, 0, this.glControl.Width, this.glControl.Height); // Use all of the glControl painting area
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            GL.Ortho(0.0, this.glControl.Width, this.glControl.Height, 0, 0, 1); // Bottom-left corner pixel has coordinate (0, 0)
        }
 
        private void glControl_Paint(object sender, PaintEventArgs e)
        {
            if (!bOpenGLReady)
                return;
 
            GL.Clear(ClearBufferMask.ColorBufferBit);
 
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
            GL.BindTexture(TextureTarget.Texture2D, iTexture);
 
            GL.Begin(BeginMode.Points);
 
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex2(-0.6f, -0.4f);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex2(0.6f, -0.4f);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex2(0.6f, 0.4f);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex2(-0.6f, 0.4f);
 
            GL.End();
 
            this.glControl.SwapBuffers();
        }
    }
}
nythrix's picture

Short answer would be that "simply" is a relative term and you're loosing time because you're using a chainsaw to drive a screw. The type of functionality you want is offered by 2D engines.

OpenGL and by extent OpenTK is 3D oriented. It doesn't matter how many D's you use though, the code is more or less the same. On the other hand GDI+ and SDL are 2D oriented so they're *simpler* (not simple mind you!) to use in these scenarios. I don't know about DirectX and I can't be bothered.

You've forgotten about GL.Finish() before this.glControl.SwapBuffers();

the Fiddler's picture
GL.Ortho(0.0, this.glControl.Width, this.glControl.Height, 0, 0, 1);

Try this instead:

GL.Ortho(0.0, this.glControl.Width, this.glControl.Height, 0, -1, 1);

It's not necessary to call GL.Finish() before SwapBuffers() as it is implicitly called anyway, according to the gl specs.

EFileTahi-A's picture
nythrix wrote:

Short answer would be that "simply" is a relative term and you're loosing time because you're using a chainsaw to drive a screw.

I believe i'm trying to use a hand-screw-drive to screw a giant bolt which was degined to be operated by an industrial screwier, accompanied by 500 page manual so that just the screwing rotation concept could be fully understood and put into practice.

A -

nythrix wrote:

The type of functionality you want is offered by 2D engines.

Well DirectX happens to do this in a single line of code:
Sprite.Draw(Texture, theSprite.SourceRectangle, New Vector3(0.0F, 0.0F, 0.0F), New Vector3(0.0F, 0.0F, 0.0F), Color.White). And DirectX is not a 2D engine and yet operates 2D as almost as simple as GDI+. Unfortunately DX lacks cross-platform capabilities.

nythrix wrote:

OpenGL and by extent OpenTK is 3D oriented. It doesn't matter how many D's you use though, the code is more or less the same. On the other hand GDI+ and SDL are 2D oriented so they're *simpler* (not simple mind you!) to use in these scenarios.

Yes, a thing I already knew and that I totally agree with you.

nythrix wrote:

I don't know about DirectX and I can't be bothered.

This is the reason why you statement at 'A' will always return false.

So in sum, the complexity in using 2D on openTK / opengl is merely related to the way opengl was assembled. It's difficulty level also gets worse when no documentation is available to explain how to operate the industrial screw driver to screw small hand-bolts. OpenGL reminds me of the WWII Bismark German Battleship, incredible fast and powerful yet inefficient to shoot down the simple WWI primitive airplanes that attacked her destroying the rudder with a single torpedo, rendering the ship useless.

nythrix wrote:

You've forgotten about GL.Finish() before this.glControl.SwapBuffers();

the GL.Finish() is not here in the code because I was passing code from my application's classes to the forum and it got left out by mistake.

The problem remains: (As I stated in my first post) How can I draw an image at a specific X,Y coordinate on the screen. My problem is not displaying a picture in the screen but to display it at a given location at certain size.

To be honest I begin actually to not care about it, I'm loosing too much time with this and I doubt someone will actually help me out, specialy, when I see people paying more attention to what and how I write instead focusing in helping.

EFileTahi-A's picture

Thanks I will try that once I get home.

But still How do I manage the 2D coord system for image positionation on the screen?
Is the way I'm redering the image the right one for 2D?

nythrix's picture

Well, I couldn't find anything inherently wrong with the code. It "should" work as it is. Maybe a forgotten setup call somewhere?

Now don't get me wrong but platform independence is a key issue here. IMO, DirectX can achieve this in a single line (apparently) BECAUSE it's platform limited. In other words, it knows what's what and behaves accordingly. OpenGL, on the other hand, has no concept of windows (in the general sense not the OS) or composition therefore it cannot directly stick a bitmap at (230, 440). OpenGL, as you probably know, operates in abstract (3D) space and has no knowledge about its surroundings. This is where all sorts of utilities and toolkits step in. And that's why you're likely to find it in both a digital watch and a tomograph at your nearest hospital.

This is the reason why you statement at 'A' will always return false.
Mine was an advice not a statement. 2D engines go far beyond displaying images. Finding a good one is hard though, because everyone focuses on 3D nowadays. It's apparently much cooler and girls go crazy about it or so I've heard.
Using OpenGL for text rendering could also turn out to be a nightmare. So you really should consider a 2D engine given the requirements in your OP. There's at least one based on OpenTK (http://www.opentk.com/node/257?page=1). I'm not sure about its state though.

Edit: Hmmm, you're TextureMinFilter'ing twice. Probably a typo. One of them should read TextureMagFilter.
Edit2: Now that I think of it, you can copy images around using Frame Buffer Objects and framebuffer blitting but that might end up being more verbose codewise. Search for FBOs and glBlitFramebuffer.
Edit3: Unlike Windows, OpenGL Y coordinate is inverted (up is more) so you should also flip the bitmap upside down before displaying it.

EFileTahi-A's picture

Well, I decided to abandon OpenTK. I will stick with GDI+ for now. Its slow but it will do it. Yes a 2D is what I was seeking but after the SDL failure I ran out of options and decided to try OpenGL, also for curiosity as I had never tried it before.

Thanks for the post though and take care.

cody's picture

I dont know why nobody pointed out these errors in the code:
- it draws only to one pixel on the screen.
- is z-test disabled?
- it only draws points, it doesnt fill anything with a texture.

c2woody's picture
Quote:

I dont know why nobody pointed out these errors in the code:

The world is cruel :(