2010-04-03 12 views
65

मैं glOrtho के उपयोग को समझ नहीं सकता। क्या कोई समझा सकता है कि इसका क्या उपयोग किया जाता है?ग्लोथो() के उपयोग की व्याख्या करें?

अद्यतन

यह एक्स y के सीमा निर्धारित करने के लिए प्रयोग किया जाता है और z सीमा निर्देशांक?

glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 

इसका मतलब है कि एक्स, वाई और जेड रेंज -1 से 1 है?

+0

[यह] (https://www.youtube.com/watch?v=8ryJMO6rBT4) वीडियो ने मुझे बहुत मदद की। – ViniciusArruda

उत्तर

117

इस तस्वीर पर एक नज़र डालें। इससे कोई फर्क नहीं पड़ता कि जेड दिशा में कितने दूर वर्टेक्स हैं, वे दूरी में नहीं आ जाएंगे।

मैं glOrtho का उपयोग हर बार जब मैं ओपन में 2 डी ग्राफिक्स करने की ज़रूरत हर बार निम्नलिखित कोड का उपयोग कर (जैसे स्वास्थ्य सलाखों, मेनू आदि) खिड़की आकार दिया जाता है:

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(0.0f, windowWidth, windowHeight, 0.0f, 0.0f, 1.0f); 

यह ओपन पुन: मैप होगा समकक्ष पिक्सेल मानों में समन्वय करता है (एक्स 0 से विंडोविड्थ और वाई 0 से विंडोहेइट तक जा रहा है)। ध्यान दें कि मैंने वाई मानों को फ़्लिप कर दिया है क्योंकि ओपनजीएल निर्देशांक विंडो के निचले बाएं कोने से शुरू होते हैं। तो फ़्लिप करके, मुझे खिड़की के ऊपरी बाएं कोने में शुरू होने वाला एक और पारंपरिक (0,0) मिलता है।

+3

इस मुद्दे को स्पष्ट करने के लिए बहुत बहुत धन्यवाद! :) – ufk

+74

ओह मेरे भगवान मैं तुमसे प्यार करता हूँ। क्या आपको कोई विचार है कि ऑनलाइन कोड की इस पंक्ति को खोजने/समझने में कितना समय लगता है? धन्यवाद, मैं इस – karpathy

+1

के लिए आपके पहले पैदा हुए बच्चे का नाम दूंगा नोट: (एंड्रॉइड पर) भले ही मॉडल में केवल नकारात्मक z मान हों, ऐसा लगता है कि अंतिम (दूर) पैरामीटर के लिए सकारात्मक मान होना आवश्यक है। मैंने 'z = -2' पर शिखर के साथ, एक सरल त्रिकोण परीक्षण (अक्षम करने के साथ) किया था। त्रिकोण तब अदृश्य था जब मैंने 'ग्लोथो (.., 0.0 एफ, -4.0 एफ); ',' ..- 1.0 एफ, -3.0 एफ) ', या' ..- 3.0 एफ, -1.0 एफ) '। दिखाई देने के लिए, दूर पैरामीटर सकारात्मक 2 या अधिक होना था; यह कोई फर्क नहीं पड़ता कि पास पैरामीटर क्या था। इनमें से कोई भी काम करता है: '..0.0 एफ, 2.0 एफ)', '..- 1.0 एफ, 2.0 एफ)', '..- 3.0 एफ, 2.0 एफ)', या '..0.0f, 1000.0f' । – ToolmakerSteve

3

glOrtho एक परिवर्तन है कि एक समानांतर प्रक्षेपण का उत्पादन वर्णन करता है। वर्तमान मैट्रिक्स (glMatrixMode देखें) इस मैट्रिक्स से गुणा किया जाता है और परिणाम वर्तमान मैट्रिक्स की जगह है, जैसे कि glMultMatrix अपने तर्क के रूप में निम्नलिखित मैट्रिक्स के साथ बुलाया गया:

OpenGL documentation (मेरी बोल्ड)

संख्या क्लिपिंग विमानों (बाएं, दाएं, नीचे, ऊपर, पास और दूर) के स्थानों को परिभाषित करें।

"सामान्य" प्रक्षेपण एक परिप्रेक्ष्य प्रक्षेपण है जो गहराई का भ्रम प्रदान करता है।

समानांतर अनुमानों कि दोनों वास्तविकता में और प्रक्षेपण विमान में समानांतर हैं प्रक्षेपण की तर्ज है: Wikipedia एक समानांतर प्रक्षेपण के रूप में परिभाषित करता है।

समांतर प्रक्षेपण एक अनुमानित दृष्टिकोण के साथ एक परिप्रेक्ष्य प्रक्षेपण के अनुरूप है- उदाहरण के लिए, जहां कैमरा ऑब्जेक्ट से एक अनंत दूरी दूर है और इसमें अनंत फोकल लम्बाई या "ज़ूम" है। Graphical Projections enter image description here

glOrtho आदेश एक "तिर्यक" प्रक्षेपण है कि आप नीचे की पंक्ति में देखते हैं पैदा करता है:

+0

हाय जानकारी के लिए धन्यवाद। मैं समांतर और परिप्रेक्ष्य प्रक्षेपण के बीच अंतर को समझ नहीं पाया। मैंने थोड़ा गुमराह किया और जवाब http://wiki.answers.com/Q/What_is_the_difference_between_orthogonal_and_perspective_projection – ufk

+6

दुर्भाग्यवश उत्तर.com से प्राप्त जानकारी बहुत बेकार है। एक आइसोमेट्रिक व्यू, उदाहरण के लिए, बहुत 3-डी है, फिर भी यह परिप्रेक्ष्य के बिना समानांतर प्रक्षेपण है। यहां देखें, और अनुमानों के कई अन्य उदाहरणों के लिंक भी हैं: http://en.wikipedia.org/wiki/Isometric_projection –

32

glOrtho: 2 डी खेल, करीब वस्तुओं और अब तक एक ही आकार के दिखाई देते हैं:

glFrustrum: 3 डी की तरह अधिक वास्तविक जीवन, समान वस्तुओं और दूर दिखाई छोटे:

कोड

#include <stdlib.h> 

#include <GL/gl.h> 
#include <GL/glu.h> 
#include <GL/glut.h> 

static int ortho = 0; 

static void display(void) { 
    glClear(GL_COLOR_BUFFER_BIT); 
    glLoadIdentity(); 
    if (ortho) { 
    } else { 
     /* This only rotates and translates the world around to look like the camera moved. */ 
     gluLookAt(0.0, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
    } 
    glColor3f(1.0f, 1.0f, 1.0f); 
    glutWireCube(2); 
    glFlush(); 
} 

static void reshape(int w, int h) { 
    glViewport(0, 0, w, h); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    if (ortho) { 
     glOrtho(-2.0, 2.0, -2.0, 2.0, -1.5, 1.5); 
    } else { 
     glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); 
    } 
    glMatrixMode(GL_MODELVIEW); 
} 

int main(int argc, char** argv) { 
    glutInit(&argc, argv); 
    if (argc > 1) { 
     ortho = 1; 
    } 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
    glutInitWindowSize(500, 500); 
    glutInitWindowPosition(100, 100); 
    glutCreateWindow(argv[0]); 
    glClearColor(0.0, 0.0, 0.0, 0.0); 
    glShadeModel(GL_FLAT); 
    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 
    glutMainLoop(); 
    return EXIT_SUCCESS; 
} 

स्कीमा

ऑर्थो: कैमरा एक विमान है, दिखाई मात्रा एक आयत:

enter image description here

Frustrum:

: कैमरा एक बिंदु, दिखाई मात्रा एक पिरामिड का एक टुकड़ा है

enter image description here

Image source

पैरामीटर

हम हमेशा साथ + y ऊपर की तरफ -z लिए + z से देख रहे हैं:

