views:

55

answers:

1

I want to implement MSAA into the Unity build of a game. Currently I am using this code I got from the Unity forums and it compiles but I can clearly see that it is having no effect in game. Any help would be appreciated.

bool msaaEnabled = false;
CGSize globalSize; 

struct MyEAGLSurface
{
    GLuint      format;
    GLuint      depthFormat;
    GLuint      framebuffer;
    GLuint      renderbuffer;
    GLuint      msaaFrameBuffer;   
    GLuint      msaaRenderBuffer;   
    GLuint      msaaDepthBuffer;   
    GLuint      depthBuffer;
    CGSize      size; 
};

typedef EAGLContext*    MyEAGLContext;

@interface EAGLView : UIView {}
@end

MyEAGLContext           _context;
MyEAGLSurface           _surface;
UIWindow *              _window;
NSTimer*                _timer;
id                      _displayLink;
BOOL                    _accelerometerIsActive = NO;

extern "C" void MSAA_Enabled( bool enabled )
{   
    if( enabled && !msaaEnabled )
    {
        // Create MSAA buffers!
        glGenFramebuffersOES(1, &_surface.msaaFrameBuffer );
        glGenRenderbuffersOES(1, &_surface.msaaRenderBuffer );
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, _surface.msaaFrameBuffer );
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, _surface.msaaRenderBuffer );

        // Samples is the amount of pixels the MSAA buffer uses to make one pixel on the render
        // buffer. Use a small number like 2 for the 3G and below and 4 or more for newer models
        int samples = 4;
        glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samples, GL_RGB5_A1_OES, globalSize.width, globalSize.height);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _surface.msaaRenderBuffer);

        // MSAA Depth buffer
        glGenRenderbuffersOES(1, &_surface.msaaDepthBuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, _surface.msaaDepthBuffer);
        glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, samples, _surface.depthFormat, globalSize.width, globalSize.height);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _surface.msaaDepthBuffer);
    }
    else
    {
    }

    msaaEnabled = enabled;
}

extern "C" void MSAA_BindTarget()
{
    if( _surface.msaaFrameBuffer && msaaEnabled )
    {
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, _surface.msaaFrameBuffer); //Bind MSAA
    }   
} 

bool CreateWindowSurface(EAGLView *view, GLuint format, GLuint depthFormat, bool retained, MyEAGLSurface* surface)
{
    CGSize newSize;
    GLuint oldRenderbuffer;
    GLuint oldFramebuffer;

        CAEAGLLayer* eaglLayer = (CAEAGLLayer*)[view layer];

    surface->format = format;
    surface->depthFormat = depthFormat;

    surface->msaaFrameBuffer = 0;
    surface->msaaRenderBuffer = 0;
    surface->msaaDepthBuffer = 0;
    surface->depthBuffer = 0;
    surface->renderbuffer = 0;
    surface->framebuffer = 0;

    eaglLayer.opaque = YES;
    eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];

    newSize = [eaglLayer bounds].size;
    newSize.width = roundf(newSize.width);
    newSize.height = roundf(newSize.height);

    globalSize = newSize;

    glGetIntegerv(GL_RENDERBUFFER_BINDING_OES, (GLint *) &oldRenderbuffer);
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, (GLint *) &oldFramebuffer);

    // Create the main frame and render buffers
    glGenFramebuffersOES(1, &surface->framebuffer);
    glGenRenderbuffersOES(1, &surface->renderbuffer);

    // Bind the frame and render buffer
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, surface->framebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, surface->renderbuffer);

    // Set storage for render buffer
    if(![_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer])
    {
        glDeleteRenderbuffersOES(1, &surface->renderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_BINDING_OES, oldRenderbuffer);
        return false;
    }

    // Attach the renderbuffer
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, surface->renderbuffer);

    if (depthFormat)
    {      
        // Regular depth buffer
        glGenRenderbuffersOES(1, &surface->depthBuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, surface->depthBuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, surface->depthFormat, newSize.width, newSize.height);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, surface->depthBuffer);
    }

    surface->size = newSize;
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, oldRenderbuffer);

    CHECK_GL_ERROR();   

    return true; 
}

