I think I managed to re-implement MSAA, this time on the framebuffers. @Commander_X, can you please test this patch against revision 15fa8d8 (the last one in PR #407)?
Code: Select all
diff --git a/src/Core/OOOpenGLExtensionManager.h b/src/Core/OOOpenGLExtensionManager.h
index 2fb596a1..de4d102e 100644
--- a/src/Core/OOOpenGLExtensionManager.h
+++ b/src/Core/OOOpenGLExtensionManager.h
@@ -274,6 +274,8 @@ PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLDRAWBUFFERSPROC glDrawBuffers;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
#endif
diff --git a/src/Core/OOOpenGLExtensionManager.m b/src/Core/OOOpenGLExtensionManager.m
index 75671d6f..08710e25 100644
--- a/src/Core/OOOpenGLExtensionManager.m
+++ b/src/Core/OOOpenGLExtensionManager.m
@@ -136,6 +136,8 @@ PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYS
PFNGLDELETEBUFFERSPROC glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)&OOBadOpenGLExtensionUsed;
PFNGLDRAWBUFFERSPROC glDrawBuffers = (PFNGLDRAWBUFFERSPROC)&OOBadOpenGLExtensionUsed;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)&OOBadOpenGLExtensionUsed;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)&OOBadOpenGLExtensionUsed;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)&OOBadOpenGLExtensionUsed;
PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)&OOBadOpenGLExtensionUsed;
#endif
#endif
@@ -682,6 +684,8 @@ static unsigned IntegerFromString(const GLubyte **ioString)
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress ("glDeleteBuffers" );
glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress ("glDrawBuffers" );
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress ("glCheckFramebufferStatus" );
+ glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)wglGetProcAddress ("glTexImage2DMultisample" );
+ glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)wglGetProcAddress ("glRenderbufferStorageMultisample" );
glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)wglGetProcAddress ("glBlitFramebuffer" );
}
#endif
diff --git a/src/Core/Universe.h b/src/Core/Universe.h
index bda93dd8..d8ef43a0 100644
--- a/src/Core/Universe.h
+++ b/src/Core/Universe.h
@@ -351,9 +351,12 @@ enum
BOOL _dockingClearanceProtocolActive;
BOOL _doingStartUp;
+ GLuint msaaTextureID;
GLuint targetTextureID;
GLuint passthroughTextureID[2];
NSSize targetFramebufferSize;
+ GLuint msaaFramebufferID;
+ GLuint msaaDepthBufferID;
GLuint targetDepthBufferID;
GLuint targetFramebufferID;
GLuint passthroughFramebufferID;
diff --git a/src/Core/Universe.m b/src/Core/Universe.m
index 3659045d..81975237 100644
--- a/src/Core/Universe.m
+++ b/src/Core/Universe.m
@@ -313,6 +313,29 @@ static GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEV
GLint previousElementBuffer;
OOGL(glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &previousElementBuffer));
+ // create MSAA framebuffer and attach MSAA texture and depth buffer to framebuffer
+ OOGL(glGenFramebuffers(1, &msaaFramebufferID));
+ OOGL(glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebufferID));
+
+ // creating MSAA texture that should be rendered into
+ OOGL(glGenTextures(1, &msaaTextureID));
+ OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID));
+ OOGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA16F, viewSize.width, viewSize.height, GL_TRUE));
+ OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0));
+ OOGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID, 0));
+
+ // create necessary MSAA depth render buffer
+ OOGL(glGenRenderbuffers(1, &msaaDepthBufferID));
+ OOGL(glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBufferID));
+ OOGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32F, viewSize.width, viewSize.height));
+ OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
+ OOGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msaaDepthBufferID));
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ OOLogERR(@"initTargetFramebufferWithViewSize.result", @"***** Error: Multisample framebuffer not complete");
+ }
+
// create framebuffer and attach texture and depth buffer to framebuffer
OOGL(glGenFramebuffers(1, &targetFramebufferID));
OOGL(glBindFramebuffer(GL_FRAMEBUFFER, targetFramebufferID));
@@ -395,6 +418,8 @@ static GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEV
OOLogERR(@"initTargetFramebufferWithViewSize.result", @"***** Error: Pingpong framebuffers not complete");
}
}
+ OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
+
_bloom = YES;
_currentPostFX = OO_POSTFX_NONE;
@@ -452,10 +477,13 @@ static GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEV
- (void) deleteOpenGLObjects
{
+ OOGL(glDeleteTextures(1, &msaaTextureID));
OOGL(glDeleteTextures(1, &targetTextureID));
OOGL(glDeleteTextures(2, passthroughTextureID));
OOGL(glDeleteTextures(2, pingpongColorbuffers));
+ OOGL(glDeleteRenderbuffers(1, &msaaDepthBufferID));
OOGL(glDeleteRenderbuffers(1, &targetDepthBufferID));
+ OOGL(glDeleteFramebuffers(1, &msaaFramebufferID));
OOGL(glDeleteFramebuffers(1, &targetFramebufferID));
OOGL(glDeleteFramebuffers(2, pingpongFBO));
OOGL(glDeleteFramebuffers(1, &passthroughFramebufferID));
@@ -471,10 +499,20 @@ static GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEV
- (void) resizeTargetFramebufferWithViewSize:(NSSize)viewSize
{
int i;
+ // resize MSAA color attachment
+ OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureID));
+ OOGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA16F, viewSize.width, viewSize.height, GL_TRUE));
+ OOGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0));
+
+ // resize MSAA depth attachment
+ OOGL(glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBufferID));
+ OOGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32F, viewSize.width, viewSize.height));
+ OOGL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
+
// resize color attachments
- OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
- OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, viewSize.width, viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
- OOGL(glBindTexture(GL_TEXTURE_2D, 0));
+ OOGL(glBindTexture(GL_TEXTURE_2D, targetTextureID));
+ OOGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, viewSize.width, viewSize.height, 0, GL_RGBA, GL_FLOAT, NULL));
+ OOGL(glBindTexture(GL_TEXTURE_2D, 0));
for (i = 0; i < 2; i++)
{
@@ -650,6 +688,8 @@ static GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEV
wireframeGraphics = [prefs oo_boolForKey:@"wireframe-graphics" defaultValue:NO];
doProcedurallyTexturedPlanets = [prefs oo_boolForKey:@"procedurally-textured-planets" defaultValue:YES];
[inGameView setGammaValue:[prefs oo_floatForKey:@"gamma-value" defaultValue:1.0f]];
+ [inGameView setMsaa:[prefs oo_boolForKey:@"anti-aliasing" defaultValue:NO]];
+ OOLog(@"MSAA.setup", @"Multisample anti-aliasing %@requested.", [inGameView msaa] ? @"" : @"not ");
[inGameView setFov:OOClamp_0_max_f([prefs oo_floatForKey:@"fov-value" defaultValue:57.2f], MAX_FOV_DEG) fromFraction:NO];
if ([inGameView fov:NO] < MIN_FOV_DEG) [inGameView setFov:MIN_FOV_DEG fromFraction:NO];
@@ -4700,7 +4740,14 @@ static const OOMatrix starboard_matrix =
if([self useShaders])
{
- OOGL(glBindFramebuffer(GL_FRAMEBUFFER, targetFramebufferID));
+ if ([gameView msaa])
+ {
+ OOGL(glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebufferID));
+ }
+ else
+ {
+ OOGL(glBindFramebuffer(GL_FRAMEBUFFER, targetFramebufferID));
+ }
}
if (!no_update)
@@ -5109,11 +5156,20 @@ static const OOMatrix starboard_matrix =
}
}
- OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
OOLog(@"universe.profile.draw", @"%@", @"End drawing");
if([self useShaders])
{
+ if ([gameView msaa])
+ {
+ // resolve MSAA framebuffer to target framebuffer
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFramebufferID);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFramebufferID);
+ glBlitFramebuffer(0, 0, (int)[gameView viewSize].width, (int)[gameView viewSize].height, 0, 0, (int)[gameView viewSize].width, (int)[gameView viewSize].height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+
+ OOGL(glBindFramebuffer(GL_FRAMEBUFFER, defaultDrawFBO));
+
OOLog(@"universe.profile.secondPassDraw", @"%@", @"Begin second pass draw");
[self drawTargetTextureIntoDefaultFramebuffer];
OOLog(@"universe.profile.secondPassDraw", @"%@", @"End second pass drawing");
diff --git a/src/SDL/MyOpenGLView.h b/src/SDL/MyOpenGLView.h
index 82426aca..b434f19b 100644
--- a/src/SDL/MyOpenGLView.h
+++ b/src/SDL/MyOpenGLView.h
@@ -173,6 +173,7 @@ extern int debug;
float _gamma;
float _fov;
+ float _msaa;
// Full screen sizes
NSMutableArray *screenSizes;
@@ -313,6 +314,9 @@ extern int debug;
- (void) setFov:(float)value fromFraction:(BOOL)fromFraction;
- (float) fov:(BOOL)inFraction;
+- (void) setMsaa:(BOOL)newMsaa;
+- (BOOL) msaa;
+
// Check current state of shift key rather than relying on last event.
+ (BOOL)pollShiftKey;
diff --git a/src/SDL/MyOpenGLView.m b/src/SDL/MyOpenGLView.m
index a770587c..d87eee82 100644
--- a/src/SDL/MyOpenGLView.m
+++ b/src/SDL/MyOpenGLView.m
@@ -2514,6 +2514,18 @@ static NSString * kOOLogKeyDown = @"input.keyMapping.keyPress.keyDown";
}
+- (BOOL) msaa
+{
+ return _msaa;
+}
+
+
+- (void) setMsaa:(BOOL)newMsaa
+{
+ _msaa = !!newMsaa;
+}
+
+
- (OOOpenGLMatrixManager *) getOpenGLMatrixManager
{
return matrixManager;