在OpenGL中绘制2D纹理 [英] Drawing a 2D texture in OpenGL

查看:98
本文介绍了在OpenGL中绘制2D纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为DrawImage的绘图函数,但它确实令人困惑,并且只能使用特定形式的重塑函数,因此我有2个问题:

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. 如何在OpenGL中绘制纹理?我只想创建一个获取纹理,x,y,宽度,高度甚至角度的函数,然后根据参数将其绘制并绘制.我想定期将其绘制为GL_QUAD,但现在不知道该如何做了.-.人们说我应该使用SDL或SFML这样做,建议吗?如果是的话,您能给我一个简单的功能来加载纹理并绘制纹理吗?我目前正在使用SOIL加载纹理.

功能如下:

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();
}

有人对我说,您不能在glBeginglEnd之间呼叫glDisableglPopMatrixglMatrixMode.问题是-没有它,代码将无法工作.知道如何在没有它的情况下使它工作吗? 2.关于glutReshapeFunc,文档说它得到了一个指向具有2个args(宽度和高度)的函数的指针-我创建了(到目前为止)一个无效的函数-任何想法如何编写一个获得宽度和高度的reshape函数高度,实际上完成了重塑所需做的事情.

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.

和一个小问题:就OpenGL之类的GUI而言,C ++比C有什么优势?据我所知,只有OOP才是问题,我没有遇到OOP可以解决而C不能解决的任何问题(在OpenGL中是我的意思.)

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).

无需回答所有问题-问题1对我来说基本上是最重要的:P

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

推荐答案

  1. 您的DrawImage函数看起来很好.虽然是的,但是您不应该在glEnd之前调用glMatrixMode等,因此请将其删除.我认为问题只是与设置投影矩阵有关,而添加的调用恰好解决了最初不应该存在的问题. glutReshapeFunc用于捕获窗口大小调整事件,因此在需要之前,您不必使用它.

  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.

SDL使您可以更好地控制事件和过剩,但设置时间要长一点. GLFW也是一个很好的选择.我想除非您看到所需的功能,否则更改并不是那么重要.这些是创建GL上下文并进行一些事件处理的库. SOIL可以全部用于它们.

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.

OpenGL是图形API,并且提供了用于执行硬件加速3D图形的通用接口,而不是GUI库.虽然有为OpenGL编写的GUI库.

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.

是的,我相信许多人会将OOP发挥到极致.我喜欢术语C ++作为更好的C语言,而不是完全重组您的编码方式.也许只是继续使用C,而是使用C ++编译器.然后,当您看到自己喜欢的功能时,请使用它.最终,您可能会发现自己正在使用很多东西,然后对它们存在的原因以及何时使用它们有了更好的理解,而不是盲目地遵循编码实践.只是imo,这都是非常主观的.

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...

要在2D屏幕上以3D方式绘制内容,可以将3D点投影"到平面上.我确定您已经看过这样的图像:

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:

这使您可以定义任意3D坐标系.除了以2D方式绘制东西外,自然要直接使用像素坐标.毕竟,这就是您要监视的内容.因此,您要使用一种旁路投影,该投影不进行任何透视缩放,而是在比例和长宽比上匹配像素.

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.

默认投影(或查看体积")是正交-1到一个立方体.要更改它,

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

这将使屏幕的左下角成为原点,并且传递给glVertex的值现在可以以像素为单位.

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

还有两件事:您可以在glVertex2f(0,0)之后使用glVertex2f(0,0)代替.推/弹出矩阵应始终在函数内配对,以免调用方将其匹配.

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;
}

这篇关于在OpenGL中绘制2D纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