@Birkemose, glTextEnv works fantastic!
@Zhenmuron, I think you will definitely want to look at this because I am capable of getting the exact effect your code creates using one sprite.
Okay so let me explain what I've done. I created a subclass of CCSprite and simply override the draw function with this.
BTW, I'm not claiming this will work 100% in all situations. I may need to turn off a few more of the OpenGL settings/states/whatever after rendering... but as far as I can tell this seems to work excellent.
-(void) draw
{
NSAssert(!usesBatchNode_, @"If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Unneeded states: -
BOOL newBlend = NO;
if( blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST ) {
newBlend = YES;
glBlendFunc( blendFunc_.src, blendFunc_.dst );
}
#define kQuadSize sizeof(quad_.bl)
//set blend function...
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //you can force it here or set it on the sprite
glActiveTexture( GL_TEXTURE0 );
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, [texture_ name]);
//the magic
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); //you can change me... GL_REPLACE, GL_SUBSTRACT produce nice effects
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); //setColor
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); //your texture
long offset = (long)&quad_;
// vertex
NSInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
glVertexPointer(3, GL_FLOAT, kQuadSize, (void*) (offset + diff) );
// color
diff = offsetof( ccV3F_C4B_T2F, colors);
glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (void*)(offset + diff));
// tex coords
diff = offsetof( ccV3F_C4B_T2F, texCoords);
glTexCoordPointer(2, GL_FLOAT, kQuadSize, (void*)(offset + diff));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if( newBlend )
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
#if CC_SPRITE_DEBUG_DRAW
CGSize s = [self contentSize];
CGPoint vertices[4]={
ccp(0,0),ccp(s.width,0),
ccp(s.width,s.height),ccp(0,s.height),
};
ccDrawPoly(vertices, 4, YES);
#endif // CC_TEXTURENODE_DEBUG_DRAW
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); //go back to default
}
Now, I still do not claim to understand OpenGL. But I do understand some of this... at least what it does... :D You need the blendFunc to be:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
You can force it in the draw class or set it in the sprite like such:
[sprite setBlendFunc:(ccBlendFunc){GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}];
If you compile you will notice your sprite goes completely white. Why? Not sure... but I am sure it has something to do with setColor and the way it's applied to the vertices. As a matter of fact what we have just done is made setColor be additive. Take a look at
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
By setting it to GL_ADD whatever we set setColor to will additively(literally) be applied to our texture. Since the default color is (255, 255, 255) we are adding white to our texture which makes it go solid white. By default you need to make the color be (0, 0, 0) now instead of (255, 255, 255).
Now, if you change GL_ADD to GL_REPLACE it will make your sprite be entirely the color set with setColor. Which is exactly what I was trying to do earlier. With this I can apply a sprite over another sprite to produce the effect in my graphic.
Last GL_SUBSTRACT inverts the image... (255, 255, 255) is a full inversion. Change it to a color like orange and you get some pretty cool effects depending on the sprite being manipulated.
There are more options but these are the three I thought were useful and interesting. If you guys find out more information and ways to make this work better please post it! :D