OpenGL में glOrtho () का उपयोग कैसे करें?


87

मैं इसका उपयोग नहीं समझ सकता glOrtho। क्या कोई समझा सकता है कि इसका उपयोग किस लिए किया जाता है?

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

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

इसका मतलब है कि x, y और z श्रेणी -1 से 1 है?


1
इस वीडियो ने मुझे बहुत मदद की।
विनीसियस

जवाबों:


153

इस चित्र पर एक नज़र डालें: चित्रमय अनुमान यहाँ छवि विवरण दर्ज करें

glOrthoआदेश एक "तिर्यक" प्रक्षेपण है कि आप नीचे की पंक्ति में देखते हैं पैदा करता है। कोई फर्क नहीं पड़ता कि जेड दिशा में कितनी दूर स्थित हैं, वे दूरी में नहीं उतरेंगे।

जब भी विंडो का आकार बदला जाता है, मैं हर बार निम्न कोड का उपयोग करते हुए OpenGL में 2D ग्राफिक्स (जैसे स्वास्थ्य पट्टी, मेनू आदि) करने की आवश्यकता होती है।

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

यह OpenGL निर्देशांक को समतुल्य पिक्सेल मानों में समन्वयित करेगा (X 0 से windowWidth पर जा रहा है और Y 0 से windowHeight पर जा रहा है)। ध्यान दें कि मैंने Y मानों को फ़्लिप किया है क्योंकि OpenGL निर्देशांक खिड़की के निचले बाएँ कोने से शुरू होते हैं। इसलिए फ्लिप करने से, मुझे खिड़की के शीर्ष बाएं कोने में शुरू होने वाला एक अधिक पारंपरिक (0,0) मिलता है।

ध्यान दें कि Z मान 0 से 1 तक क्लिप किया गया है। इसलिए जब आप अपने शीर्ष स्थान के लिए Z मान निर्दिष्ट करते हैं तो सावधान रहें, यदि यह उस सीमा के बाहर आता है तो इसे क्लिप किया जाएगा। अन्यथा यदि यह उस सीमा के अंदर है, तो यह Z परीक्षणों को छोड़कर स्थिति पर कोई प्रभाव नहीं डालेगा।


90
ओह माय गॉड आई लव यू। क्या आपके पास कोई विचार है कि कोड की इस एकल पंक्ति को खोजने / जानने में कितना समय लगता है? धन्यवाद, मैं इस के लिए आप के बाद अपने पहले जन्मे बच्चे का नाम रखूंगा
karpathy

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

9
यह OpenGl पर खराब ट्यूटोरियल की मात्रा का हास्यास्पद है।
basickarl

1
@ कारी, आशा है कि यह लिंक मदद कर सकता है। > learnopengl.com/# .In
P

1
@mgouin जेड श्रेणी निर्दिष्ट करती है कि आपका जेड-पास विमान और आपका जेड-दूर विमान कहां हैं। जब आप अपनी ज्यामिति बनाते हैं, तो यह Z मान दो Z विमानों के अंदर होना चाहिए। यदि वे Z विमानों के बाहर आते हैं, तो आपकी ज्यामिति अभिलिखित की जाएगी। इसके अलावा आपके रेंडरर में केवल गहराई के लिए एक निश्चित रिज़ॉल्यूशन होता है। यदि आपके पास अपना दूर का विमान 1000 इकाइयों से दूर है और आप एक छोटे से मॉडल की कोशिश करते हैं, जिसके चेहरे एक-दूसरे से 0.1 यूनिट दूर हों, तो ओपनग्लॉट आपको आपकी जरूरत के हिसाब से गहराई देने में सक्षम होगा और आपको जेड-फाइटिंग (चंचलता) मिलेगी। चेहरों के बीच।
माइकपोते

54

न्यूनतम रननीय उदाहरण

glOrtho: 2 डी गेम, ऑब्जेक्ट्स करीब और दूर समान आकार में दिखाई देते हैं:

यहाँ छवि विवरण दर्ज करें

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

यहाँ छवि विवरण दर्ज करें

main.c

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

गिटहब ऊपर

संकलित करें:

gcc -ggdb3 -O0 -o main -std=c99 -Wall -Wextra -pedantic main.c -lGL -lGLU -lglut

साथ चलाएं glOrtho:

./main 1

साथ चलाएं glFrustrum:

./main

उबंटू 18.10 पर परीक्षण किया गया।

योजना

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

यहाँ छवि विवरण दर्ज करें

Frustrum: कैमरा एक बिंदु है, दृश्यमान मात्रा एक पिरामिड का एक टुकड़ा:

यहाँ छवि विवरण दर्ज करें

छवि स्रोत

पैरामीटर

हम हमेशा से + z ऊपर से + y ऊपर की ओर देख रहे हैं:

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

स्कीमा:

छवि स्रोत

यह हुड के नीचे कैसे काम करता है

अंत में, OpenGL हमेशा "उपयोग करता है":

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

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

glOrthoऔर glFrustrumबस रैखिक परिवर्तन (AKA मैट्रिक्स गुणन) ऐसे हैं:

  • glOrtho: डिफॉल्ट क्यूब में दिए गए 3 डी आयत लेता है
  • glFrustrum: किसी दिए गए पिरामिड सेक्शन को डिफॉल्ट क्यूब में लेता है

यह परिवर्तन तब सभी शीर्षों पर लागू होता है। यह मेरा 2 डी में मतलब है:

छवि स्रोत

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

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

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

एक कारण जिसे आप उपयोग करना चाहते हैं, z != 0वह है स्प्राइट्स को बैकग्राउंड को डीप बफर के साथ छिपाना।

प्रतिवाद

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

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

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

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

चूंकि आप स्पष्ट रूप से शेडर लिखते हैं, इससे आप एल्गोरिथ्म को अपनी आवश्यकताओं के अनुरूप बना सकते हैं। इस तरह की लचीलापन अधिक आधुनिक GPUs की एक प्रमुख विशेषता है, जो पुराने लोगों के विपरीत है जो कुछ इनपुट मापदंडों के साथ एक निश्चित एल्गोरिथ्म करते थे, अब मनमानी गणना कर सकते हैं। इसे भी देखें: 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;
}

गिटहब ऊपर

आउटपुट:

यहाँ छवि विवरण दर्ज करें

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

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

जैसा कि ओपन 2 डॉक्स में बताया गया है ।

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

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


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

4

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

OpenGL प्रलेखन (मेरी बोल्ड)

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

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

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

समानांतर प्रक्षेपण एक काल्पनिक दृष्टिकोण के साथ एक परिप्रेक्ष्य प्रक्षेपण से मेल खाता है - उदाहरण के लिए, एक जहां कैमरा वस्तु से एक अनंत दूरी पर है और एक अनंत फोकल लंबाई है, या "ज़ूम" है।


नमस्कार, जानकारी के लिए धन्यवाद। मैं काफी समानांतर और परिप्रेक्ष्य प्रक्षेपण के बीच अंतर नहीं समझ सका। मैंने थोड़ा सा गुगली की
ufk

6
दुर्भाग्य से आपको जो जानकारी answer.com से मिली वह बहुत बेकार है। उदाहरण के लिए, एक आइसोमेट्रिक दृश्य बहुत 3-डी है, फिर भी यह परिप्रेक्ष्य के बिना एक समानांतर प्रक्षेपण है। यहां देखें, और अनुमानों के कई अन्य उदाहरणों के लिंक भी हैं: en.wikipedia.org/wiki/Isometric_projection
बेन Voigt
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.