developer tip

OpenGL에서 "즉시 모드"는 무엇을 의미합니까?

copycodes 2020. 10. 21. 08:13
반응형

OpenGL에서 "즉시 모드"는 무엇을 의미합니까?


"즉시 모드"란 무엇입니까? 코드 예제를 제공하십시오.

유지 모드 대신 즉시 모드를 사용해야하는 경우는 언제입니까? 각 방법의 장단점은 무엇입니까?


"직접 모드"의 한 예는 사용 glBeginglEnd함께 glVertex그들 사이입니다. "직접 모드"의 또 다른 예는 사용하는 glDrawArrays클라이언트 정점 배열 (즉, 함께 하지 정점 버퍼 객체).

일반적으로 즉시 모드 (첫 번째 "hello world"프로그램 제외)를 사용하고 싶지 않을 것입니다. 이는 더 이상 사용되지 않는 기능이고 최적의 성능을 제공하지 않기 때문입니다.

즉시 모드가 최적이 아닌 이유는 그래픽 카드가 프로그램의 흐름과 직접 연결되기 때문입니다. 드라이버는 GPU에게 glEnd데이터 제출이 언제 완료 될지 알 수없고 해당 데이터도 전송해야하기 때문에 이전 렌더링을 시작하도록 지시 할 수 없습니다 ( 이후 에만 수행 할 수 있음glEnd ).
마찬가지로 클라이언트 정점 배열을 사용하면 드라이버는을 호출하는 순간에만 배열의 복사본을 가져올 수 glDrawArrays있으며 그렇게하는 동안 애플리케이션을 차단해야합니다. 그 이유는 그렇지 않으면 드라이버가 캡처하기 전에 어레이의 메모리를 수정 (또는 해제) 할 수 있기 때문입니다. 데이터가 한 시점에서 정확히 유효하다는 것만 알고 있기 때문에 이전 또는 이후에 해당 작업을 예약 할 수 없습니다.

이와 반대로, 예를 들어 정점 버퍼 객체를 사용하면 버퍼에 데이터를 채우고 OpenGL에 전달합니다. 프로세스는 더 이상이 데이터를 소유하지 않으므로 더 이상 수정할 수 없습니다. 운전자는이 사실에 의존 할 수 있으며 버스가 비어있을 때마다 데이터를 업로드 할 수 있습니다.
나중에 glDrawArrays또는 glDrawElements호출은 작업 대기열로 이동하고 즉시 (실제로 완료되기 전에!) 반환되므로 프로그램은 명령을 계속 제출하는 동시에 드라이버가 하나씩 작동합니다. 또한 운전자가 이미 그렇게 일찍 할 수 있었기 때문에 데이터가 도착할 때까지 기다릴 필요가 없을 것입니다.
따라서 렌더 스레드와 GPU가 비동기 적으로 실행되고 모든 구성 요소가 항상 사용 중이므로 성능이 향상됩니다.

즉시 모드는 사용이 매우 간단하다는 장점이 있지만, 다시 사용되지 않는 방식으로 OpenGL을 올바르게 사용하는 것은 정확히 로켓 과학이 아닙니다. 추가 작업이 거의 필요하지 않습니다.

다음은 즉시 모드의 일반적인 OpenGL "Hello World"코드입니다.

glBegin(GL_TRIANGLES);
    glColor3f(1.0f, 0.0f, 0.0f);   glVertex2f(0.0f,   1.0f);
    glColor3f(0.0f, 1.0f, 0.0f);   glVertex2f(0.87f,  -0.5f);
    glColor3f(0.0f, 0.0f, 1.0f);   glVertex2f(-0.87f, -0.5f);
glEnd();

편집 :
일반적인 요청에 따라 유지 모드의 동일한 내용은 다음과 같습니다.

float verts = {...};
float colors = {...};
static_assert(sizeof(verts) == sizeof(colors), "");

// not really needed for this example, but mandatory in core profile after GL 3.2
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

GLuint buf[2];
glGenBuffers(2, buf);

// assuming a layout(location = 0) for position and 
// layout(location = 1) for color in the vertex shader

// vertex positions
glBindBuffer(GL_ARRAY_BUFFER, buf[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

// copy/paste for color... same code as above. A real, non-trivial program would
// normally use a single buffer for both -- usually with stride (5th param) to
// glVertexAttribPointer -- that presumes interleaving the verts and colors arrays.
// It's somewhat uglier but has better cache performance (ugly does however not
// matter for a real program, since data is loaded from a modelling-tool generated
// binary file anyway).
glBindBuffer(GL_ARRAY_BUFFER, buf[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glEnableVertexAttribArray(1); 
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);

glDrawArrays(GL_TRIANGLES, 0, 3); 

실행 가능 유지 예제

Damon 핵심 부품 을 제공 했지만 저와 같은 newbs는 완전한 실행 가능한 예제를 찾고있을 것입니다.

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

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

#include <GLFW/glfw3.h>

#define INFOLOG_LEN 512

static const GLuint WIDTH = 800, HEIGHT = 600;
/* vertex data is passed as input to this shader
 * ourColor is passed as input to the to the fragment shader.
*/
static const GLchar* vertexShaderSource =
    "#version 330 core\n"
    "layout (location = 0) in vec3 position;\n"
    "layout (location = 1) in vec3 color;\n"
    "out vec3 ourColor;\n"
    "void main() {\n"
    "    gl_Position = vec4(position, 1.0f);\n"
    "    ourColor = color;\n"
    "}\n";
static const GLchar* fragmentShaderSource =
    "#version 330 core\n"
    "in vec3 ourColor;\n"
    "out vec4 color;\n"
    "void main() {\n"
    "    color = vec4(ourColor, 1.0f);\n"
    "}\n";
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) {
    glfwInit();
    GLFWwindow* 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);

    /* Build and compile shader program. */
    /* Vertex shader */
    GLint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    GLint success;
    GLchar infoLog[INFOLOG_LEN];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, INFOLOG_LEN, NULL, infoLog);
        printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
    }
    /* Fragment shader */
    GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, INFOLOG_LEN, NULL, infoLog);
        printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
    }
    /* Link shaders */
    GLint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, INFOLOG_LEN, NULL, infoLog);
        printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    GLuint vbo, vao;
    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(shaderProgram);
        glBindVertexArray(vao);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glBindVertexArray(0);
        glfwSwapBuffers(window);
    }
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glfwTerminate();
    return EXIT_SUCCESS;
}

Ubuntu 18.10 :

sudo apt-get install libglew-dev libglfw3-dev
gcc main.c -lGL -lGLEW -lglfw

즉시 "동등":

glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.5f, -0.5.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-0.5f, -0.5f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glEnd();

이 예제는 여기 에서 적용 됩니다 .

대부분의 "최신"OpenGL 튜토리얼은 일반적으로 모드와 GLFW를 유지하며 다음에서 많은 예제를 찾을 수 있습니다.

참고URL : https://stackoverflow.com/questions/6733934/what-does-immediate-mode-mean-in-opengl

반응형