Я сейчас работаю над игрой для iOS. Теперь мне нужна функция для рисования произвольного светящегося и полупрозрачного эллипса с помощью opengl. Это довольно сложно, так как я использую cocos2d 1.1, который не поддерживает OpenGLES 2.0, поэтому нет шейдеров. Вот что я сделал:
Первая - это функция для рисования экструзионных линий, это от 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);
}
Тогда моя функция рисования эллипса. По сути, он разделил эллипс на множество маленьких линий и использовал вышеупомянутую функцию рисования линий для их рисования:
-(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];
}
Моя проблема в том, что в вышеописанном режиме наложения мой эллипс выглядит следующим образом:
Вы можете видеть, что режим наложения явно не правильный. Место, где соединяются линии, не похоже на другую часть из-за смешивания. Но я не могу понять, какой режим наложения мне следует использовать.
Я также попробовал glBlendEquation(GL_MAX_EXT)
, и это определенно делает мой эллипс намного лучше:
Но проблема в том, что если я использую GL_MAX_EXT, альфа-значение цвета, похоже, полностью игнорируется, поэтому нет никакого способа сделать эллипс полупрозрачным. Может ли кто-нибудь помочь мне найти правильный способ сделать это? Большое спасибо!
Кстати, вот моя текстура: