न्यूनतम रननीय उदाहरण
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 {
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;
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[] = {
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);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
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");
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
संचालन दोनों ।