2 ответов:
одним из примеров "немедленного режима" является использование
glBeginиglEndС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();Edit:
По общему запросу, то же самое в сохраненном режиме будет выглядеть примерно так это: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);
Runnable сохранил пример
Деймон предоставил ключевые части, но новички, такие как я, будут искать полный запускаемый пример.
#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 15.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, вы найдете много примеров в:

Comments