void DestroySurface(MyEAGLSurface* surface)
{
    EAGLContext *oldContext = [EAGLContext currentContext];

    if (oldContext != _context)
        [EAGLContext setCurrentContext:_context];

    if(surface->msaaDepthBuffer)
    {
        glDeleteRenderbuffersOES(1, &surface->msaaDepthBuffer);
        surface->msaaDepthBuffer = 0;
    }

    if(surface->depthBuffer)
    {
        glDeleteRenderbuffersOES(1, &surface->depthBuffer);
        surface->depthBuffer = 0;
    }

    glDeleteRenderbuffersOES(1, &surface->msaaRenderBuffer);
    surface->msaaRenderBuffer = 0;

    glDeleteFramebuffersOES(1, &surface->msaaFrameBuffer);
    surface->msaaFrameBuffer = 0;

    glDeleteRenderbuffersOES(1, &surface->renderbuffer);
    surface->renderbuffer = 0;

    glDeleteFramebuffersOES(1, &surface->framebuffer);
    surface->framebuffer = 0;

    if (oldContext != _context)
        [EAGLContext setCurrentContext:oldContext];
}

void PresentSurface(MyEAGLSurface& surface)
{
    EAGLContext *oldContext = [EAGLContext currentContext];
    GLuint oldRenderbuffer;

    if (oldContext != _context)
        [EAGLContext setCurrentContext:_context];

    CHECK_GL_ERROR();

    glGetIntegerv(GL_RENDERBUFFER_BINDING_OES, (GLint *) &oldRenderbuffer);

    if( msaaEnabled )
    {
        glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, surface.msaaFrameBuffer);
        glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, surface.framebuffer);

        // Call a resolve to combine buffers
        glResolveMultisampleFramebufferAPPLE();   
    }

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, surface.renderbuffer);

    if(![_context presentRenderbuffer:GL_RENDERBUFFER_OES])
        EAGL_ERROR("swap renderbuffer");

    if(oldContext != _context)
        [EAGLContext setCurrentContext:oldContext];
}   

void PresentContext_UnityCallback(struct UnityFrameStats const* unityFrameStats)
{   
#if ENABLE_INTERNAL_PROFILER
    _unityFrameStats = *unityFrameStats;

    if (_frameId % BLOCK_ON_GPU_EACH_NTH_FRAME == (BLOCK_ON_GPU_EACH_NTH_FRAME-1))
    {
        Prof_Int64 gpuTime0 = mach_absolute_time();

#if ENABLE_BLOCK_ON_GPU_PROFILER
        UnityFinishRendering();
#endif

        Prof_Int64 gpuTime1 = mach_absolute_time();
        _gpuDelta = gpuTime1 - gpuTime0;
    }
    else
        _gpuDelta = 0;
#endif


#if ENABLE_INTERNAL_PROFILER
    Prof_Int64 swapTime0 = mach_absolute_time();
#endif

    PresentSurface(_surface);

#if ENABLE_INTERNAL_PROFILER
    Prof_Int64 vblankTime = mach_absolute_time();

    if (_lastVBlankTime < 0) _lastVBlankTime = vblankTime;
    _frameDelta = vblankTime - _lastVBlankTime; _lastVBlankTime = vblankTime;

    Prof_Int64 swapTime1 = vblankTime;
    _swapDelta = swapTime1 - swapTime0;
#endif
    }

int OpenEAGL_UnityCallback(UIWindow** window, int* screenWidth, int* screenHeight)
{
    CGRect rect = [[UIScreen mainScreen] bounds];

    // Create a full-screen window
    _window = [[UIWindow alloc] initWithFrame:rect];
    EAGLView* view = [[EAGLView alloc] initWithFrame:rect];
    [_window addSubview:view];

    //CAEAGLLayer* eaglLayer = (CAEAGLLayer*)[view layer];
    _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

    MSAA_Enabled(true);
    MSAA_BindTarget();

    if (!_context)
        return false;

    if (![EAGLContext setCurrentContext:_context]) {
        _context = 0;
        return false;
    }

    if (!CreateWindowSurface(view, GL_RGB565_OES, GL_DEPTH_COMPONENT16_OES, NO, &_surface)) {
        return false;
    }

    glViewport(0, 0, _surface.size.width, _surface.size.height);
    [_window makeKeyAndVisible];
    [view release];

    *window = _window;
    *screenWidth = _surface.size.width;
    *screenHeight = _surface.size.height;   

    return true;
}
A: 

Got it working with some help from the Unity forums. If anyone wants to know how to implement, take a look at the thread here: http://forum.unity3d.com/threads/60785-iPhone-4-MSAA-Test-Results

The code provided at the bottom of the thread only seemed to compile using a Unity 3.0 build, btw.

fraggleRockz