Jump to content
  • Advertisement
Sign in to follow this  
mushroomfire

OpenGL MSAA help

This topic is 1012 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am trying to enable MSAA for my game, and I'm trying to understand how it works in OpenGL, its a bit confusing. I am looking at https://www.opengl.org/wiki/Multisampling attempting to make sense of it. This is what I have so far:

 

Creating framebuffer:

			// Create framebuffer
			glGenFramebuffers(1, &fbo);
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);

			// Create multisampled texture
			glGenTextures(1, &prim);
			glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, prim);
			glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, aasamples, GL_RGBA8, width, height, GL_TRUE);


			GLuint rbo;
			glGenRenderbuffers(1, &rbo);
			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
			glBindRenderbuffer(GL_RENDERBUFFER, 0);
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

			if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
				return;
			}
			glBindFramebuffer(GL_FRAMEBUFFER, 0);

Drawing:

			glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
			glDrawBuffer(GL_BACK);
			glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                        glDrawElements(prim, size, GL_UNSIGNED_INT, 0);

                        glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
                        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
                        glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

                        SwapBuffers(hdc);

Can anyone point me in the right direction? or just list the steps needed to render an object with multisampling enabled? The code above is really messy, and is really just things I threw together based on what I could find online.

Share this post


Link to post
Share on other sites
Advertisement

I think, for the default framebuffer, you tell the windowing system to give you MSAA, when you create the context.

 

Section 3.2 seems relevant for that purpose in the linked page (assuming you use raw windows API and not some library for creating window/context).

Edited by Waterlimon

Share this post


Link to post
Share on other sites

I think, for the default framebuffer, you tell the windowing system to give you MSAA, when you create the context.

 

Section 3.2 seems relevant for that purpose in the linked page (assuming you use raw windows API and not some library for creating window/context).

 

Alright, so I took a look at Section 3.2 and added the attributes code they have to mine. It looks like:

			PIXELFORMATDESCRIPTOR pfd = {
				sizeof(PIXELFORMATDESCRIPTOR),  // Size of this structure
				1,                              // Version of this structure
				PFD_DRAW_TO_WINDOW |            // Draw to Window (not to bitmap)
				PFD_SUPPORT_OPENGL |            // Support OpenGL calls in window
				PFD_DOUBLEBUFFER |              // Double buffered mode
				PFD_STEREO_DONTCARE,
				PFD_TYPE_RGBA,                  // RGBA Color mode
				32,                             // Want the display bit depth
				0, 0, 0, 0, 0, 0,                    // Not used to select mode
				0, 0,                            // Not used to select mode
				0, 0, 0, 0, 0,                      // Not used to select mode
				24,                             // Size of depth buffer
				8,                              // bit stencil
				0,                              // Not used to select mode
				PFD_MAIN_PLANE,                 // Draw in main plane
				0,                              // Not used to select mode
				0, 0, 0
			};


			int pixFmt = ChoosePixelFormat(hdc, &pfd);
			SetPixelFormat(hdc, pixFmt, &pfd);

			// Make temp context
			auto tc = wglCreateContext(hdc);
			wglMakeCurrent(hdc, tc);

			glewInit();

			UINT numpf;
			int piAttributes[] = {
				WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
				WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
				WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
				WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
				WGL_COLOR_BITS_ARB, 32,
				WGL_DEPTH_BITS_ARB, 24,
				WGL_STENCIL_BITS_ARB, 8,
				WGL_SAMPLE_BUFFERS_ARB, 1, //Number of buffers (must be 1 at time of writing)
				WGL_SAMPLES_ARB, 4,        //Number of samples
				0
			};

			wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
			wglChoosePixelFormatARB(hdc, piAttributes, 0, 1, &pixFmt, &numpf);
			DescribePixelFormat(hdc, pixFmt, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
			SetPixelFormat(hdc, pixFmt, &pfd);

			int attribs[] = {
				WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
				WGL_CONTEXT_MINOR_VERSION_ARB, 3,
				WGL_CONTEXT_FLAGS_ARB, 0,
				0 };

			context = wglCreateContextAttribsARB(hdc, 0, attribs);

			wglMakeCurrent(0, 0);
			wglDeleteContext(tc);
			wglMakeCurrent(hdc, context);

Is this right? I'm still getting aliased lines on my objects, so the problem doesn't seem to be here.

Share this post


Link to post
Share on other sites

I did not read everything, but here is what cached my eye:

I assume you use the same sample count for all render images. So aasamples must be 4 because your renderbuffer for depth uses 4 samples.

In your drawing code

glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glDrawBuffer(GL_BACK);
...

First you want to bind your fbo to GL_DRAW_FRAMEBUFFER

Also glDrawBuffer(GL_BACK) makes no sense there. GL_BACK is only a valid value for the default frame buffer.
And for a simple fbo with only one color image like yours, you don't have to use glDrawBuffer at all.

In general: Rendering to a multi sample fbo and then blitting to the default frame buffer that is not multi sample IS FINE.

@Waterlimon
GL_MULTISAMPLE is enabled by default

Edited by Osbios

Share this post


Link to post
Share on other sites
I forgot: You also didn't bind the texture to the fbo.

glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, prim, 0);
Note: glFramebufferTexture needs GL 3.2 otherwise you have to use glFramebufferTexture2D.

Share this post


Link to post
Share on other sites

@Osbios

Would I still need a renderbuffer? It doesn't seem like it's being used anywhere.

It seems like it's working but only if I comment out this line:

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

otherwise it just gives me a black screen.

 

Also it seems like some objects aren't rendering... Not sure what might be causing it.

Edited by MushroomFire

Share this post


Link to post
Share on other sites
I ask my first question again: Did you make sure you are using the same sample count for texture and renderbuffer?

Share this post


Link to post
Share on other sites

Yeah, here's the updated code:

                        // Create framebuffer
			glGenFramebuffers(1, &fbo);
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);

			// Create multisampled color texture
			glGenTextures(1, &prim);
			glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, prim);
			glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, aasamples, GL_RGBA8, window->getSize().x(), window->getSize().y(), GL_TRUE);

			GLuint rbo;
			glGenRenderbuffers(1, &rbo);
			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, aasamples, GL_DEPTH24_STENCIL8, width, height);
			glBindRenderbuffer(GL_RENDERBUFFER, 0);
			//glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

			glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, prim, 0);

			if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
				return;
			}

and the draw:

			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
			glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glDrawElements(prim, size, GL_UNSIGNED_INT, 0);

			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
			glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);

			SwapBuffers(hdc);

Share this post


Link to post
Share on other sites

And now you are using different variables for the size. Is width and height the same as window->getSize().x() and window->getSize().y()?

Don't understand me wrong, you actually can use different sized targets for a FBO. If for example you attach a 100x100 and a 1000x1000 draw target to a FBO. OpenGL will only draw to the 100x100 area on BOTH targets. But I'm sure that is not what you want.

Also don't cut out so much code. Often the error is hidden in code nobody else sees because it did not get posted. Best way is to get a minimal example that is still able to compile.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!