2

I'm currently working on an iOS game. Now what I want is a function to draw arbitrary glowing and semi-transparent ellipse with opengl. It's kind of tricky since I'm using cocos2d 1.1 which does not support opengl es 2.0 so there is no shader. Here is what I did:

First is a function to draw extrusion lines, this is from http://answers.oreilly.com/topic/1669-how-to-render-anti-aliased-lines-with-textures-in-ios-4/

-(void) drawLineFrom:(CGPoint) start to:(CGPoint) end color:(ccColor4B) color width:(CGFloat) width texture:(CCTexture2D *) texture{
    // calculate direction vector
    CGPoint e = [self op:end minus:start];
    CGFloat length = sqrtf(e.x * e.x + e.y * e.y);
    e = ccp(e.x * width / length, e.y * width / length);

    CGPoint n = ccp(-e.y, e.x);
    CGPoint s = [self op:CGPointZero minus:n];
    CGPoint ne = [self op:n plus:e];
    CGPoint nw = [self op:n minus:e];
CGPoint sw = [self op:CGPointZero minus:ne];
    CGPoint se = [self op:CGPointZero minus:nw];

    // init vertices
    CGPoint vertices[8];
    vertices[0] = [self op:start plus:sw];
    vertices[1] = [self op:start plus:nw];
    vertices[2] = [self op:start plus:s];
    vertices[3] = [self op:start plus:n];
    vertices[4] = [self op:end plus:s];
    vertices[5] = [self op:end plus:n];
    vertices[6] = [self op:end plus:se];
    vertices[7] = [self op:end plus:ne];

    // init texture coordinates
    CGPoint texCoords[8] = {ccp(0, 0) ,ccp(0,1), ccp(0.5, 0), ccp(0.5, 1), ccp(0.5, 0), ccp(0.5, 1), ccp(1, 0), ccp(1, 1)};
    // init colors
    ccColor4B colors[8];
    for (int i = 0; i < 8; i++) {
        colors[i] = color;
    }

    glBindTexture(GL_TEXTURE_2D, texture.name);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
    glVertexPointer(2, GL_FLOAT, 0, vertices);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
}

Then is my draw ellipse function. Basically what it did is to segment the ellipse to many small lines and use the above draw line function to draw them:

-(void) drawEllipse:(float) r focus1:(CGPoint) f1 focus2:(CGPoint) f2 {
    // load texture
    CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: @"glow.png"];

    int segments = 50;
    CGFloat width = r / 2;
    CGFloat height = sqrtf(powf(r / 2, 2) - powf([Helper distanceFrom:f1 to:f2] / 2, 2));
    CGPoint center = CGPointMake((f1.x + f2.x) / 2, (f1.y + f2.y) / 2);

    glEnable(GL_TEXTURE_2D);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glTranslatef(center.x, center.y, 0.0);
    glRotatef(atanf((f1.y - f2.y) / (f1.x - f2.x)) * 180 / M_PI, 0, 0, 1);

    GLfloat vertices[segments * 2];
    int count = 0;
    for (GLfloat i = 0; i < 360.0f; i += (360.0f / segments)) {
        vertices[count++] = (cos(degreesToRadian(i)) * width);
        vertices[count++] = (sin(degreesToRadian(i)) * height);
    }

    int i = 0;
    CGFloat lineWidth = 20;
    ccColor4B lineColor = ccc4(255, 255, 255, 50);
    while (i < segments * 2 - 2) {
        [self drawLineFrom:ccp(vertices[i++], vertices[i++]) to:ccp(vertices[i++], vertices[i++]) color:lineColor width:lineWidth texture:texture];
    }
    [self drawLineFrom:ccp(vertices[segments * 2 - 2], vertices[segments * 2 - 1]) to:ccp(vertices[0], vertices[1]) color:lineColor width:lineWidth texture:texture];
}

My problem is that with the above blend mode, my ellipse looks like this:

enter image description here

You can see that the blend mode is clearly not right. The spot where the lines are joined together does not look like the other part because of blending. But I cannot figure out what blend mode I should use.

I also tried glBlendEquation(GL_MAX_EXT), and it definitely makes my ellipse look much better: enter image description here

But the problem is if I use GL_MAX_EXT the alpha value of the color seems to be completely ignored so there is no way to make the ellipse semi-transparent. Could anybody help me figure out the right way to do this? Thank you very much!

BTW, here is my texture:

enter image description here

CodeSmile
  • 64,284
  • 20
  • 132
  • 217
eveningsun
  • 1,322
  • 1
  • 9
  • 5
  • Well, of course this is not an answer to your question, but doesn't the second image look like it should? Your texture also suggests that the inner part shouldn't really be transparent, the outer part is still transparent (thus the glow effect). So I think the `GL_MAX_EXT` actually does what you want. Look at the first image, even if the knots would have the same transparency as the rest of the lines, the whole thing would still look very pale and not really glowing. Imagine, in the second image it's so glowy in the middle that you cannot see through. – Christian Rau Mar 13 '12 at 09:07
  • Hi there, what I actually want is the first image without the knots. I'm new to opengl so I don't really understand how I got the second image... I mean in the ColorArray the alpha value of all my color is 50 as you can see in the code. But the actual drawing looks like that it completely ignored the alpha value set in the ColorArray. Why is this happening? – eveningsun Mar 13 '12 at 14:14
  • Well, thats exactly what [`glBlendEquation(GL_MAX_EXT)`](http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquation.xml) does, just take the maximum of both colors (and thus don't do any acutal blending). I still think the second image looks perfect and the first one doesn't really glow, but Ok, it's your application ;) – Christian Rau Mar 13 '12 at 14:55
  • Have you tried replacing the center where R=1 G=1 B=1 A=1 with something with a transparency(A=.25)? You may want to update the yellow part to be a bit transparent too. I think that will get you the effect you are looking for with the GL_MAX_EXT blend mode. – Mark Mar 14 '12 at 15:06

0 Answers0