glOrtho(left, right, bottom, top, near, far) 
  • left: न्यूनतम x हम
  • right देखें: अधिकतम x हम देखते हैं
  • bottom: minim उम y हम देखते हैं
  • top: अधिकतम y हम
  • -near देखें: न्यूनतम z हम देखते हैं। हां, यह -1 बार near है। तो एक नकारात्मक इनपुट का अर्थ सकारात्मक z है।
  • -far: अधिकतम z हम देखते हैं। नकारात्मक भी।

स्कीमा:

Image source

यह कैसे, ओपन हमेशा "का उपयोग करता है" हुड

तहत काम करता है अंत में:

glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 

अगर हम न glOrtho है और न ही glFrustrum उपयोग करते हैं, कि हम क्या मिलता है।

glOrtho और glFrustrum सिर्फ रैखिक परिवर्तनों हैं (उर्फ आव्यूह गुणन) ऐसी है कि:

  • glOrtho: डिफ़ॉल्ट घन
  • glFrustrum में एक दिया 3 डी आयत लेता है: डिफ़ॉल्ट घन में एक दिया पिरामिड खंड लेता है

यह परिवर्तन तब सभी vertexes लिए आवेदन किया है। यह मैं 2 डी में क्या मतलब है:

Image source

परिवर्तन के बाद अंतिम चरण सरल है:

  • घन (culling) के बाहर किसी भी अंक निकालने के लिए: बस यह सुनिश्चित करें कि x, y और z[-1, +1]
  • में हैं z घटक ध्यान न दें और केवल ले x और y, जिसे अब 2 डी स्क्रीन

के साथ रखा जा सकता है, z को अनदेखा किया गया है, इसलिए आप हमेशा 0 का उपयोग कर सकते हैं।

एक कारण है कि आप z != 0 का उपयोग करना चाहते हैं, sprites को गहराई बफर के साथ पृष्ठभूमि छुपाएं।

डेप्रिकेशन

glOrthoOpenGL 4.5 के रूप में हटा दिया गया है: संगतता प्रोफाइल 12.1। "फिक्स्ड-फंक्शन वर्टेक्स ट्रांसफरेशन" लाल रंग में है।

तो उत्पादन के लिए इसका उपयोग न करें। किसी भी मामले में, समझना कुछ ओपनजीएल अंतर्दृष्टि प्राप्त करने का एक अच्छा तरीका है।

आधुनिक ओपनजीएल 4 प्रोग्राम सीपीयू पर रूपांतरण मैट्रिक्स (जो छोटा है) की गणना करते हैं, और उसके बाद मैट्रिक्स और सभी बिंदुओं को ओपनजीएल में परिवर्तित किया जाता है, जो अलग-अलग बिंदुओं के लिए हजारों मैट्रिक्स गुणाओं को वास्तव में समानांतर में कर सकता है ।

मैन्युअल रूप से vertex shaders लिखा गया है, तो ओपनजीएल छायांकन भाषा के सुविधाजनक वेक्टर डेटा प्रकारों के साथ आमतौर पर गुणा को स्पष्ट रूप से करें।

चूंकि आप स्पष्ट रूप से शेडर लिखते हैं, इससे आपको अपनी आवश्यकताओं के लिए एल्गोरिदम को ट्विक करने की अनुमति मिलती है। इस तरह की लचीलापन अधिक आधुनिक जीपीयू की एक प्रमुख विशेषता है, जो पुराने इनपुट के साथ कुछ इनपुट पैरामीटर के साथ एक निश्चित एल्गोरिदम था, अब मनमानी गणना कर सकते हैं।यह भी देखें: https://stackoverflow.com/a/36211337/895245

एक स्पष्ट GLfloat transform[] के साथ यह कुछ इस तरह दिखेगा:

#include <math.h> 
#include <stdio.h> 
#include <stdlib.h> 

#define GLEW_STATIC 
#include <GL/glew.h> 

#include <GLFW/glfw3.h> 

#include "common.h" 

static const GLuint WIDTH = 800; 
static const GLuint HEIGHT = 600; 
/* ourColor is passed on to the fragment shader. */ 
static const GLchar* vertex_shader_source = 
    "#version 330 core\n" 
    "layout (location = 0) in vec3 position;\n" 
    "layout (location = 1) in vec3 color;\n" 
    "out vec3 ourColor;\n" 
    "uniform mat4 transform;\n" 
    "void main() {\n" 
    " gl_Position = transform * vec4(position, 1.0f);\n" 
    " ourColor = color;\n" 
    "}\n"; 
static const GLchar* fragment_shader_source = 
    "#version 330 core\n" 
    "in vec3 ourColor;\n" 
    "out vec4 color;\n" 
    "void main() {\n" 
    " color = vec4(ourColor, 1.0f);\n" 
    "}\n"; 
static GLfloat vertices[] = { 
/* Positions   Colors */ 
    0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 
    -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 
    0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f 
}; 

int main(void) { 
    GLint shader_program; 
    GLint transform_location; 
    GLuint vbo; 
    GLuint vao; 
    GLFWwindow* window; 
    double time; 

    glfwInit(); 
    window = glfwCreateWindow(WIDTH, HEIGHT, __FILE__, NULL, NULL); 
    glfwMakeContextCurrent(window); 
    glewExperimental = GL_TRUE; 
    glewInit(); 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    glViewport(0, 0, WIDTH, HEIGHT); 

    shader_program = common_get_shader_program(vertex_shader_source, fragment_shader_source); 

    glGenVertexArrays(1, &vao); 
    glGenBuffers(1, &vbo); 
    glBindVertexArray(vao); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
    /* Position attribute */ 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); 
    glEnableVertexAttribArray(0); 
    /* Color attribute */ 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); 
    glEnableVertexAttribArray(1); 
    glBindVertexArray(0); 

    while (!glfwWindowShouldClose(window)) { 
     glfwPollEvents(); 
     glClear(GL_COLOR_BUFFER_BIT); 

     glUseProgram(shader_program); 
     transform_location = glGetUniformLocation(shader_program, "transform"); 
     /* THIS is just a dummy transform. */ 
     GLfloat transform[] = { 
      0.0f, 0.0f, 0.0f, 0.0f, 
      0.0f, 0.0f, 0.0f, 0.0f, 
      0.0f, 0.0f, 1.0f, 0.0f, 
      0.0f, 0.0f, 0.0f, 1.0f, 
     }; 
     time = glfwGetTime(); 
     transform[0] = 2.0f * sin(time); 
     transform[5] = 2.0f * cos(time); 
     glUniformMatrix4fv(transform_location, 1, GL_FALSE, transform); 

     glBindVertexArray(vao); 
     glDrawArrays(GL_TRIANGLES, 0, 3); 
     glBindVertexArray(0); 
     glfwSwapBuffers(window); 
    } 
    glDeleteVertexArrays(1, &vao); 
    glDeleteBuffers(1, &vbo); 
    glfwTerminate(); 
    return EXIT_SUCCESS; 
} 

जेनरेट किए गए उत्पादन: http://imgur.com/QVW14Gu

glOrtho के लिए मैट्रिक्स वास्तव में सरल है, केवल स्केलिंग और अनुवाद से बना है:

scalex, 0,  0,  translatex, 
0,  scaley, 0,  translatey, 
0,  0,  scalez, translatez, 
0,  0,  0,  1 

जैसा कि OpenGL 2 docs में उल्लिखित है।

glFrustum matrix हाथ से गणना करना बहुत कठिन नहीं है, लेकिन परेशान होना शुरू हो जाता है। ध्यान दें कि कैसे छिन्नक केवल पर स्केलिंग और glOrtho तरह अनुवाद, अधिक जानकारी के साथ नहीं किया जा सकता: https://gamedev.stackexchange.com/a/118848/25171

GLM ओपन सी ++ गणित पुस्तकालय ऐसे मैट्रिक्स की गणना के लिए एक लोकप्रिय पसंद है। http://glm.g-truc.net/0.9.2/api/a00245.html दस्तावेज ortho और frustum संचालन दोनों दस्तावेज।

+1

"इसके बजाय क्या उपयोग किया जाना चाहिए?" - अपनी खुद की matrices का निर्माण और उन्हें सीधे असाइन करें। – Kromster

संबंधित मुद्दे