Texure mapping anti-alias

I have an 512 by 512 image like this:

I mapped it to a 3D plane:


The location and perspective are all correct. But you can see that the edge is very jigsaw. Does not Open GL has anti-alias or I just did not turn it on?

Here is my code:

      CGContextRef spriteContext = CGBitmapContextCreate(spriteData, spriteWidth, spriteHeight, 8, spriteWidth * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);

    CGContextTranslateCTM(spriteContext, 0, spriteHeight);

    CGContextScaleCTM(spriteContext, 1, -1);

      CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)spriteWidth, (CGFloat)spriteHeight), spriteImage);

      CGContextRelease(spriteContext);



    glDeleteTextures(1, &spriteTexture);

    glGenTextures(1, &spriteTexture);

    // Bind the texture name. 

    glBindTexture(GL_TEXTURE_2D, spriteTexture);

    // Set the texture parameters to use a minifying filter and a linear filer (weighted average)

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_LINEAR);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );



    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, spriteWidth, spriteHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);

glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

 glClearColor(.0f, 0.0f, 0.0f, .0f);

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);



 //Setup model view matrix

 glMatrixMode(GL_MODELVIEW);



GLfloat teapot_vertices1[12];




glLoadMatrixf(m);





teapot_vertices1[0] = frames;

teapot_vertices1[1] = frameh;

teapot_vertices1[2] = 0;

teapot_vertices1[3] = frames + framel;;

teapot_vertices1[4] = frameh;

teapot_vertices1[5] = 0;

teapot_vertices1[6] = 0;

teapot_vertices1[7] = 0;

teapot_vertices1[8] = 0;

teapot_vertices1[9] = framel;

teapot_vertices1[10] = 0;

teapot_vertices1[11] = 0;







glVertexPointer(3 ,GL_FLOAT, 0, teapot_vertices1);






for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1)

 {

      glDrawElements(GL_TRIANGLE_STRIP, new_teapot_indicies[i], GL_UNSIGNED_SHORT, &new_teapot_indicies[i+1]);

 }





//glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);



 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

 [context presentRenderbuffer:GL_RENDERBUFFER_OES];

Enabling FSAA (creating a context with a multisampled backbuffer) should help.
For texture-only AA, you could do a 5x5 gaussian with radius chosen from texture coord derivative data.

Hi, Thank you for you post.

I am pretty new to Opengl, could you show some sample code to do this?

THank you again.

Fireman

Actually, the edges and the jaggies inside the image will need different solutions.

Turning on hardware anti-aliasing will help with your edges. But your OpenGL-ES (iPhone?) hardware may not support that. Google for anti-aliasing on your platform.

You could also cheat by adding a one pixel transparent border - that plus linear filtering will soften edges.

The jaggies inside the images look your texture sampling method, but I see:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_LINEAR);
In your code. Weird. That doesn’t look like linear filtered.

Where’s the code where you set your texture co-ordinates? I wonder, looking at your vertices being set up, whether you aren’t using a rectangle texture somehow? And you turned on linear filtering for Power-Of-Two textures (GL_TEXTURE_2D)?

Bruce

On that note, I see where you are loading the texture base map, but not where you are generating the texture MIPmaps. Did I miss it?

http://www.opengl.org/sdk/docs/man4/xhtml/glGenerateMipmap.xml

The key question with each case of stairstep aliasing in your image is whether that edge (e.g. green/red boundary, or red/black boundary) is an edge in the texture data or an edge in the geometry (triangles) you are rendering. If the former, your code needs fixed to properly implement min/mag filtering on the texture. If the latter, enable MSAA rendering. As Bruce mentioned, you’re going to need MSAA for the edges of geometry (e.g. the outside of the red rectangle) – or some other solution. For edges internal to the texture, min/mag filtering + MIPmaps.

I am trying to use MSAA, here is my code. But it did not display anything. !!!

-(void) createMultisampleFrameBuffer
{
glGenFramebuffers(1, &sampleFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, sampleFramebuffer);

glGenRenderbuffers(1, &sampleColorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, sampleColorRenderbuffer);
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_RGBA8_OES, backingWidth, backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, sampleColorRenderbuffer);

glGenRenderbuffers(1, &sampleDepthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, sampleDepthRenderbuffer);
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, sampleDepthRenderbuffer);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));

}

  • (BOOL)createFramebuffer
    {
    // Generate IDs for a framebuffer object and a color renderbuffer
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    // This call associates the storage for the current render buffer with the EAGLDrawable (our CAEAGLLayer)
    // allowing us to draw into a buffer that will later be rendered to screen wherever the layer is (which corresponds with our view).
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    // For this sample, we also need a depth buffer, so we’ll create and attach one via another renderbuffer.
    glGenRenderbuffersOES(1, &depthRenderbuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
    {
    NSLog(@“failed to make complete framebuffer object %x”, glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
    return NO;
    }

#ifdef _USE_MSAA
[self createMultisampleFrameBuffer];
#endif

return YES;

}

  • (void)drawView
    {
    // Make sure that you are drawing to the current context
    [EAGLContext setCurrentContext:context];

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glClearColor(.0f, 0.0f, 0.0f, .0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

#ifdef _USE_MSAA
glBindFramebuffer(GL_FRAMEBUFFER, sampleFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#endif

//Setup model view matrix
glMatrixMode(GL_MODELVIEW);

GLfloat teapot_vertices1[12];



glVertexPointer(3 ,GL_FLOAT, 0, teapot_vertices1);


// Draw teapot. The new_teapot_indicies array is an RLE (run-length encoded) version of the teapot_indices array in teapot.h
for(int i = 0; i &lt; num_teapot_indices; i += new_teapot_indicies[i] + 1)
{
	glDrawElements(GL_TRIANGLE_STRIP, new_teapot_indicies[i], GL_UNSIGNED_SHORT, &new_teapot_indicies[i+1]);
}


//glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

#ifdef _USE_MSAA
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, viewFramebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, sampleFramebuffer);
glResolveMultisampleFramebufferAPPLE();

const GLenum discards[]  = {GL_COLOR_ATTACHMENT0,GL_DEPTH_ATTACHMENT};
//glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE,2,discards);

glBindRenderbuffer(GL_RENDERBUFFER, sampleColorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];

#else

glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];

#endif

}

How about also using glHint(GL_PERSPECTIVE_CORRECTION_HINT,…) on the textured object, along with mip-mapping, as it also deals with interpolation of texels ??