我目前正在开发iOS游戏。现在我想要的是用opengl绘制任意发光和半透明椭圆的功能。这有点棘手,因为我使用的是cocos2d 1.1,它不支持opengl es 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,颜色的alpha值似乎完全被忽略,因此无法使椭圆半透明。有人能帮我找出正确的方法吗?非常感谢你!
BTW,这是我的纹理: