Que signifie «mode immédiat» dans OpenGL?

Qu’est-ce que le “mode immédiat”? Donnez un exemple de code.

Quand dois-je utiliser le mode immédiat au lieu du mode conservé? Quels sont les avantages et les inconvénients de l’utilisation de chaque méthode?

Un exemple de “mode immédiat” consiste à utiliser glBegin et glEnd avec glVertex entre eux. Un autre exemple de “mode immédiat” est d’utiliser glDrawArrays avec un tableau de vertex client (c’est-à-dire pas un object tampon de vertex).

En général, vous ne voudrez jamais utiliser le mode immédiat (sauf peut-être pour votre premier programme “hello world”) car il s’agit d’une fonctionnalité obsolète qui n’offre pas des performances optimales.

La raison pour laquelle le mode immédiat n’est pas optimal est que la carte graphique est directement liée au stream de votre programme. Le pilote ne peut pas glEnd au GPU de commencer le rendu avant glEnd , car il ne sait pas quand vous glEnd soumettre des données, et il doit également transférer ces données (ce qu’il ne peut faire qu’après glEnd ).
De même, avec un tableau de vertex client, le pilote ne peut extraire qu’une copie de votre tableau au moment où vous appelez glDrawArrays . Il doit alors bloquer votre application. La raison en est que sinon vous pourriez modifier (ou libérer) la mémoire du tableau avant que le pilote ne l’ait capturé. Il ne peut pas planifier cette opération plus tôt ou plus tard, car elle sait uniquement que les données sont valables exactement à un moment donné.

Contrairement à cela, si vous utilisez par exemple un object tampon de sumts, vous remplissez un tampon avec des données et vous le transmettez à OpenGL. Votre processus ne possède plus ces données et ne peut donc plus les modifier. Le conducteur peut compter sur ce fait et peut (même spéculativement) télécharger les données chaque fois que le bus est gratuit.
N’importe lequel de vos appels glDrawArrays ou glDrawElements ultérieurs ira simplement dans une queue de travail et reviendra immédiatement (avant de finir!), Ainsi votre programme continue à soumettre des commandes alors que le pilote travaille en même temps. Ils n’auront probablement pas besoin d’attendre l’arrivée des données, car le pilote pourrait déjà le faire beaucoup plus tôt.
Ainsi, les threads et les GPU exécutés de manière asynchrone, chaque composant est occupé à tout moment, ce qui améliore les performances.

Le mode immédiat a l’avantage d’être simple à utiliser, mais utiliser OpenGL correctement de manière non déconseillée n’est pas non plus un casse-tête: il ne nécessite que très peu de travail supplémentaire.

Voici le code OpenGL “Hello World” typique en mode immédiat:

 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(); 

Modifier:
Par demande commune, la même chose en mode conservé ressemblerait à ceci:

 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); glEnableVertexAtsortingbArray(0); glVertexAtsortingbPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); // copy/paste for color... same code as above. A real, non-sortingvial program would // normally use a single buffer for both -- usually with ssortingde (5th param) to // glVertexAtsortingbPointer -- 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); glEnableVertexAtsortingbArray(1); glVertexAtsortingbPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0); glDrawArrays(GL_TRIANGLES, 0, 3); 

Exemple runnable retenu

Damon a fourni les éléments clés, mais les newbs comme moi chercheront un exemple complet.

 #include  #include  #define GLEW_STATIC #include  #include  #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 comstack shader program. */ /* Vertex shader */ GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glComstackShader(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); glComstackShader(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 atsortingbute */ glVertexAtsortingbPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAtsortingbArray(0); /* Color atsortingbute */ glVertexAtsortingbPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAtsortingbArray(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; } 

Sur Ubuntu 15.10:

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

Immédiat “équivalent”:

 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(); 

Cet exemple est adapté d’ ici .

La plupart des tutoriels OpenGL “modernes” conservent le mode et GLFW, vous trouverez de nombreux exemples à: