簡體   English   中英

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

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

我剛開始嘗試遵循簡單的“繪制立方體” openGl 教程 在最終戰勝讓 OpenGL 工作之后,我仍然有非常好的結果。 我的問題是對象傾向於調整自己的大小以匹配窗口大小。 相反,我希望窗口大小決定渲染區域 - 窗口越大,您看到的越多。

以下是調整大小的一些屏幕截圖:
正常尺寸
調整大小
圖片有意保留為鏈接!

這種自動調整大小的行為帶來了一個問題,即 OpenGL 中使用的坐標是什么。

首先要記住:OpenGL 是一個繪圖 API。 它不維護場景或類似的東西。

所以 OpenGL 所做的是,它將幾何輸入坐標以頂點屬性的形式映射到屏幕空間。 在舊的固定函數中有一個特殊的頂點屬性,稱為“頂點位置”或簡稱“頂點”(實際頂點不僅僅是位置)。

在三個步驟的過程中,位置被轉換為通常稱為“屏幕”空間(但根據視口的放置位置,它也可能被稱為“窗口”或“視口”空間):

1. 轉換到視圖/眼睛空間:這是通過將頂點位置與模型視圖矩陣相乘來完成的。

某些進一步的計算,如照明計算是在視圖空間中完成的。

2.轉換到剪輯空間:將視圖空間位置轉換為剪輯空間。 這通常被稱為投影,描述這種變換的矩陣被稱為投影矩陣

在剪輯空間中會發生一些特殊的事情,總結為剪輯,您還不必擔心。

3. 在最后一步中,將裁剪后的幾何圖形轉換為標准化設備坐標 (NDC)。 NDC 空間實際上是朝向視口的 1:1 映射,即 NDC 體積的限制直接對應於使用 glViewport 設置的視口的偏移和尺寸。

你不能改變第三步發生的方式,第一步被保留用於將東西轉換成視圖空間。 因此,任何調整都必須在第 2 步中進行。

所以這是你必須做的:投影限制必須與視口范圍成正比。 像這樣例如

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

哦,只是一般注意事項:您也應該始終在繪圖功能中設置視口和投影設置。 如果您看到將這些語句放在窗口調整大小處理程序中的教程,請忽略它並在繪圖代碼中執行它。 從長遠來看,這確實簡化了事情。

有趣的部分:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM