Implement iphone MSAA using Unity build
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-&g开发者_开发知识库t;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;
}
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.
精彩评论