Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
wiki2:ogl [2015/11/29 18:41] alfred [glDrawArrays & glDrawElements] |
wiki2:ogl [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 25: | Línea 25: | ||
| * https://open.gl/depthstencils | * https://open.gl/depthstencils | ||
| * https://open.gl/framebuffers | * https://open.gl/framebuffers | ||
| + | |||
| + | ==== VBO (Vertex Buffer Objects) ==== | ||
| + | OpenGL ES defines the concept of buffers for exchanging data between memory areas. A buffer is a contiguous range of RAM that the graphics processor can control and manage. All the data that programs supply to the GPU should be in buffers. It doesn’t matter if a buffer stores geometric data, colors, hints for lighting effects, or other information. | ||
| + | |||
| + | The process of creating and using VBOs (Vertex Buffer Objects) should be familiar to you because it mimics the process used for textures: first generate a ‘‘name,’’ allocate space for the data, load the data, and then use glBindBuffer() whenever you want to use it. | ||
| + | |||
| + | - Generate. ''glGenBuffers()''. Ask OpenGL ES to generate a unique identifier for a buffer that the graphics processor controls. | ||
| + | - Bind. ''glBindBuffer()''. Tell OpenGL ES to use a buffer for subsequent operations. | ||
| + | - Buffer Data. ''glBufferData() or glBufferSubData()''. Tell OpenGL ES to allocate and initialize sufficient contiguous memory for a currently bound buffer—often by copying data from CPU-controlled memory into the allocated memory. | ||
| + | - Enable or Disable. Tell OpenGL ES whether to use data in buffers during subsequent rendering. | ||
| + | - Set Pointers. Tell OpenGL ES about the types of data in buffers and any memory offsets needed to access the data. | ||
| + | - Draw ''glDrawArrays() or glDrawElements()''. Tell OpenGL ES to render all or part of a scene using data in currently bound and enabled buffers. | ||
| + | - Delete''glDeleteBuffers()''. Tell OpenGL ES to delete previously generated buffers and free associated resources. | ||
| + | |||
| + | <code objc> | ||
| + | -(void)createVBO { | ||
| + | int numXYZElements=3; | ||
| + | int numNormalElements=3; | ||
| + | int numColorElements=4; | ||
| + | int numTextureCoordElements=2; | ||
| + | long totalXYZBytes; | ||
| + | long totalNormalBytes; | ||
| + | long totalTexCoordinateBytes; | ||
| + | int numBytesPerVertex; | ||
| + | |||
| + | // we need to generate a name for this VBO | ||
| + | glGenBuffers(1, &m_VBO_SphereDataName); | ||
| + | glBindBuffer(GL_ARRAY_BUFFER,m_VBO_SphereDataName); | ||
| + | |||
| + | /* | ||
| + | the size of each vertex in the lines 2ff. And in this case a | ||
| + | vertex is the summation of its coordinates, texture coordinates, and | ||
| + | the normal vector, as required. The total is now multiplied by the total | ||
| + | number of vertices. | ||
| + | */ | ||
| + | numBytesPerVertex=numXYZElements; | ||
| + | if(m_UseNormals) numBytesPerVertex+=numNormalElements; | ||
| + | if(m_UseTexture) numBytesPerVertex+=numTextureCoordElements; | ||
| + | numBytesPerVertex*=sizeof(GLfloat); | ||
| + | |||
| + | /* | ||
| + | allocates the memory on the GPU. The final parameter is a hint to the | ||
| + | driver saying that the data is never expected to change. If you expect | ||
| + | to update it, then use GL_DYNAMIC_DRAW. | ||
| + | */ | ||
| + | glBufferData(GL_ARRAY_BUFFER, numBytesPerVertex*m_NumVertices, 0, GL_STATIC_DRAW); | ||
| + | |||
| + | /* | ||
| + | Here we use memory mapping by calling glMapBufferOES(). This | ||
| + | returns a pointer to a memory-mapped portion of the GPU’s data | ||
| + | storage inside the application’s address space. The direct method uses | ||
| + | the more traditional glBufferData(). | ||
| + | */ | ||
| + | GLubyte *vboBuffer=(GLubyte *)glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); | ||
| + | |||
| + | /* | ||
| + | Now calculate the total number of bytes for each data type. | ||
| + | */ | ||
| + | totalXYZBytes=numXYZElements*m_NumVertices*sizeof(GLfloat); | ||
| + | totalNormalBytes=numNormalElements*m_NumVertices*sizeof(GLfloat); | ||
| + | totalTexCoordinateBytes=numTextureCoordElements*m_NumVertices*sizeof(GLfloat); | ||
| + | |||
| + | // it is possible to copy the individual buffers one at a time by merely using memcpy() | ||
| + | memcpy(vboBuffer,m_VertexData,totalXYZBytes); | ||
| + | if(m_UseNormals) { | ||
| + | vboBuffer += totalXYZBytes; | ||
| + | memcpy(vboBuffer,m_NormalData,totalNormalBytes); | ||
| + | } | ||
| + | if(m_UseTexture) { | ||
| + | vboBuffer += totalNormalBytes; | ||
| + | memcpy(vboBuffer,m_TexCoordsData,totalTexCoordinateBytes); | ||
| + | } | ||
| + | |||
| + | // forces the actual copy action to execute | ||
| + | glUnmapBufferOES(GL_ARRAY_BUFFER); | ||
| + | m_TotalXYZBytes=totalXYZBytes; | ||
| + | m_TotalNormalBytes=totalNormalBytes; | ||
| + | } | ||
| + | </code> | ||
| + | <code objc> | ||
| + | -(bool)renderVBO { | ||
| + | int i; | ||
| + | static int counter=0; | ||
| + | /* | ||
| + | binds it, in the same way a texture is bound. This simply makes | ||
| + | it the current object in use, until another is bound or this one is | ||
| + | unbound with glBindBuffer(GL_ARRAY_BUFFER, 0);. | ||
| + | */ | ||
| + | glBindBuffer(GL_ARRAY_BUFFER, m_VBO_SphereDataName); | ||
| + | |||
| + | glMatrixMode(GL_MODELVIEW); | ||
| + | glDisable(GL_CULL_FACE); | ||
| + | glEnable(GL_BLEND); | ||
| + | glEnable(GL_DEPTH_TEST); | ||
| + | |||
| + | /* | ||
| + | enable the various data buffers as has been done in previous | ||
| + | execute() methods. | ||
| + | */ | ||
| + | glEnableClientState(GL_VERTEX_ARRAY); | ||
| + | if(m_UseNormals) glEnableClientState(GL_NORMAL_ARRAY); | ||
| + | |||
| + | /* | ||
| + | When using VBOs, the various pointers to the data blocks are the offset | ||
| + | from the first element, which always starts at ‘‘address’’ of zero instead | ||
| + | one in the app’s own address space. So, the vertex pointer starts at address | ||
| + | of 0, while the normals are right after the vertices, and the texture | ||
| + | coordinates are right after the normals. | ||
| + | */ | ||
| + | glVertexPointer(3,GL_FLOAT,0,(GLvoid*)(char*)0); | ||
| + | glNormalPointer(GL_FLOAT,0,(const GLvoid*)(char*)(0+m_TotalXYZBytes)); | ||
| + | glTexCoordPointer(2,GL_FLOAT,0, (const GLvoid*)((char*)(m_TotalXYZBytes+m_TotalNormalBytes))); | ||
| + | if(m_UseTexture) { | ||
| + | if(m_TexCoordsData!=nil) { | ||
| + | glEnable(GL_TEXTURE_2D); | ||
| + | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
| + | if(m_TextureID!=0) glBindTexture(GL_TEXTURE_2D, m_TextureID); | ||
| + | } | ||
| + | } else { | ||
| + | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
| + | } | ||
| + | |||
| + | /* | ||
| + | Draw | ||
| + | */ | ||
| + | glDrawArrays(GL_TRIANGLE_STRIP, 0, (m_Slices+1)*2*(m_Stacks-1)+2); | ||
| + | glDisable(GL_BLEND); | ||
| + | glDisable(GL_TEXTURE_2D); | ||
| + | return true; | ||
| + | } | ||
| + | </code> | ||
| ===== Texturas ===== | ===== Texturas ===== | ||
| + | |||
| + | ==== Básico ==== | ||
| Creating textures is very similar to creating vertex buffers : Create a texture, bind it, fill it, and configure it. | Creating textures is very similar to creating vertex buffers : Create a texture, bind it, fill it, and configure it. | ||
| Línea 48: | Línea 181: | ||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
| </code> | </code> | ||
| + | ==== Animar texturas ==== | ||
| + | === Usando el fragment shader === | ||
| + | * {{:wiki2:ogl:animating.textures.zip|}} | ||
| + | |||
| + | ==== Renderizar sobre textura ==== | ||
| + | |||
| + | Para esto se usa un FBO. Básicamente creas el FBO, reemplazas el buffer donde renderizas por el del FBO creado y dibujas, luego enlazas otra vez el buffer por defecto y en el FBO tienes la textura. | ||
| + | |||
| + | Recuerda indicar el tamaño de píxels, haber creado anteriormente de las texturas que vas a usar en el fbo y tener el shader program activo. | ||
| + | |||
| + | :!: Recuerda que para OpenGL el 0,0 está en la esquina de abajo a la izquierda. Si el sistema que usas cambia, es probable que **la textura fbo aparezca volteada**. | ||
| + | |||
| + | * {{:wiki2:ogl:fbo.zip|}} | ||
| + | ===== Transformaciones ===== | ||
| + | |||
| + | ==== Anidar transformaciones (push y pop matrix) ==== | ||
| + | |||
| + | Para anidar transformaciones dentro de otras (al mover, escalar un elemento se mueva y escale igual el que tiene dentro), las figuras hijo aplicarán sus transformaciones a partir de la matriz del modelo de la padre. | ||
| + | |||
| + | Es decir: | ||
| + | <code java> | ||
| + | float[] translateMatrix = new float[16]; | ||
| + | setIdentityM(translateMatrix, 0); | ||
| + | float[] scaleMatrix = new float[16]; | ||
| + | setIdentityM(scaleMatrix, 0); | ||
| + | |||
| + | if (mMatrix == null) { | ||
| + | // Si no tiene padre inicializamos la matriz del modelo a la identidad | ||
| + | setIdentityM(modelMatrix, 0); | ||
| + | } else { | ||
| + | // Si tiene padre usamos su matriz de modelo para aplicar las nuevas transformaciones | ||
| + | for (int i = 0; i < 16; i++) | ||
| + | modelMatrix[i] = mMatrix[i]; | ||
| + | } | ||
| + | |||
| + | // Creamos nuestras transformaciones | ||
| + | translateM(translateMatrix, 0, posX, posY, posZ); | ||
| + | scaleM(scaleMatrix, 0, sizeX, sizeY, sizeZ); | ||
| + | |||
| + | float[] temp = new float[16]; | ||
| + | |||
| + | // Aplicamos las transformaciones sobre la matriz del modelo (anterior o identidad) | ||
| + | multiplyMM(temp, 0, modelMatrix, 0, translateMatrix, 0); | ||
| + | for (int i = 0; i < 16; i++) | ||
| + | modelMatrix[i] = temp[i]; | ||
| + | |||
| + | multiplyMM(temp, 0, modelMatrix, 0, scaleMatrix, 0); | ||
| + | for (int i = 0; i < 16; i++) | ||
| + | modelMatrix[i] = temp[i]; | ||
| + | </code> | ||
| + | * {{:wiki2:ogl:nested.transforms.zip|}} | ||
| ===== Lenguaje GLSL ===== | ===== Lenguaje GLSL ===== | ||
| Línea 166: | Línea 350: | ||
| </code> | </code> | ||
| ===== Shaders en general ===== | ===== Shaders en general ===== | ||
| + | |||
| + | * :!: El optimizador de GLSL borrará todas las variables que no uses. | ||
| ===== Vertex Shader ===== | ===== Vertex Shader ===== | ||
| ==== Cambiar el tamaño de los puntos dibujados ==== | ==== Cambiar el tamaño de los puntos dibujados ==== | ||
| Línea 177: | Línea 363: | ||
| </code> | </code> | ||
| + | ==== Hacer el color algo más oscuro ==== | ||
| + | <code> | ||
| + | gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates) * vec4(0.5, 0.5, 0.5, 1); | ||
| + | </code> | ||
| ===== Otros ===== | ===== Otros ===== | ||
| ==== Código ejemplo iOS ==== | ==== Código ejemplo iOS ==== | ||