OpenGL ES code to revise - iphone

I´m creating an opengl ES project and I´m trying to show some textures, all works good but the problem is the use of the memory, every 5 seconds increments almost 1 Mb, I think I´m doing something wrong, I´m not using any of this apple recommendations I will tray for sure, but I want to know if my code have some bug, there is how I´m paiting:
// Generate the vertex buffer object (VBO)
glGenBuffers(1, &ui32Vbo);
// Bind the VBO so we can fill it with data
glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo);
// Set the buffer's data
// Calculate verts size: (3 vertices * stride (3 GLfloats per each vertex))
glBufferData(GL_ARRAY_BUFFER, uiSize, verts, GL_STATIC_DRAW);
// Bind the VBO so we can fill it with data
glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 20, 0); // Stride = 20 bytes
glBindTexture(GL_TEXTURE_2D, textID);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 20, (void *)12);
glDrawArrays(GL_TRIANGLE_FAN, 4, 4);
// Bind the VBO so we can fill it with data
glBindBuffer(GL_ARRAY_BUFFER, 0);
Thank you very much!!!

You should generate the vertex buffer object only once, the use it draw.
It seems you create a new one each frame.

Related

rendering with multiple vertex and index buffer objects (ios - OpenGLES 2.0)

I am not able to render my all objects using more than 1 pair of vertex and index buffer objects. To check everything, I initialized just 3 objects and render them. This results in a distorted geometry for the first two and the third objects geometry renders somewhat fine (not perfect).
When I just initialize all of the 3 but render just first, it again shows distorted geometry and somehow the third geometry is more visible (even when I am not rendering it).
However, If I am initializing and rendering any one of them, it renders just fine (perfect).
here is my code:
float tempAngles[4] = {0, 60, 180, 360};
pieOne = [[IVNode alloc]initWithPieGeometry:0.75 thickness:0.20 startAngle:tempAngles[0]*M_PI/180 andEndAngle:tempAngles[1]*M_PI/180];
glGenBuffers(1, &vertexBuffer1);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer1);//vertexBuffer[i]);
glBufferData(GL_ARRAY_BUFFER, [pieOne.pie getVertexSize]*sizeof(GLfloat), [pieOne.pie returnVertexArray] , GL_STATIC_DRAW);
glGenBuffers(1, &indexBuffer1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer1);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, [pieOne.pie getIndicesSize]*sizeof(GLushort),[pieOne.pie returnIndexArray], GL_STATIC_DRAW);
pieTwo = [[IVNode alloc]initWithPieGeometry:1.0 thickness:0.20 startAngle:tempAngles[1]*M_PI/180 andEndAngle:tempAngles[2]*M_PI/180];
glGenBuffers(1, &vertexBuffer2);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer2);//vertexBuffer[i]);
glBufferData(GL_ARRAY_BUFFER, [pieTwo.pie getVertexSize]*sizeof(GLfloat), [pieTwo.pie returnVertexArray] , GL_STATIC_DRAW);
glGenBuffers(1, &indexBuffer2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, [pieTwo.pie getIndicesSize]*sizeof(GLushort),[pieTwo.pie returnIndexArray], GL_STATIC_DRAW);
pieThree = [[IVNode alloc]initWithPieGeometry:0.75 thickness:0.20 startAngle:tempAngles[2]*M_PI/180 andEndAngle:tempAngles[3]*M_PI/180];
glGenBuffers(1, &vertexBuffer3);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer3);//vertexBuffer[i]);
glBufferData(GL_ARRAY_BUFFER, [pieThree.pie getVertexSize]*sizeof(GLfloat), [pieThree.pie returnVertexArray] , GL_STATIC_DRAW);
glGenBuffers(1, &indexBuffer3);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer3);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, [pieThree.pie getIndicesSize]*sizeof(GLushort),[pieThree.pie returnIndexArray], GL_STATIC_DRAW);
//#define BUFFER_OFFSET(i) ((char *)NULL + (i))
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(12));
Now In my rendering function I have:
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.77f, 0.88f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float yellow[3][4] = {1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f};
glUseProgram(_program);
//1st
GLKMatrix4 model = GLKMatrix4Identity;// GLKMatrix4MakeTranslation(1.5, 0, 0);
_modelViewProjectionMatrix = GLKMatrix4Multiply(_modelViewProjectionMatrix, model);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0,_normalMatrix.m);
glUniform4f(uniforms[COLOR_VECTOR], yellow[0][0], yellow[0][1], yellow[0][2], yellow[0][3]);
//bind corresponding buffer before drawing
glBindBuffer(GL_ARRAY_BUFFER, indexBuffer1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer1);
glDrawElements(GL_TRIANGLES, [pieOne.pie getIndicesSize], GL_UNSIGNED_SHORT, (void*)0);
//2nd
model = GLKMatrix4MakeTranslation(0, -1, 0);
_modelViewProjectionMatrix = GLKMatrix4Multiply(_modelViewProjectionMatrix, model);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0,_normalMatrix.m);//
glUniform4f(uniforms[COLOR_VECTOR], yellow[1][0], yellow[1][1], yellow[1][2], yellow[1][3]);
//bind corresponding buffer before drawing
glBindBuffer(GL_ARRAY_BUFFER, indexBuffer2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2);
glDrawElements(GL_TRIANGLES, [pieTwo.pie getIndicesSize], GL_UNSIGNED_SHORT,(void*)0);
//3rd
model = GLKMatrix4MakeTranslation(-1.5, 0, 0);
_modelViewProjectionMatrix = GLKMatrix4Multiply(_modelViewProjectionMatrix, model);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0,_normalMatrix.m);
glUniform4f(uniforms[COLOR_VECTOR], yellow[2][0], yellow[2][1], yellow[2][2], yellow[2][3]);
//bind corresponding buffer before drawing
glBindBuffer(GL_ARRAY_BUFFER, indexBuffer3);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer3);
glDrawElements(GL_TRIANGLES, [pieThree.pie getIndicesSize], GL_UNSIGNED_SHORT, (void*)0);
}
getIndicesSize returns the number of elements in indexArray.
getVertexSize return the number of elements in vertexArray.
returnVertexArray returns the vertex array of the geometry.
returnIndexArray returns the index array of the geometry.
vertex array is of type GLfloat.
index array is of type GLushort.
Number of elements in vertex array generated is 24522.
Number of elements in Index array generated is 22680.
On the internet, only examples of multiple VBO/IBO I found were not using GLkit and they did exactly what I am doing here in terms of initializing buffers and rendering.
I have spent almost 2 days on this issue. I feel there is some very basic thing missing. Somehow the last bound buffer affects all other geometries I feel (based on my results as I explained above). Could it be a simulator issue (I don't think so)? Fast response will be appreciated. Thanks
You seem to have some confusion about how the glVertexAttribPointer functions are supposed to work. When you call glVertexAttribPointer, it tells OpenGL:
On the next draw call, render starting from the address of the currently bound buffer plus the provided buffer offset.
After this, it doesn't matter if you change what buffer is bound, because the pointer still points to the buffer that was bound at the time of the function call.
Therefore in this code:
glBindBuffer(GL_ARRAY_BUFFER, indexBuffer1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer1);
glDrawElements(GL_TRIANGLES, [pieOne.pie getIndicesSize], GL_UNSIGNED_SHORT, (void*)0);
Calling glBindBuffer(GL_ARRAY_BUFFER) does absolutely nothing here, because you're not updating the pointer.
glBindBuffer(GL_ARRAY_BUFFER, indexBuffer1);
//need to set glVertexAttribPointers here
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer1);
glDrawElements(GL_TRIANGLES, [pieOne.pie getIndicesSize], GL_UNSIGNED_SHORT, (void*)0);

How to batch render sprites in OpenGL ES (iPhone)

I have a game that renders a bunch of sprites (several hundred), almost all of which are using the same texture. Currently, I'm calling glDrawArrays(...) for each one, which I recently discovered was very inefficient. After doing some research, I've learned that I need to put all my vertices for every sprite into one big vertex buffer, and call glDrawArrays(...) just once using that. However, when I do so it only draws the first sprite, and the other 200 are blank.
blueSpriteVertices[blueBatchNum * 4] = Vertex3DMake(xloc, yloc, zloc);
blueSpriteVertices[blueBatchNum * 4 + 1] = Vertex3DMake(xloc + size, yloc, zloc);
blueSpriteVertices[blueBatchNum * 4 + 2] = Vertex3DMake(xloc, yloc + size, zloc);
blueSpriteVertices[blueBatchNum * 4 + 3] = Vertex3DMake(xloc + size, yloc + size, zloc);
blueBatchNum++;
//^^This block of code^^ is called iteratively, adding data for various sprites
//(around 200) to the vertex array. "xloc", "yloc", etc. are private members of
//this sprite class
//Draw the whole batch
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1, 1, 1, 1);
//This code is actually in the Texture2D class implementation, hence "_name"
//and "coordinates"
glBindTexture(GL_TEXTURE_2D, _name);
glVertexPointer(3, GL_FLOAT, 0, blueSpriteVertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_VERTEX_ARRAY);
I finally solved this problem by using GL_TRIANGLES instead of GL_TRIANGLE_STRIP, and handled the triangle strips manually. By doing so I was able to eliminate all the "strips" that it was interpreting in between my sprites. Works like a charm now, and the batching definitely improved my game's performance astronomically.
Using (GL_TRIANGLES instead of GL_TRIANGLE_STRIP works for me (on Android)
glDrawElements(GL_TRIANGLES, 6 * mSpriteCounter, GL_UNSIGNED_SHORT, (char*) NULL);
The glDrawArrays() last parameter should contain the number of vertices (in your case you have only 4). Also you must have the same number of texture coordinates to match the drawn vertices!

How to dynamically create vertices in glVertexPointer() in openGLES

I have a set of textures which I need to draw at different vertices such that every texture is visible.I cannot define a static set of vertices since I load the textures dynamically and I dont know how many textures will be loaded everytime ( i choose them based on a condition).
This is how my code looks as of now.
for(int i=0;i<num_img;i++)
{
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.0);
glRotatef(rot, 1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, texture[i]);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glNormalPointer(GL_FLOAT, 0, normals);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
Is there anyway to dynamically generate vertices that can be passed as final argument of glVertexPointer() ?
Do you know the maximum number of vertices that you will use? Maybe you could create the vertices array to be that maximum size then in the first parameter of glVertexPointer you only pass the number of vertices that you actually use.

Setting Up OpenGL ES 2.0 Textures

I'm working on an iPhone project in Xcode 3.2.4 for which I'd like to display textures using OpenGL ES 2.0. I don't have much previous experience working with OpenGL, but so far it doesn't seem too awful. So far I've mainly been referring to The OpenGL ES 2.0 Programming Guide (gold book).
Right now I've got a project based on Xcode's default OpenGL template, with the drawFrame function replaced with my texture-displaying code, which in turn is based on the Simple_Texture2D project from the gold book. However, the square I should be drawing my texture onto does not display it; it's black instead, and I'm not sure why this is happening.
Here are the contents of drawFrame:
[(EAGLView *)self.view setFramebuffer];
GLuint textureID;
static const GLfloat squareVertices[] =
{
-0.5f, -0.33f,
0.5f, -0.33f,
-0.5f, 0.33f,
0.5f, 0.33f
};
// Generate a 2 x 2 rgb image at 3 bytes per pixel.
GLubyte image[4 * 3] =
{
255, 0, 0,
0, 255, 0,
0, 0, 255,
255, 255, 0
};
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLushort indices[] = {0, 1, 2, 3, 2, 1};
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
[(EAGLView *)self.view presentFramebuffer];
Perhaps to an experienced OpenGL user it'll be obvious what I'm doing wrong. Otherwise, any suggestions, guesses, or constructive comments of any kind are great too.
Thanks in advance!
You need not only vertex positions but also texture coordinates. As it stands you're only specifying vertex positions, so you're only going to vertices with whatever color was set last, no texture.
Try setting up a texCoord array and doing another glVertexAttribPointer(ATTRIB_TEXCOORD, ...) and a glEnableVertexArray(ATTRIB_TEXCOORD).
(If you're lighting you may want normals as well.)
There's sample code off songho's OpenGL Vertex Array page (glDrawElements section). See the draw3 function and prior setup.
Note that vertex buffer objects (and other buffer objects) are generally replacing vertex arrays (and other arrays) as the preferred solution for rendering batches of data at once. VBOs have more opportunity to be stored in a high-performance way by the driver.

glPointSizePointerOES and glScalef

I am using point sprites to display a few ten thousand points, each with a different size. It works well, looks great and is quite fast. I'm using a VBO with the coordinates and the sizes in it (4 floats per point).
Here is my display code
glEnable(GL_POINT_SPRITE_OES);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, pointTexture);
glTexEnvi( GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE );
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, pointVertices);
glVertexPointer(3, GL_FLOAT, 4*sizeof(float), 0);
glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
glPointSizePointerOES(GL_FLOAT,4*sizeof(float),(GLvoid*) (sizeof(GL_FLOAT)*3));
glDrawArrays(GL_POINTS, 0, pointNum);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_POINT_SPRITE_OES);
Now, I would also like to be able to zoom in, i.e. use glScalef. Is it possible to change the size of the points accordingly without updating the VBO? glPointSize doesn't have any effect, as I'm using GL_POINT_SIZE_ARRAY_OES.
Yes, use glPointParameter with the GL_POINT_DISTANCE_ATTENUATION parameter.
http://www.khronos.org/opengles/sdk/1.1/docs/man/glPointParameter.xml
It's quite tricky to get right, though.