0

我有一个opengl项目,我只是想在屏幕上绘制一个红色矩形,问题是1)它很大,几乎占据了整个屏幕,2)它是倾斜的。我对opengl真的很陌生,所以我不了解坐标系,以及一些函数的作用,例如glOrtho()函数。

这是代码:

void display()
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   glBegin(GL_QUADS);     
      glColor3f(1, 0, 0);  // NOT SURE WHERE THIS STARTS, AND HOW THE COORDINATES WORK
        glVertex2f(-1.0f, 1.0f); 
        glVertex2f( 1.0f, 1.0f);  
        glVertex2f( 1.0f,-1.0f);        
        glVertex2f(-1.0f,-1.0f);   
    glEnd();                  

   glFlush();
}

void init()
{
   glClearColor(0.0, 0.0, 0.0, 1.0);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(0, 10.0, 0, 10.0, -1.0, 1.0); //What does this do and how does it's coordinates work?
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glRotatef(30.0, 1.0, 1.0, 1.0);
   glEnable(GL_DEPTH_TEST);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(250, 250);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
    glutCreateWindow("Model View");


    glutDisplayFunc(display);

   init();
    glutMainLoop();

    return 0;
}

无论如何,我更愿意把它变成一种学习体验,所以请解释并链接到有帮助的东西!谢谢。

4

2 回答 2

5

Procedure display is responsible for the actual drawing.

void display()
{

This line clears the buffer; the buffer is basically the memory are where the image is rendered; it is basically a matrix with width and height 600x600. To clear means to set every cell of the matrix to the same value. Every cell is a pixel and contains a color and a depth. With this call you are telling OpenGL to paint everything opaque black, and to reset the depth to 1. Why opaque black? Because of your call to glClearColor: the first three parameters are the red, green and blue component, and they can range between 0 and 1. 0,0,0 means black. For the last component you specified 1, which means opaque; 0 would be transparent. This last component is called alpha and is used when alpha blending is enabled. Why the clear depth is 1? Because 1 is the default, and you didn't call glClearDepth to override that value.

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

This is telling OpenGL that you want to draw quadrilaterals.

   glBegin(GL_QUADS);

You want these quadrilateral to be red (remember that the first component of a color is red).

      glColor3f(1, 0, 0);  // NOT SURE WHERE THIS STARTS, AND HOW THE COORDINATES WORK

Now you list the vertices of the quadrilateral (it's only one, four vertices); all vertices will be red because you never update the color by calling glColor3f; you can associate a different color to every vertex, the final result is usually very cute if you pick red (1,0,0), green (0,1,0), blue (0,0,1) and white (1,1,1); this quadrilateral should appear to screen as a square, because it is a square geometrically, your window is a square, and the camera (defined with glOrtho) has a square aspect (first four parameters of the call to glOrtho). If you didn't call glOrtho you would probably see only red, because the default OpenGL coordinates range between -1 and 1 and so you are covering the entire window.

        glVertex2f(-1.0f, 1.0f); 
        glVertex2f( 1.0f, 1.0f);  
        glVertex2f( 1.0f,-1.0f);        
        glVertex2f(-1.0f,-1.0f);   

This means that you are done with drawing.

    glEnd();                  

Technically, it may be that OpenGL didn't send any of the commands you specified to the graphic card; commands may be enqueued for efficiency reason. Calling glFlush forces the command to be sent to the graphic card.

   glFlush();
}

You wrote this function, init to initialize some of the OpenGL states, that you felt would remain stable across the application. In reality a real application like a game would have most of this stuff under display. For instance a game must continuously update the camera, as the player moves.

void init()
{

Here as we said before you are setting the clear color to be opaque black.

   glClearColor(0.0, 0.0, 0.0, 1.0);

Here you are saying that the camera is not of a perspective type; basically things that are far away don't get smaller. It is similar to the view that an artificial satellite has of a city. In particular you are creating a camera which is not "centered" on the field of view: I recommend to use a call like glOrtho(-10.0, 10.0, -10.0, 10.0, -1.0, 1.0) for your first experiments. For a non perspective camera the coordinates that you specify here override the convention -1 to +1 that we mentioned above. Try to regulate the parameters such that your red square appears small, and centered.

   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(0, 10.0, 0, 10.0, -1.0, 1.0); //What does this do and how does it's coordinates work?

Here you are basically positioning the camera relative to the square, or the square relative to the camera; there are infinite ways to see it. You are defining a geometrical transformation, and the reason why it is called MODELVIEW is that it is not uniquely something that alters the model (the square) or the view (the camera) but both, depending on the way you see it. However, your square appears rotated because you are calling glRotatef; remove it and the square should appear like a square.

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glRotatef(30.0, 1.0, 1.0, 1.0);

Depth test is a technique that uses the depth store in the buffer in order to remove hidden surfaces, for instance the back faces of a cube in a 3D scene. Your scene is 2D and you are drawing only a quad, so this is really non affecting your drawing.

   glEnable(GL_DEPTH_TEST);
}

In the main you are interacting with glut, an optional subsystem which is not part of OpenGL but is useful to carry out some boring and tedious operations that only the operating system is authorized to perform.

int main(int argc, char *argv[])
{

First you must init glut.

    glutInit(&argc, argv);

Then you define the window that will contain your rendering image.

    glutInitWindowSize(600, 600);
    glutInitWindowPosition(250, 250);

GLUT_RGB means that your window only supports red, green and blue, and doesn't have an alpha channel (this is very often the case). GLUT_DEPTH means that your buffer will be able to store the depth of each pixel. GLUT_SINGLE means that the window is single buffered, that is your commands will directly draw on the window; another option is double buffering, where you actually draw on a back buffer, and then you swap front and back buffer so that the rendered image appears suddenly, and not in a progressive fashion. Your scene is so simple that you shouldn't notice any difference between GLUT_SINGLE and GLUT_DOUBLE.

    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);

Then you actually create the window.

    glutCreateWindow("Model View");

You tell glut which function should be called to render the scene.

    glutDisplayFunc(display);

Here you call your init function.

   init();

This is a window loop, provided by glut. Most windowing system require a software loop in order to keep the window alive, and able to respond to clicks, drags, resize and keyboard strokes.

    glutMainLoop();

    return 0;
}

Long story short, several versions of OpenGL are available, and they can be programmed using several languages, and targeted to several platforms. The single most important difference between these versions is that some use a fixed function pipeline (FFP) whereas the newest versions have a programmable pipeline. Your program uses a fixed function pipeline. You should switch to a programmable pipeline whenever you can, because it is the modern way of doing computer graphics, and is much more flexible, even though it requires a little more programming, as the name suggests.

You should ignore the tutorials that I linked originally, I didn't immediately realized how outdated they were. You should go with the one recommended by datenwolf or, if you are interested in mobile development, you could consider learning OpenGL ES 2 (the 2 is important, because the previous version was fixed function). There is also a variant of OpenGL ES 2 for HTML5 and Javascript, called WebGL. You find the tutorials here, together with a ZIP file containing all the examples; I use their codebase whenever I need to check if I understood a new concept.

于 2013-02-12T00:08:06.207 回答
0

因为你看起来很有趣:)

您在 (1,1) 到 (-1,-1) //display() 中创建了一个红色方块

然后说相机将使用正交投影//glOrtho查看它(它创建一个投影矩阵,使用一个点来放置相机并给它一个方向)

并且可能通过 glRotating MODEL*VIEW* 稍微倾斜

PS您必须将gl命令视为发送到gl子系统的消息,这些消息会改变它的各种状态,场景中的内容,相机在哪里,灯光在哪里等等......等等......

于 2013-02-11T23:38:02.180 回答