Sunday, December 18, 2016

opengl es - Why do my sprites have a dark shadow/line/frame surrounding the texture?


I'm starting OpenGL with Apple's GLKit hand I'm having some trouble to get my sprites displayed properly. The Problem is that they all are surrounded with thin dark lines. The screen shot below shows two rectangles with a png image textures containing transparency (obviously).


enter image description here


The black shadows, surrounding them are definitely not part of the pngS. The green png is done without anti-aliasing the blue one has an anti-aliased border. The black border is also apparent if I draw only one sprite.


Te relevant part (hope so...) of code is:


//render the scene
-(void)render
{

glClearColor(69./255., 115./255., 213./255., 1.);
glClear(GL_COLOR_BUFFER_BIT);
[shapes enumerateObjectsUsingBlock:^(AAAShape *shape, NSUInteger idx, BOOL *stop)
{
[shape renderInScene:self];
}];
}

//creating and storing the effect inside shape class
-(GLKBaseEffect *)effect

{
if(!effect)
{
effect = [[GLKBaseEffect alloc] init];
}
return effect;
}

//rendering the shape (including effect configuration)
-(void)renderInScene:(AAAScene *)scene

{
//TODO: Storing vertices in Buffer
self.effect.transform.projectionMatrix = scene.projectionMatrix;
self.effect.transform.modelviewMatrix = self.objectMatrix;
if(texture)
{
self.effect.texture2d0.enabled = GL_TRUE;
self.effect.texture2d0.envMode = GLKTextureEnvModeReplace;
self.effect.texture2d0.target = GLKTextureTarget2D;
self.effect.texture2d0.name = texture.name;

}
[self.effect prepareToDraw];

if(texture)
{
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0, self.textureCoordinates);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}


glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, self.vertices);
glDrawArrays(GL_TRIANGLE_FAN, 0, self.vertexCount);
glDisableVertexAttribArray(GLKVertexAttribPosition);

if(texture)
{
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
glDisable(GL_BLEND);

}
}

Any ideas anyone? Thank you.



Answer



This looks like a case of not drawing with a premultiplied alpha texture correctly. Here's a few helpful links on the subject:



If you search for "premultiplied alpha" and iOS you might find a direct solution to your problem. I suspect it will have something to do with the way you're setting up the glBlendFunc call. Here's my take at it:


In Shawn's XNA code he mentions that where before you would do:


RenderState.SourceBlend = Blend.SourceAlpha; 

RenderState.DestinationBlend = Blend.InverseSourceAlpha;

You should do this instead:


RenderState.SourceBlend = Blend.One; 
RenderState.DestinationBlend = Blend.InverseSourceAlpha;

I'm not too familiar with OpenGL, but my intuition tells me it should be something like replacing:


glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

With:



glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

Edit


Trevor mentioned that this conversion of textures into the pre-multiplied format is done automatically at build time by XCode, even if they were not originally in that format. Thanks for the tip.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...