Can I create Vertex Buffer Objects without color information? - iphone

I want to create a grid of rectangles for a simulation, where we colorize the rectangles based on calculation results.
Initially I would just want to build the VBO to define the grid. And then in every frame simply assign colors to the rectangles.
Is this possible or is a VBO always "hard-wired" with a set of colors? Because all examples I find online do it like this. They initialize the VBO together with colors and not just the vertex position data, like this:
// allocate a new buffer
glGenBuffers(1, &cubeVBO);
// bind the buffer object to use
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
const GLsizeiptr vertex_size = NUMBER_OF_CUBE_VERTICES*NUMBER_OF_CUBE_COMPONENTS_PER_VERTEX*sizeof(GLfloat);
const GLsizeiptr color_size = NUMBER_OF_CUBE_COLORS*NUMBER_OF_CUBE_COMPONENTS_PER_COLOR*sizeof(GLubyte);
// allocate enough space for the VBO
glBufferData(GL_ARRAY_BUFFER, vertex_size + color_size, 0, GL_STATIC_DRAW);

A VBO is just a piece of memory, you use it to make things run faster by having the data reside in the graphics card. (Some hardware uses system memory for VBO, so not really much to gain in this case)
I also find it cleaner to always use VBOs, but that's a bit of a personal preference.
Anyway you can create VBOs, and then change the data inside them, same as piece of RAM, if you need to change everything on VBO every frame again no performance benefit, but if you only need to change stuff from time to time, or some of the data is fixed (say your vertex data), then you start to get some benefits...
for example:
glGenBuffers(1, &vboObjects[vboGroupBeaver]);
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
glBufferData(GL_ARRAY_BUFFER, beaverVerts*8*sizeof(GLfloat), 0, GL_STATIC_DRAW);
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
NSString *path;
path = [[NSBundle mainBundle] pathForResource:#"beaver01" ofType:#"bin"];
NSFileHandle *model = [NSFileHandle fileHandleForReadingAtPath:path];
float vertice[8];
int counter = 0;
while (read([model fileDescriptor], &vertice, 8*sizeof(float))) {
memcpy(vbo_buffer, vertice, 8*sizeof(GLfloat)); // 0
vbo_buffer += 8*sizeof(GLfloat);
counter++;
}
NSLog(#"Vertices %1i",counter);
glUnmapBufferOES(GL_ARRAY_BUFFER);
This bit of code loads a model into a VBO (vboGroupBeaver), in this example it's the first keyframe of a animation.
All the data is now in the VBO, if I do this after:
glVertexPointer(3, GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL));
glNormalPointer(GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT,8*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLES, 0, beaverVerts);
I get a beaver drawn... (Notice that I'm using interleaved vertex data, that's why the pointer calls have the extra info).
In your case you would have a Color Pointer instead of a Texture pointer.
Now, if you want to change stuff all you have to do is glMapBufferOES to a buffer var, and interate thru it to change only the parts you need.
Something like:
vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
for (int i = start; i < end; i++) {
vbo_buffer += 6*sizeof(GLfloat); // offset to position
memcpy(vbo_buffer, whatYouWantToChange, 2*sizeof(GLfloat)); // change what you want, watch the size
}
EDIT give an example with color
First some example data, in this case a triangle with per vertex data interleaved:
static const ColoredTriangle vertexData[] = {
{
{0.0, 0.0, 0.0}, // Vertex 0
{0.0, 0.0, 1.0}, // Normal
{1.0, 0.0, 0.0, 1.0} // Color
},
{
{0.0, 480.0, 0.0}, // Vertex 1
{0.0, 0.0, 1.0}, // Normal
{1.0, 1.0, 0.0, 1.0} // Color
},
{
{320.0, 0.0, 0.0}, // Vertex 2
{0.0, 0.0, 1.0}, // Normal
{1.0, 1.0, 1.0, 1.0} // Color
}
Copy the thing to the vbo (after creating/binding/MapBuffer.
memcpy(vbo_buffer, vertexData, 10*3*sizeof(float));
draw the thing
glVertexPointer(3, GL_FLOAT, 10*sizeof(GLfloat), (GLvoid*)((char*)NULL));
glNormalPointer(GL_FLOAT, 10*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
glColorPointer(4, GL_FLOAT, 10*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat)))
glDrawArrays(GL_TRIANGLES, 0, beaverVerts);
So now you have a triangle being draw with interleaved data from the VBO.
Now on each frame you want to do something just change the data.
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
vbo_buffer += 6*sizeof(GLfloat); // position the buffer at the first vertex color data
for (int i = 0; i < 3; i++) {
memcpy(vbo_buffer, newColor, 4*sizeof(GLfloat));
vbo_buffer += 10*sizeof(GLfloat); // skip the stripe
}
glUnmapBufferOES(GL_ARRAY_BUFFER);
Then draw again, and you just changed the color info.
Depending on the number of changes you're going to be making it might be better to change GL_STATIC_DRAW to something else also...
Disclaimer
This was made on the fly, so beware of dragons.

You can define the vertex coordinates in a VBO and the vertex colors in another, then you can use glVertexAttribPointer (or glVertexPointer, glColorPointer) to set up the vertex attributes for rendering.

Related

Incorrect colors implementation OpenGL ES2 - IOS

I have very simple OpenGL ES example similar to Hehe's example : http://nehe.gamedev.net/tutorial/ios_lesson_02__first_triangle/50001/
As shown above triangle filled with three colors - red, blue, green.
Instead in my app i always get triangle almost completely filled with black color, only small area around top vertex filled with green and small area around right bottom filled with red ... and there is no blue at all.
The first question is : why do the colors not interpolate in the middle of my triangle and why does blue color is not visible at all?
Any changes in my colors array affect nothing, e.g. when i try to make triangle white the colors do not change anyway ... in the meantime if i change Z coordinate in positions array then i can see the blue color.
The second question is : why any changes in colors do nothing and changes in positions change the color instead?
Seems like somewhere here i made one stupid mistake but i can't catch it.
This is Vertex / Color arrays :
const float colors[] = { // this does not work, triangle still black-green-red
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0
};
const float positions[] = { // if i change 3rd index to 1.0 then i will see blue color
-0.5, -0.5, 0.0, 1.0,
0.0, 0.5, 0.0, 1.0,
0.5, -0.5, 0.0, 1.0
};
This is VBO :
- (BOOL)setupVBO
{
BOOL success = YES;
glGenBuffers(1, &_positionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _positionBuffer);
glBufferData(
GL_ARRAY_BUFFER,
sizeof(positions) * sizeof(float),
&positions[0],
GL_STATIC_DRAW);
glGenBuffers(1, &_colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _colorBuffer);
glBufferData(
GL_ARRAY_BUFFER,
sizeof(colors) * sizeof(float),
&colors[0],
GL_STATIC_DRAW);
return success;
}
Render :
- (void)render:(CADisplayLink*)displayLink
{
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, _positionBuffer);
glVertexAttribPointer(_positionSlot, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, _colorRenderBuffer);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_TRIANGLES, 0, 3);
[_glContext presentRenderbuffer:GL_RENDERBUFFER];
}
Thanks for any advice ...
Ok, i found where was the issue :)
As far as i am beginner in Open GL i just copypasted the code from example and renamed some variables ... and did not catch that i renamed ColorBuffer (VBO color, i.e. actual color data of drawing object) variable to ColorRenderBuffer variable (place in memory where GL processes actual color data)
Stupid mistake and i hope nobody will do the same :)

Drawing multiple moving objects

I'm currently working on an iOS game where, long story short, I need to draw a lot of moving cubes - approximate maximum of 200 per frame. Emphasis on moving because yes, I have indeed Googled away for hours on this topic and have yet to find a suitable solution for fast, efficient drawing of multiple objects where their position updates every frame.
Through my endless amounts of research on this subject most seem to mention VBOs, however I'm not sure this would suit my case where the position of every object changes every frame.
I'm using OpenGL 1 at the moment - I have working code and on generation 3/4+ devices (the ones which support OpenGL 2, ha) it runs at a reasonable framerate - however when testing on my (old, yes) 2nd-gen iPod touch, it is very sluggish and essentially unplayable.
My code comprises of a static array of vertices for a 'cube' and an array containing the position and colour of every cube. My game logic loop updates the position of every cube in the array. At the moment I'm looping through the cube array, calling glTranslatef and glDrawArrays for every cube. From what I've read this is very inefficient, however I'm completely confused as to how you would optimise it. Any ideas?
(maybe I shouldn't be aiming for old, discontinued iOS devices but given my belief that my code is incredibly inefficient, I figure it'll help my future endeavours regardless if I find a way to address this)
For such simple objects I would make one big VBO say 200 Objects * NrVerticesPerCube, put all the data interleaved Vertex,Normal,UV,Vertex,Normal,UV, etc.
I do something similar in a keyframe animation of a beaver in my game, I start with something like this:
glGenBuffers(1, &vboObjects[vboGroupBeaver]);
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
glBufferData(GL_ARRAY_BUFFER, beaverVerts*8*sizeof(GLfloat), 0, GL_STATIC_DRAW);
vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
NSString *path;
path = [[NSBundle mainBundle] pathForResource:#"beaver01" ofType:#"bin"];
NSFileHandle *model = [NSFileHandle fileHandleForReadingAtPath:path];
float vertice[8];
int counter = 0;
while (read([model fileDescriptor], &vertice, 8*sizeof(float))) {
memcpy(vbo_buffer, vertice, 8*sizeof(GLfloat)); // 0
vbo_buffer += 8*sizeof(GLfloat);
counter++;
}
glUnmapBufferOES(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
This creates my VBO buffer with the correct size (in this case 8 * sizeof(GLfloat) wich is 3 Verts, 3 Normals and 2UV), and copies the first keyframe to the buffer, you could do the same with you initial object positions, or just leave that and compute latter...
Then in each frame I do interpolation between 2 keyframes for each vertex of my beaver, and just make one draw call, this is very fast for the 4029 vertices my beaver has, and works at 60FPS on my iPhone 3G.
For you doing only gltranslates it would be even simpler, just add the values of x,y,z to each vertice of each cube.
You would update it like this:
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
Bind the vbo buffer and mapit to a buffer var.
Calculate the stuff you want on a temp var.
memcpy(vbo_buffer, currentVert, 6*sizeof(GLfloat)); // 0
vbo_buffer += 8*sizeof(GLfloat);
Copy it and update buffer to next object, repeat until all objects updated...
You could also do all the updates in a seperate array and copy the whole array, but then you would be copying extra info that usually doesn't change (normals and UV). Or you could not use interleaved data and copy that...
glUnmapBufferOES(GL_ARRAY_BUFFER);
Unmap the VBO buffer
glVertexPointer(3, GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL));
glNormalPointer(GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT,8*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLES, 0, beaverVerts);
Setup your draw call, and draw it all...
If you need to rotate objects and not just gltranslate them, you will need to add some matrix multiplications along the way...
EDIT **
ok, making a gltranste by hand is actually very easy (rotation, etc is a bit trickier).
I'm using a an interleaved plane drawed using TRIANGLE_STRIP instead of triangles, but the principle is the same.
float beltInter[] = {
0.0, 0.0, 0.0, // vertices[0]
0.0, 0.0, 1.0, // Normals [0]
6.0, 1.0, // UV [0]
0.0, 480, 0.0, // vertices[1]
0.0, 0.0, 1.0, // Normals [1]
0.0, 1.0, // UV [1]
320.0, 0.0, 0.0, // vertices[2]
0.0, 0.0, 1.0, // Normals [2]
6.0, 0.0, // UV [2]
320.0, 480, 0.0, // vertices[3]
0.0, 0.0, 1.0, // Normals [3]
0.0, 0.0 // UV [3]
};
So this is interleaved vertex, you got vertex then Normals then UV, if you're not using textures substitute UV for color.
The easiest way is to have an array with all the objects inside (made easy if all your objects are the same size) and make the position updates after draw (instead of in the middle of the opengl frame), better still make a seperate thread, create 2 VBOs update one of them while drawing from the other, something like this:
Thread 1 OpenGL DrawFrom VBO0
Thread 2 Game Updates, update positions on internal array and copy to VBO1, set Var saying VBO1 yes ready (so thread 1 only changes from drawing to VBO1 when all the updates are done).
Thread 1 OpenGL DrawFrom VBO1
Thread 2 Game update, same thing but update VBO0
continue with same logic
this is called double buffering and you use it to garanty stability, without this sometimes your game logic will be updating the VBO while the graphics card needs it and the graphics card will have to wait, resulting in lower FPS.
Anyway, back on topic
to make the equivalent to gltranslatef(10,20,30) just do:
int maxvertices = 4;
float x = 10;
float y = 20;
float z = 30;
int counter = 0;
int stride = 8; // stride is 8 = 3 x vertice + 3 x normal + 2 x UV change to 3 x color or 4 x color depending on your needs
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[myObjects]);
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
while (counter < (maxVertices*8)) {
beltInter[counter] += x; // just sum the corresponding values to each
beltInter[counter+1] += y;
beltInter[counter+2] += z;
memcpy(vbo_buffer, currentVert, 3*sizeof(GLfloat)); // again only copy what you need, in this case only copying the vertices, if your're updating all the data, you can just do a single memcpy at the end instead of these partial ones
vbo_buffer += stride*sizeof(GLfloat); // forward the buffer
counter += stride; // only update the vertex, but you could update everything
}
glUnmapBufferOES(GL_ARRAY_BUFFER);
glVertexPointer(3, GL_FLOAT, stride*sizeof(GLfloat), (GLvoid*)((char*)NULL));
glNormalPointer(GL_FLOAT, stride*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT,stride*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, maxVertices);
Of course the update values doesn't have to be the same for all the objects, infact using a base array like this you can update all the info as you go along and just have the routine to copy it to VBO when needed.
All this was written from memory on the fly, so there maybe dragons :-)
Hope that helps.
You could optimise quite a bit by sticking all the coords for all your cubes in a single array, and drawing it with a single glDrawArrays call.
I'm not sure why you'd want to split up the cubes into separate arrays, except maybe because it makes your data structure more elegant/object oriented, but that's the first place I'd look at making an improvement.
Dump the cube coordinates in one big array, and give each cube object an index into that array so that you can still keep your update logic fairly compartmentalised (as in, cube n owns the coordinates in the range x to y and is responsible for updating them, but when you actually draw the coordinates you run glDrawArrays directly on the centralised coord array instead of looping through the cube objects and rendering them individually).

