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/22 09:19] alfred [Operators and flow control] |
wiki2:ogl [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 22: | Línea 22: | ||
| * {{:wiki2:gldrawelements.simple.zip|Example}} | * {{:wiki2:gldrawelements.simple.zip|Example}} | ||
| + | ==== Buffers ==== | ||
| + | * https://open.gl/depthstencils | ||
| + | * 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 ===== | ||
| + | |||
| + | ==== Básico ==== | ||
| + | |||
| + | Creating textures is very similar to creating vertex buffers : Create a texture, bind it, fill it, and configure it. | ||
| + | |||
| + | Remember to use power of two textures (..., 128x128, 256x256, 1024x1024...). However, in standard OpenGL ES 2.0, textures don’t have to be square, but each dimension should be a power of two ( POT ). This means that each dimension should be a number like 128, 256, 512, and so on, but there is also a maximum texture size that varies from implementation to implementation but is usually something large, like 2048 x 2048. | ||
| + | |||
| + | In glTexImage2D, the GL_RGB indicates that we are talking about a 3-component color, and GL_BGR says how exactly it is represented in RAM. As a matter of fact, BMP does not store Red->Green->Blue but Blue->Green->Red, so we have to tell it to OpenGL. So imagine that we stored a BMP in a ''unsigned char* data'' variable, and ''unsigned int widht, height'' variables have the size: | ||
| + | |||
| + | <code cpp> | ||
| + | // Create one OpenGL texture | ||
| + | GLuint textureID; | ||
| + | glGenTextures(1, &textureID); | ||
| + | |||
| + | // "Bind" the newly created texture : all future texture functions will modify this texture | ||
| + | glBindTexture(GL_TEXTURE_2D, textureID); | ||
| + | |||
| + | // Give the image to OpenGL | ||
| + | glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data); | ||
| + | |||
| + | // Configure the texture | ||
| + | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
| + | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
| + | </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 43: | Línea 254: | ||
| * **sampler2D**: Used to represent and access a 2D texture | * **sampler2D**: Used to represent and access a 2D texture | ||
| * **samplerCube**: Used to represent and access a cube mapped texture | * **samplerCube**: Used to represent and access a cube mapped texture | ||
| - | * **float floatarray[3]**: One-dimensional arrays; can be of types such as floats, vectors, | + | * **float floatarray[3]**: One-dimensional arrays; can be of types such as floats, vectors, and integers |
| - | and integers | + | |
| You can address components in a vec4 type in the following ways: | You can address components in a vec4 type in the following ways: | ||
| - | * **{x, y, z, w}**: You can use this representation when accessing vectors that | + | * **{x, y, z, w}**: You can use this representation when accessing vectors that represent points or normals. |
| - | represent points or normals. | + | * **{r, g, b, a}**: You can use this representation when accessing vectors that represent colors. |
| - | * **{r, g, b, a}**: You can use this representation when accessing vectors that | + | * **{s, t, p, q}**: You can use this representation when accessing vectors that represent texture coordinates. |
| - | represent colors. | + | |
| - | * **{s, t, p, q}**: You can use this representation when accessing vectors that | + | |
| - | represent texture coordinates. | + | |
| <code> | <code> | ||
| vec3 position; | vec3 position; | ||
| Línea 120: | Línea 327: | ||
| - | * Const: The const qualifier specifies a compile time constant or a read-only function parameter. | + | * **Const**: The const qualifier specifies a compile time constant or a read-only function parameter. |
| - | * Attribute: The attribute qualifier specifies a linkage between a vertex shader and the main OpenGL ES 2.0 program for per-vertex data. Some examples of the types of variables where the attribute qualifier can be used are vertex position, vertex textures, and vertex normal. | + | * **Attribute**: The attribute qualifier specifies a linkage between a vertex shader and the main OpenGL ES 2.0 program for per-vertex data. Some examples of the types of variables where the attribute qualifier can be used are vertex position, vertex textures, and vertex normal. |
| - | * Uniform: The uniform qualifier specifies that the value does not change across the primitive being processed. Uniform variables form the linkage between a vertex or fragment shader and the main OpenGL ES 2.0 application. Some examples of variables where the uniform qualifier would be appropriate are lighting values, material values, and matrices. | + | * **Uniform**: The uniform qualifier specifies that the value does not change across the primitive being processed. Uniform variables form the linkage between a vertex or fragment shader and the main OpenGL ES 2.0 application. Some examples of variables where the uniform qualifier would be appropriate are lighting values, material values, and matrices. |
| - | * Varying: The varying qualifier specifies a variable that occurs both in the vertex shader and fragment shader. This creates the linkage between a vertex shader and fragment shader for interpolated data. These are usually values for the diffuse and the specular lighting that will be passed from the vertex shader to the fragment shader. Texture coordinates, if present, are also varying. The values of the diffuse and specular lighting, as well as textures, are interpolated or “varying” across the object the shader is rendering. Some examples of varying variables are the vertex texture coordinate, the diffuse color of the vertex, and the specular color of the vertex. | + | * **Varying**: The varying qualifier specifies a variable that occurs both in the vertex shader and fragment shader. This creates the linkage between a vertex shader and fragment shader for interpolated data. These are usually values for the diffuse and the specular lighting that will be passed from the vertex shader to the fragment shader. Texture coordinates, if present, are also varying. The values of the diffuse and specular lighting, as well as textures, are interpolated or “varying” across the object the shader is rendering. Some examples of varying variables are the vertex texture coordinate, the diffuse color of the vertex, and the specular color of the vertex. |
| <code> | <code> | ||
| Const int NumberLights = 3; | Const int NumberLights = 3; | ||
| Línea 136: | Línea 343: | ||
| varying float vSpecular; | varying float vSpecular; | ||
| </code> | </code> | ||
| + | ==== Otras funciones ==== | ||
| + | * The color from the currently active texture that matches the texture coordinates in the texture coordinate is found through the ''texture2D()'' function. | ||
| + | <code> | ||
| + | vec4 color = texture2D(sTexture, vTextureCoord); | ||
| + | </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 148: | Línea 362: | ||
| gl_FragColor = vec4(1,0,0,1); | gl_FragColor = vec4(1,0,0,1); | ||
| </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 ===== | ||
| + | ==== Código ejemplo iOS ==== | ||
| + | |||
| + | * {{:wiki2:ogl:squarewithshaders.zip|}} | ||
| + | * {{:wiki2:ogl:squaretexturedwitharrays.zip|}} | ||
| + | * {{:wiki2:ogl:squaretexturedwithbuffers.zip|}} | ||