简体   繁体   English

OpenGL坐标是什么? 忽略 OpenGL 窗口大小

[英]What the OpenGL coordinates are? Ignore OpenGL window size

I just started trying to folow simple "draw cube" openGl tutorial .我刚开始尝试遵循简单的“绘制立方体” openGl 教程 After final victory over getting OpenGL to work, I still have very veird results.在最终战胜让 OpenGL 工作之后,我仍然有非常好的结果。 My problem is that the objects tend to resize themselves to match the window size.我的问题是对象倾向于调整自己的大小以匹配窗口大小。 Instead, I'd like the window size determine the rendering area - the larger the window is, the more you may see.相反,我希望窗口大小决定渲染区域 - 窗口越大,您看到的越多。

Here are some screenshots of the resizing :以下是调整大小的一些屏幕截图:
Normal size正常尺寸
Resized调整大小
Images kept as links intentionally!图片有意保留为链接!

This auto-resizing behavior brings a question what the coordinates used in OpenGL are.这种自动调整大小的行为带来了一个问题,即 OpenGL 中使用的坐标是什么。

First thing to keep in mind: OpenGL is a drawing API.首先要记住:OpenGL 是一个绘图 API。 It doesn't maintain a scene or something like that.它不维护场景或类似的东西。

So what OpenGL does is, it maps geometry input coordinates in the form of vertex attributes to screen space.所以 OpenGL 所做的是,它将几何输入坐标以顶点属性的形式映射到屏幕空间。 In the old fixed function there's a special vertex attribute called "vertex position" or just short "vertex" (the actual vertex is more than just position).在旧的固定函数中有一个特殊的顶点属性,称为“顶点位置”或简称“顶点”(实际顶点不仅仅是位置)。

The position is transformed to what's usually called "screen" space (but depending on where the viewport is placed, it might as well be called "window" or "viewport) space) in a three step process:在三个步骤的过程中,位置被转换为通常称为“屏幕”空间(但根据视口的放置位置,它也可能被称为“窗口”或“视口”空间):

1. Transformation into view/eye space: This is done by multiplying the vertex position with the modelview matrix. 1. 转换到视图/眼睛空间:这是通过将顶点位置与模型视图矩阵相乘来完成的。

Certain further calculations, like illumination calculation are done in view space.某些进一步的计算,如照明计算是在视图空间中完成的。

2. Transformation to clip space: The view space position is transformed into clip space. 2.转换到剪辑空间:将视图空间位置转换为剪辑空间。 This is usually called the projection and aptly the matrix describing this transformation is called the projection matrix这通常被称为投影,描述这种变换的矩阵被称为投影矩阵

In clip space some special things happen, summarized as clipping, you don't have to worry about yet.在剪辑空间中会发生一些特殊的事情,总结为剪辑,您还不必担心。

3. In the final step transformed the clipped geometry into normalized device coordinates (NDC). 3. 在最后一步中,将裁剪后的几何图形转换为标准化设备坐标 (NDC)。 NDC space is practically a 1:1 mapping toward the viewport, ie the limits of the NDC volume directly correspond to the offset and dimension of the viewport set with glViewport. NDC 空间实际上是朝向视口的 1:1 映射,即 NDC 体积的限制直接对应于使用 glViewport 设置的视口的偏移和尺寸。

You can't change the way the 3rd step happens, and the 1st step is reserved for transforming stuff into view space.你不能改变第三步发生的方式,第一步被保留用于将东西转换成视图空间。 So any adjustments must happen in the 2nd step.因此,任何调整都必须在第 2 步中进行。

So here's what you have to do: The projection limits must be directly proportional to the viewport extents.所以这是你必须做的:投影限制必须与视口范围成正比。 Like this for example像这样例如

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-width/2, width/2, -height/2, height/2, -1, 1);

Oh, and just on a general note: You should always set the viewport and projection setup in the drawing function, too.哦,只是一般注意事项:您也应该始终在绘图功能中设置视口和投影设置。 If you see a tutorial that puts those statements in a window resize handler, just disregard it and just do it in the drawing code anyway.如果您看到将这些语句放在窗口调整大小处理程序中的教程,请忽略它并在绘图代码中执行它。 On the long term this really simplifies things.从长远来看,这确实简化了事情。

The interesting part:有趣的部分:

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
glOrtho( -1 * w, 1 * w, -1 * h, 1 * h, 10, -10);

glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); 

In context:在上下文中:

#include <GL/glut.h>

void display();
void specialKeys();

double rotate_y=0; 
double rotate_x=0;

void display(){
   //  Clear screen and Z-buffer
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
  double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
  glOrtho( -1 * w, 1 * w, -1 * h, 1 * h, 10, -10);

  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity(); 

  // Rotate when user changes rotate_x and rotate_y
  glRotatef( rotate_x, 1.0, 0.0, 0.0 );
  glRotatef( rotate_y, 0.0, 1.0, 0.0 );

  //Multi-colored side - FRONT
  glBegin(GL_POLYGON);

  glColor3f( 1.0, 0.0, 0.0 );     glVertex3f(  0.5, -0.5, -0.5 );      // P1 is red
  glColor3f( 0.0, 1.0, 0.0 );     glVertex3f(  0.5,  0.5, -0.5 );      // P2 is green
  glColor3f( 0.0, 0.0, 1.0 );     glVertex3f( -0.5,  0.5, -0.5 );      // P3 is blue
  glColor3f( 1.0, 0.0, 1.0 );     glVertex3f( -0.5, -0.5, -0.5 );      // P4 is purple

  glEnd();

  // White side - BACK
  glBegin(GL_POLYGON);
  glColor3f(   1.0,  1.0, 1.0 );
  glVertex3f(  0.5, -0.5, 0.5 );
  glVertex3f(  0.5,  0.5, 0.5 );
  glVertex3f( -0.5,  0.5, 0.5 );
  glVertex3f( -0.5, -0.5, 0.5 );
  glEnd();

  // Purple side - RIGHT
  glBegin(GL_POLYGON);
  glColor3f(  1.0,  0.0,  1.0 );
  glVertex3f( 0.5, -0.5, -0.5 );
  glVertex3f( 0.5,  0.5, -0.5 );
  glVertex3f( 0.5,  0.5,  0.5 );
  glVertex3f( 0.5, -0.5,  0.5 );
  glEnd();

  // Green side - LEFT
  glBegin(GL_POLYGON);
  glColor3f(   0.0,  1.0,  0.0 );
  glVertex3f( -0.5, -0.5,  0.5 );
  glVertex3f( -0.5,  0.5,  0.5 );
  glVertex3f( -0.5,  0.5, -0.5 );
  glVertex3f( -0.5, -0.5, -0.5 );
  glEnd();

  // Blue side - TOP
  glBegin(GL_POLYGON);
  glColor3f(   0.0,  0.0,  1.0 );
  glVertex3f(  0.5,  0.5,  0.5 );
  glVertex3f(  0.5,  0.5, -0.5 );
  glVertex3f( -0.5,  0.5, -0.5 );
  glVertex3f( -0.5,  0.5,  0.5 );
  glEnd();

  // Red side - BOTTOM
  glBegin(GL_POLYGON);
  glColor3f(   1.0,  0.0,  0.0 );
  glVertex3f(  0.5, -0.5, -0.5 );
  glVertex3f(  0.5, -0.5,  0.5 );
  glVertex3f( -0.5, -0.5,  0.5 );
  glVertex3f( -0.5, -0.5, -0.5 );
  glEnd();

  glFlush();
  glutSwapBuffers();
}

void specialKeys( int key, int x, int y ) {
   //  Right arrow - increase rotation by 5 degree
  if (key == GLUT_KEY_RIGHT)
    rotate_y += 5;

  //  Left arrow - decrease rotation by 5 degree
  else if (key == GLUT_KEY_LEFT)
    rotate_y -= 5;

  else if (key == GLUT_KEY_UP)
    rotate_x += 5;

  else if (key == GLUT_KEY_DOWN)
    rotate_x -= 5;

  //  Request display update
  glutPostRedisplay();
}

int main(int argc, char* argv[]){
  //  Initialize GLUT and process user parameters
  glutInit(&argc,argv);

  //  Request double buffered true color window with Z-buffer
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

  // Create window
  glutCreateWindow("Awesome Cube");

  //  Enable Z-buffer depth test
  glEnable(GL_DEPTH_TEST);

  // Callback functions
  glutDisplayFunc(display);
  glutSpecialFunc(specialKeys);

  //  Pass control to GLUT for events
  glutMainLoop();

  //  Return to OS
  return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM