Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing a 2D texture in OpenGL [closed]

Tags:

c

opengl

I had a drawing function called DrawImage but it's really confusing and is only working with a specific form of the reshape function so I have 2 questions:

  1. How do I draw a texture in OpenGL ? I just want to create a function that gets a texture, x, y, width, height and maybe angle and paint it and draws it according to the arguments. I want to draw it as a GL_QUAD regularly but I'm not sure how to do that anymore .-. People say I should use SDL or SFML to do so, is it recommended ? If it is, can you give me a simple function that loads a texture and one that draws it ? I'm currently using SOIL to load textures.

the function is as here:

void DrawImage(char filename, int xx, int yy, int ww, int hh, int angle) 
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, filename);

  glLoadIdentity();
  glTranslatef(xx,yy,0.0);
  glRotatef(angle,0.0,0.0,1.0);
  glTranslatef(-xx,-yy,0.0);

// Draw a textured quad
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(xx,yy);
glTexCoord2f(0, 1); glVertex2f(xx,yy + hh);
glTexCoord2f(1, 1); glVertex2f(xx + ww,yy + hh);
glTexCoord2f(1, 0); glVertex2f(xx + ww,yy);

glDisable(GL_TEXTURE_2D);
glPopMatrix();

glMatrixMode(GL_PROJECTION);
glPopMatrix();

glMatrixMode(GL_MODELVIEW);
glEnd();
}

Someone said to me that you can't call glDisable, glPopMatrix or glMatrixMode between glBegin and glEnd. The problem is - the code won't work without it. Any idea how to make it work without it ? 2. About the glutReshapeFunc, the documentation says it gets a pointer to a functions with 2 args, width and height - I created (up to now) a function that gets void - any idea how to write a reshape function that gets a width and height and actually does what reshape needs to do.

and one minor question: How better is C++ than C when it comes to GUIs like OpenGL ? As all as I can see, only OOP is the matter and I didn't went to any problem that OOP could solve and C couldn't (in OpenGL I mean).

No need to answer all of the question - question number 1 is basically the most important to me :P

like image 395
user3745476 Avatar asked Jun 17 '14 11:06

user3745476


People also ask

How do you show textures in OpenGL?

in display() function : GLuint texture; texture = LoadTexture("bubble. png"); glBindTexture(GL_TEXTURE_2D, texture);

How do textures work in OpenGL?

A texture is an OpenGL Object that contains one or more images that all have the same image format. A texture can be used in two ways: it can be the source of a texture access from a Shader, or it can be used as a render target.

What is Gl_repeat?

GL_REPEAT : The integer part of the coordinate will be ignored and a repeating pattern is formed. GL_MIRRORED_REPEAT : The texture will also be repeated, but it will be mirrored when the integer part of the coordinate is odd.

What is Gl_rgba?

GL_RGBA. Red, green, blue, and alpha values (RGBA)


1 Answers

  1. Your DrawImage function looks pretty much just fine. Although, yes, you shouldn't be calling glMatrixMode etc. befor glEnd so remove them. I believe the issue is simply to do with setting up your projection matrix and the added calls just happen to fix an issue that shouldn't be there in the first place. glutReshapeFunc is used to capture window resize events so until you need it you don't have to use it.

  2. SDL gives you a lot more control over events and glut, but takes a little longer to set up. GLFW is also a good alternative. I guess its not that important to change unless you see a feature you need. These are libs to create a GL context and do some event handling. SOIL can be used for them all.

  3. OpenGL is a graphics API and gives a common interface for doing hardware accelerated 3D graphics, not a GUI lib. There are GUI libs written for OpenGL though.

  4. Yes I believe many take OOP to the extreme. I like the term C++ as a better C, rather than completely restructuring the way you code. Maybe just keep using C, but with a C++ compiler. Then when you see a feature you like, use it. Eventually you may find you're using lots and then have a better appreciation for the reason for their existence and when to use them rather than blindly following coding practices. Just imo, this is all very subjective.

So, the projection matrix...

To draw stuff in 3D on a 2D screen you "project" the 3D points onto a plane. I'm sure you've seen images like this:

enter image description here

This allows you to define your arbitrary 3D coordinate system. Except for drawing stuff in 2D its natural to want to use pixel coordinates directly. After all that's what you monitor displays. Thus, you want to use kind of a bypass projection which doesn't do any perspective scaling and matches pixels in scale and aspect ratio.

The default projection (or "viewing volume") is an orthographic -1 to one cube. To change it,

glMatrixMode(GL_PROJECTION); //from now on all glOrtho, glTranslate etc affect projection
glOrtho(0, widthInPixels, 0, heightInPixels, -1, 1);
glMatrixMode(GL_MODELVIEW); //good to leave in edit-modelview mode

Call this anywhere really, but since the only affecting variables are window width/height it's normal to put it in some initialization code or, if you plan on resizing your window, a resize event handler such as:

void reshape(int x, int y) {... do stuff with x/y ...}
...
glutReshapeFunc(reshape); //give glut the callback

This will make the lower left corner of the screen the origin and values passed to glVertex can now be in pixels.

A couple more things: instead of glTranslatef(-xx,-yy,0.0); you could just use glVertex2f(0,0) after. Push/pop matrix should always be paired within a function so the caller isn't expected to match it.

I'll finish with a full example:

#include <GL/glut.h>
#include <GL/gl.h>
#include <stdio.h>

int main(int argc, char** argv)
{
    //create GL context
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
    glutInitWindowSize(800, 600);
    glutCreateWindow("windowname");

    //create test checker image
    unsigned char texDat[64];
    for (int i = 0; i < 64; ++i)
        texDat[i] = ((i + (i / 8)) % 2) * 128 + 127;

    //upload to GPU texture
    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 8, 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, texDat);
    glBindTexture(GL_TEXTURE_2D, 0);

    //match projection to window resolution (could be in reshape callback)
    glMatrixMode(GL_PROJECTION);
    glOrtho(0, 800, 0, 600, -1, 1);
    glMatrixMode(GL_MODELVIEW);

    //clear and draw quad with texture (could be in display callback)
    glClear(GL_COLOR_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, tex);
    glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
    glTexCoord2i(0, 0); glVertex2i(100, 100);
    glTexCoord2i(0, 1); glVertex2i(100, 500);
    glTexCoord2i(1, 1); glVertex2i(500, 500);
    glTexCoord2i(1, 0); glVertex2i(500, 100);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
    glFlush(); //don't need this with GLUT_DOUBLE and glutSwapBuffers

    getchar(); //pause so you can see what just happened
    //System("pause"); //I think this works on windows

    return 0;
}
like image 165
jozxyqk Avatar answered Sep 22 '22 13:09

jozxyqk