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开发者_Go百科 = 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.
精彩评论