actualizar opengl

actualizar - opengl minecraft



¿Qué significa "modo inmediato" en OpenGL? (2)

¿Qué es el "modo inmediato"? Da un ejemplo de código.

¿Cuándo debo usar el modo inmediato en lugar del modo retenido? ¿Cuáles son los pros y los contras de usar cada método?


Runnable retenido ejemplo

Damon ha proporcionado las partes clave, pero los nuevos como yo buscaremos un ejemplo completo ejecutable.

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

En Ubuntu 15.10:

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

"Equivalente" inmediato

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

Este ejemplo está adaptado desde here .

La mayoría de los tutoriales de OpenGL "modernos" normalmente conservan el modo y GLFW, encontrará muchos ejemplos en:


Un ejemplo de "modo inmediato" es usar glBegin y glEnd con glVertex entre ellos. Otro ejemplo de "modo inmediato" es usar glDrawArrays con una matriz de vértices de cliente (es decir, no un objeto de búfer de vértice).

Por lo general, nunca querrá usar el modo inmediato (excepto tal vez para su primer programa "hello world") porque está en desuso y no ofrece un rendimiento óptimo.

La razón por la cual el modo inmediato no es óptimo es que la tarjeta gráfica está vinculada directamente con el flujo de su programa. El controlador no puede decirle a la GPU que comience a renderizar antes de glEnd , porque no sabe cuándo terminará de enviar datos, y también necesita transferir esos datos (lo cual solo puede hacer después de glEnd ).
De forma similar, con una matriz de vértices de cliente, el controlador solo puede extraer una copia de la matriz en el momento en que llame a glDrawArrays , y debe bloquear su aplicación mientras lo hace. La razón es que, de lo contrario, podría modificar (o liberar) la memoria de la matriz antes de que el controlador la haya capturado. No puede programar esa operación antes o después, porque solo sabe que los datos son válidos exactamente en un punto en el tiempo.

En contraste con eso, si usa, por ejemplo, un objeto de búfer de vértice, llena un búfer con datos y lo entrega a OpenGL. Su proceso ya no posee esta información y, por lo tanto, ya no puede modificarla. El conductor puede confiar en este hecho y puede (incluso de forma especulativa) cargar los datos siempre que el autobús esté libre.
Cualquiera de sus llamadas a glDrawArrays o glDrawElements posteriores simplemente irá a una cola de trabajo y regresará inmediatamente (¡antes de terminar realmente!), Por lo que su programa sigue enviando comandos mientras que el controlador funciona uno por uno. También es probable que no tengan que esperar a que lleguen los datos, porque el conductor ya podría hacer eso mucho antes.
Por lo tanto, el subproceso de representación y la GPU se ejecutan de forma asíncrona, cada componente está ocupado en todo momento, lo que produce un mejor rendimiento.

El modo inmediato tiene la ventaja de ser muy fácil de usar, pero volver a utilizar OpenGL de forma no obsoleta tampoco es una ciencia exacta, solo requiere un poco de trabajo extra.

Aquí está el código típico de OpenGL "Hello World" en modo inmediato:

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

Editar:
Por solicitud común, lo mismo en el modo retenido se vería algo así:

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