【问题标题】:What the OpenGL coordinates are? Ignore OpenGL window sizeOpenGL坐标是什么?忽略 OpenGL 窗口大小
【发布时间】:2013-03-31 00:36:12
【问题描述】:

我刚开始尝试遵循简单的“绘制立方体”openGl tutorial。在最终战胜了让 OpenGL 工作之后,我仍然有非常糟糕的结果。我的问题是对象倾向于调整自己的大小以匹配窗口大小。相反,我希望窗口大小决定渲染区域 - 窗口越大,您看到的越多。

以下是调整大小的一些屏幕截图:
Normal size
Resized
图片故意保留为链接!

这种自动调整大小的行为带来了一个问题,OpenGL 中使用的坐标是什么。

【问题讨论】:

  • 看看这个question。我认为它解决了您的问题。

标签: c++ opengl freeglut obsolete


【解决方案1】:

首先要记住:OpenGL 是一个绘图 API。它不保留场景或类似的东西。

所以 OpenGL 所做的是将几何输入坐标以顶点属性的形式映射到屏幕空间。在旧的固定函数中,有一个特殊的顶点属性,称为“顶点位置”或简称“顶点”(实际顶点不仅仅是位置)。

通过三个步骤将位置转换为通常称为“屏幕”空间(但取决于视口的放置位置,也可能称为“窗口”或“视口)空间):

1。转换为视图/眼睛空间:这是通过将顶点位置与模型视图矩阵相乘来完成的。

某些进一步的计算,例如照明计算是在视图空间中完成的。

2。转换为剪辑空间:将视图空间位置转换为剪辑空间。这通常称为投影,描述这种变换的矩阵恰当地称为投影矩阵

在剪辑空间中会发生一些特殊的事情,总结为剪辑,您不必担心。

3。在最后一步中,将剪裁的几何图形转换为标准化的设备坐标 (NDC)。 NDC 空间实际上是与视口的 1:1 映射,即 NDC 体积的限制直接对应于 glViewport 设置的视口的偏移量和尺寸。

您无法更改第 3 步的发生方式,第 1 步保留用于将内容转换为视图空间。所以任何调整都必须发生在第二步。

因此,您必须这样做:投影限制必须与视口范围成正比。比如这样

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

哦,只是一般性说明:您也应该始终在绘图函数中设置视口和投影设置。如果您看到将这些语句放在窗口调整大小处理程序中的教程,请忽略它并在绘图代码中执行它。从长远来看,这确实简化了事情。

【讨论】:

  • 我喜欢你的一般说明,但我的问题是我完全不知道如何获得窗口尺寸(将谷歌搜索,但我害怕准备展示的新邪恶功能我是多么蹩脚)以及如何将它应用到gluPerspective(在等待回复时在互联网上发现)只需要宽度/高度 - 所以调整大小会导致缩放(也许可以使用一些翻译,但这是正确的吗? )。
  • 好吧,genpfault 发布了您所解释的内容,所以我的资源已经完成。谢谢你:)
  • @TomášZato:窗口尺寸超出了 OpenGL 的范围。您可能正在使用 GLFW、GLUT 或 SDL 之类的框架(您链接的教程使用 GLUT)。 glutGet(GLUT_WINDOW_WIDTH) 和 glutGet(GLUT_WINDOW_HEIGHT) 就是你要找的。​​span>
【解决方案2】:

有趣的部分:

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

在上下文中:

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

【讨论】:

  • 谢谢!这段代码对我有很多启发:) 我会尝试应用它。
  • 请问为什么 glMatrixMode 被调用了两次?为什么窗口大小除以 300?
  • 一次切换到投影矩阵堆栈,一次切换到模型视图堆栈。从技术上讲,您可以使用一个but you really shouldn't do that。 GLUT 默认为 300x300 像素窗口(并且您没有通过 glutInitWindowSize() 覆盖)所以我认为这是您想要坚持的大小。
猜你喜欢
  • 2015-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-25
  • 1970-01-01
  • 2010-10-31
  • 2013-02-09
  • 1970-01-01
相关资源
最近更新 更多