Overview
I’m trying to build a graphic in my game by combining a few images and gradients. I started by using Core Graphics which worked wonderfully, but was abysmally slow. I’ve now tried to port it over to OpenGL using GLKit and I’m very close, but there’s one last issue:
I’ve already drawn a texture into a triangle on the screen. Now, over the top of it, I’d like to draw a gradient. To draw a gradient, I figured it’d be easiest to just draw a triangle with a black color at two of the vertices and a fully transparent (alpha=0) color on the third. The gradient renders fine by itself, but when it is rendered over the top of the texture, it appears as if the alpha of the texture is also affected and causes the background to show through.
What I want:

What I get instead:

I admit that I’m not too familiar with OpenGL or GLKit. I suspect that the texture’s alpha at every point on the triangle is (1 – gradient alpha) which would explain why the texture is fully opaque in the corner and why both the texture and gradient seem to have partial transparency in the middle.
Can I accomplish what I want with GLKit? Does it even relate to GLKit and GLKBaseEffect, or am I just doing some funky multi-texturing thing in OpenGL that I can turn off?
Code Snippets
Render function in my sprite class, for drawing the texture:
typedef struct {
CGPoint geometryVertex;
CGPoint textureVertex;
} TexturedVertex;
- (void)renderTriangleStrip:(TexturedVertex *)coordinates ofSize:(NSInteger)size {
self.effect.texture2d0.envMode = GLKTextureEnvModeReplace;
self.effect.texture2d0.name = self.textureInfo.name;
self.effect.texture2d0.enabled = YES;
self.effect.transform.modelviewMatrix = self.transform;
[self.effect prepareToDraw];
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
long offset = (long)coordinates;
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, size);
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
}
Render function in my shape class, for drawing the triangle w/gradient:
typedef struct {
CGPoint position;
GLKVector4 color;
} ColoredVertex;
- (void)renderVertices:(ColoredVertex *)vertices ofSize:(NSInteger)size {
self.effect.texture2d0.envMode = GLKTextureEnvModeDecal;
self.effect.texture2d0.enabled = NO;
self.effect.useConstantColor = NO;
self.effect.transform.modelviewMatrix = self.transform;
[self.effect prepareToDraw];
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribColor);
long offset = (long)vertices;
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ColoredVertex), (void *) (offset + offsetof(ColoredVertex, position)));
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(ColoredVertex), (void *) (offset + offsetof(ColoredVertex, color)));
glDrawArrays(GL_TRIANGLE_FAN, 0, size);
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribColor);
}
Thanks in advance for your help!
Edit: It seems like glBlendFunc(…) might contain my answer. But I don’t understand the different modes. Am I on the right track here?
Edit: Still no solution yet, but I’ve updated my assumptions in the question.
I’m not sure to understand your problem, so I’ll try to restate it as I get it.
I understand that it is pass 3 that causes you problems.
If this is it, what you need to do to obtain your reference image is to draw your gradient triangle using a proper blending mode, and proper vertex colors. In your case, two black colors and one white color.
For you case, the blending would be setup using :
This will instruct OpenGL to draw you triangle so that the resulting pixel color is given by
dst = 0 * src + src * dst, which isdst = dst * src.