What does "instant mode" mean in OpenGL?

What is instant mode? Give an example code.

When do I need to use instant mode instead of saved mode? What are the advantages and disadvantages of using each method?

+66
opengl
Jul 18 2018-11-18T00:
source share
2 answers

One example of "immediate mode" uses glBegin and glEnd with glVertex between. Another example of "immediate mode" is the use of glDrawArrays with an array of client vertices (i.e. not a vertex object object).

Normally, you will never want to use immediate mode (with the possible exception, perhaps, for your first hello world program), because this is outdated functionality and does not provide optimal performance.

The reason that immediate mode is not optimal is because the graphics card is directly connected to your program stream. The driver cannot say that the GPU will start rendering before glEnd , because it does not know when you are finished submitting data, and it also needs to transfer this data (which can only be done after glEnd ).
Similarly, with an array of client vertices, a driver can only retrieve a copy of your array when glDrawArrays , and it should block your application. The reason is that otherwise you could modify (or free) the memory of the array before the driver grabs it. He cannot plan this operation sooner or later, since he only knows that the data is valid at exactly one point in time.

In contrast, if you use, for example, a vertex buffer object, you fill the buffer with data and pass it to OpenGL. Your process no longer owns this data and therefore cannot change it. The driver can rely on this fact and can (even speculatively) download data whenever the bus is free.
Any of your later calls to glDrawArrays or glDrawElements will simply go into the work queue and return immediately (before the actual termination!), So your program continues to send commands while the driver runs one by one. They also probably do not need to wait until the data arrives, because the driver could already do this much earlier.
Thus, rendering threads and GPUs is performed asynchronously, each component is always busy, which provides better performance.

Immediate mode has the advantage of being dead, easy to use, but using OpenGL in a properly not obsolete way is not exactly rocket science - it requires very little extra work.

Here is a typical OpenGL "Hello World" code in immediate mode:

 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:
By common request, the same in saved mode will look something like this:

 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 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); 
+118
Jul 18 2018-11-17T00:
source share

Managed Saved Example

Damon provided key parts, but beginners like me will be looking for a complete executable example.

jneqT.png

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

In Ubuntu 15.10:

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

The immediate "equivalent":

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

This example is adapted from here .

Most of the "modern" OpenGL guides usually keep the mode and GLFW, you will find many examples:

+6
Mar 22 '16 at 22:17
source share



All Articles