How to use vertex buffer objects (VBO) instead of calling glDrawArrays thousands of times in OpenGL ES 1.0 on iOS?

For a simulation we've created a OpenGL1.1 view with a grid of 32 x 48 rectangles.
We're drawing this grid every time the CADisplayLink calls our draw function, and the vertex positions never change. The only thing that changes from frame to frame is the color of a vertex.
This is a simplified example of how we do it:
- (void)drawFrame {
// draw grid
for (int i = 0; i < numRectangles; i++) {
// ... calculate CGPoint values for vertices ...
GLshort vertices[ ] = {
bottomLeft.x, bottomLeft.y,
bottomRight.x, bottomRight.y,
topLeft.x, topLeft.y,
topRight.x, topRight.y
};
glVertexPointer(2, GL_SHORT, 0, vertices);
glColor4f(r, g, b, 1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
The OpenGL instrument recommended using Vertex Buffer Objects (VBO) for better performance.
Is there an example of how to set up a very basic, simple usage of Vertex Buffer Objects in a case where the vertices don't change from frame to frame?
Apple is providing an example over here, under the section Use Vertex Buffer Objects to Manage Copying Vertex Data, but it's incomplete.
GLuint vertexBuffer;
GLuint indexBuffer;
void CreateVertexBuffers()
{
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}
It doesn't show how to really create the data. The previous listing (which is supposed to be a "bad example") contains these two lines:
const vertexStruct vertices[] = {...};
const GLubyte indices[] = {...};
So these two arrays or structs have to be passed into:
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
and
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
?
Is this the "Interleaved (array of structs)" format preferred by iOS, according to Apple under the Use Interleaved Vertex Data section?
You're not supposed to draw single primitives using glDrawArrays, but large batches. So far you're using only regular vertex arrays, not vertex buffer objects.
The idea is, to put the geometry off all rectangles into one single VBO (a VBO is essentially a vertex array stored "in" OpenGL, rather your process). Changing single vertices is possible by using glBufferSubData.
Vertex color can be put into a vertex array, and hence into a VBO as well.
Update
Say you have some hexagon:
GLfloat vertices[2][] = {
{0, 0}, // 0
{1, 0}, // 1
{0.5, 0.866}, // 2
{-0.5, 0.866}, // 3
{-1, 0}, // 4
{0.5, -0.866}, // 5
{-0.5, -0.866}, // 6
};
and you want to draw only part of the triangles, say the triangles consisting of vertices [0,1,2], [0,3,4] and [0,5,6], then you'd create the following index array
GLushort indices[] = {
0, 1, 2,
0, 3, 4,
0, 5, 6
};
And use that as the indices for glDrawElements.
Update 2
One thing that many computer graphics and OpenGL newbies get wrong is, that a vertex is not merely a position, but a combination of vertex attributes. Which attributes make a vertex is a design choice made by the programmer. But the commonly used vertex attributes are
position
normal
texture coordinates
vertex color
Until OpenGL-3 core the position attribute was mandatory. Since OpenGL-3 core, which made shaders mandatory, vertex attributes are just arbitrary input data into shaders, and as long as a vertex shader manages to deliver the *gl_Position* output, OpenGL is happy.
The important thing is, that two vertices are identical only then, if all the attributes are the same. If they differ in just one attribute, they're not the same vertex. Now let's take our previous example of the hexagon. We're now making the triangles red, green and blue and were going to add two triangles, to extend the red and green ones into kind of diamond shapes:
// x, y, red, green, blue
GLfloat vertices[5][] = {
// red
{0, 0, 1, 0, 0}, // 0
{1, 0, 1, 0, 0}, // 1
{0.5, 0.866, 1, 0, 0}, // 2
{1, 1, 1, 0, 0}, // 3
// green
{0, 0, 0, 1, 0}, // 4
{-0.5, 0.866, 0, 1, 0}, // 5
{-1, 0, 0, 1, 0}, // 6
{-1, 1, 0, 1, 0}, // 7
// blue
{0, 0, 0, 0, 1}, // 8
{0.5, -0.866, 0, 0, 1}, // 9
{-0.5, -0.866, 0, 0, 1}, // 10
};
The triangles we now want to draw are
GLushort indices[] = {
// the two red triangles
0, 1, 2,
3, 2, 1,
// the two green triangles
4, 5, 6,
5, 7, 6,
// the blue triangle
8, 9, 10
};
Now we need to tell OpenGL about the structure of our vertex array. This is where the stride parameter of the gl…Pointer functions enters the picture. If nonzero, the stride tells OpenGL the distance (in bytes) between the start of each vertex in the array. By passing the data pointer with the right offset this makes OpenGL access the right things. In our case a vertex consists of
2 position elements of GLfloat with offset 0
3 color elements of GLfloat with offset 2*sizeof(GLfloat)
and each vertex is sizeof(GLfloat)*5 bytes apart.
We'll let the C compiler do the offset calculations for us, by simply dereferencing the right array elements and taking the address of it:
glVertexPointer(2, GL_FLOAT, sizeof(GLfloat)*5, &vertices[0][0]);
glColorPointer(3, GL_FLOAT, sizeof(GLfloat)*5, &vertices[0][2]);
The rest is just glDrawElements(GL_TRIANGLES, 5, GL_UNSIGNED_SHORT, indices).
Note that we're not using VBOs at this point, but client side vertex arrays only. VBOs build upon vertex arrays. So I strongly suggest you first get a strong grip of vertex arrays, before going to tackle VBOs. They quite easy to use actually, but there are a few conceptional pitfalls, like tricking the compiler to pass a number for a pointer parameter.

OpenGL ES 1.1 2D Ring with Texture iPhone

I would appreciate some help with the following. I'm trying to render a ring shape on top of another object in OpenGL ES 1.1 for an iPhone game. The ring is essentially the difference between two circles.
I have a graphic prepared for the ring itself, which is transparent in the centre.
I had hoped to just create a circle, and apply the texture to that. The texture is a picture of the ring that occupies the full size of the texture (i.e. the outside of the ring touches the four sides of the texture). The centre of the ring is transparent in the graphic being used.
It needs to be transparent in the centre to let the object underneath show through. The ring is rendering correctly, but is a solid black mass in the centre, not transparent. I'd appreciate any help to solve this.
Code that I'm using to render the circle is as follows (not optimised at all: I will move the coords in proper buffers etc for later code, but I have written it this way to just try and get it working...)
if (!m_circleEffects.empty())
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
int segments = 360;
for (int i = 0; i < m_circleEffects.size(); i++)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(m_circleEffects[i].position.x, m_circleEffects[i].position.y, 0);
glBindTexture(GL_TEXTURE_2D, m_Texture);
float radius = 1.764706;
GLfloat circlePoints[segments * 3];
GLfloat textureCoords[segments * 2];
int circCount = 3;
int texCount = 2;
for (GLfloat i = 0; i < 360.0f; i += (360.0f / segments))
{
GLfloat pos1 = cosf(i * M_PI / 180);
GLfloat pos2 = sinf(i * M_PI / 180);
circlePoints[circCount] = pos1 * radius;
circlePoints[circCount+1] = pos2 * radius;
circlePoints[circCount+2] = (float)z + 5.0f;
circCount += 3;
textureCoords[texCount] = pos1 * 0.5 + 0.5;
textureCoords[texCount+1] = pos2 * 0.5 + 0.5;
texCount += 2;
}
glVertexPointer(3, GL_FLOAT, 0, circlePoints);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);
glDrawArrays(GL_TRIANGLE_FAN, 0, segments);
}
m_circleEffects.clear();
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
I've been experimenting with trying to create a ring rather than a circle, but I haven't been able to get this right yet.
I guess that the best approach is actually to not create a circle, but a ring, and then get the equivalent texture coordinates as well. I'm still experimenting with the width of the ring, but, it is likely that the radius of the ring is 1/4 width of the total circle.
Still a noob at OpenGL and trying to wrap my head around it. Thanks in advance for any pointers / snippets that might help.
Thanks.
What you need to do is use alpha blending, which blends colors into each other based on their alpha values (which you say are zero in the texture center, meaning transparent). So you have to enable blending by:
glEnable(GL_BLEND);
and set the standard blending functions for using a color's alpha component as opacity:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
But always keep in mind in order to see the transparent object correctly blended over the object behind, you need to render your objects in back to front order.
But if you only use the alpha as a object/no-object indicator (only values of either 0 or 1) and don't need partially transparent colors (like glass, for example), you don't need to sort your objects. In this case you should use the alpha test to discard fragments based on their alpha values, so that they don't pollute the depth-buffer and prevent the behind lying object from being rendered. An alpha test set with
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
will only render fragments (~pixels) that have an alpha of more than 0.5 and will completely discard all other fragments. If you only have alpha values of 0 (no object) or 1 (object), this is exactly what you need and in this case you don't actually need to enable blending or even sort your objects back to front.

Corrupted image if variable is not static

I'm doing the following:
static GLfloat vertices[3][3] =
{
{0.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{-1.0, 0.0, 0.0}
};
glColor4ub(255, 0, 0, 255);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 9);
glDisableClientState(GL_VERTEX_ARRAY);
This works ok:
http://dl.dropbox.com/u/41764/posts/Screen%20shot%202010-03-28%20at%2020.04.56.png
However, if I remove static from vertices and therefore re-create the data on the stack on each rendering, I get the following:
http://dl.dropbox.com/u/41764/posts/Screen%20shot%202010-03-28%20at%2020.06.38.png
This happens both on the simulator and on the device.
Should I be keeping the variables around after I call glDrawArrays?
The reason you're seeing weird results is because you're not drawing what you think you are.
glDrawArrays(GL_TRIANGLES, 0, 9);
This means draw 9 vertices, hence 3 triangles. You only have 3 vertices declared in your array, so what the other 2 triangles will end up being is anybody's guess. You can see in the second picture that you indeed have more than 1 triangle... The data it ends up using is whatever else is on the stack at that time.
glDrawArrays does transfer on call, and I seriously doubt the iPhone would not be compliant on this. It's really basic GL, that (I believe) gets tested for conformance.
You are rendering uninitialized data in both cases. It just happens to look correct in the static case.
The third parameter to glDrawArrays is the number of vertices (which should be 3 in your case because you are trying to draw a single triangle).
You already told the GL that you are specifying 3 GLfloat per vertex (the first parameter of glVertexPointer). So the GL can figure out the total number of GLfloat to expect.
This should work:
GLfloat vertices[3][3] =
{
{0.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{-1.0, 0.0, 0.0}
};
glColor4ub(255, 0, 0, 255);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);