cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

sherrick01821
Journeyman III

Offscreen rendering with OpenGL

I would like to do rendering into an offscreen buffer attached to a texture but don't know how to do it. Could someone tell me the calls to make?

0 Likes
10 Replies
gsellers
Staff
Staff

Re: Offscreen rendering with OpenGL

Hi,

You need to use a Frame Buffer Object (FBO). It's well documented in the spec and you should be able to find examples on line. However, the basic set of operations is to:

  1. Create your texture (glGenTextures, glBindTexture, glTexStorage2D).
  2. Create a framebuffer object and bind it (glGenFramebuffers, glBindFramebuffer).
  3. Attach the texture to the framebuffer (glFramebufferTexture2D).
  4. Set the draw buffers to COLOR_ATTACHMENT0 (glDrawBuffers).

Now when you draw, you'll draw into the texture. To render to the screen again, bind 0 as the framebuffer (glBindFramebuffer again), and set the draw buffer to GL_BACK (glDrawBuffers again).

You can look up all the functions above in the OpenGL reference pages here http://www.opengl.org/sdk/docs/man4/. They should have enough information for you to get this working. Let us know if you have any issues.

Cheers,

Graham

sherrick01821
Journeyman III

Re: Offscreen rendering with OpenGL

Graham:

Thanks for the info. I”ll try it. One other colleague of mine says he did it but didn’t use glDrawBuffers().

He does his like this. Will this work as well?

Steve

============

I declare the following globals:

GLuint renderTex,framebuffer;

GLint renderTexRes = 1742;

============

Then I make the framebuffer object:

//

// create the extra framebuffer and render-target

//

void initRenderTexture(int resx, int resy) {

const GLubyte * strExt;

fprintf(stdout,"Creating render texture of %d x

%d\n",resx,resy);

// make sure OpenGL environment is OK

strExt = glGetString (GL_EXTENSIONS);

if (gluCheckExtension((const

GLubyte*)"GL_EXT_framebuffer_object",

strExt) == GL_FALSE) {

fprintf(stderr,"GL_EXT_framebuffer_object does not

exist!\n");

baseGraceful(1);

}

// create the OGL framebuffer structure

glGenFramebuffersEXT(1, &framebuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);

// create the OGL texture structure

glGenTextures(1, &renderTex);

glBindTexture(GL_TEXTURE_2D, renderTex);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,

GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,

GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, (GLsizei)resx,

(GLsizei)resy,

0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

// attach the texture to the framebuffer

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,

GL_COLOR_ATTACHMENT0_EXT,

GL_TEXTURE_2D, renderTex, 0);

return;

}

initRenderTexture(renderTexRes,renderTexRes);

============

When I draw, I do the following:

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glViewport((GLint)0,(GLint)0,(GLsizei)renderTexRes,(GLsizei)renderTexRes);

// draw my stuff that goes on the texture

// switch back to drawing to the screen

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

glViewport((GLint)0,(GLint)0,(GLsizei)runx,(GLsizei)runy);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// draw a polygon that uses that texture

From: gsellers

Sent: Thursday, May 31, 2012 7:44 AM

To: Steven Herrick

Subject: Re: Offscreen rendering with OpenGL | AMD Developer Forums

AMD Developer Forums

Re: Offscreen rendering with OpenGL

in Graphics Programming

0 Likes
gsellers
Staff
Staff

Re: Offscreen rendering with OpenGL

Hi Steve,

Actually the call to glDrawBuffers is not necessary if you're only ever going to render to the first attachment on that FBO and won't ever change that. The default draw buffer for a user-created FBO is COLOR_ATTACHMENT0 and so that first call to glDrawBuffers is technically redundant. If you want to render to multiple attachments or otherwise do anything with a non-default state, you can delay the call to glDrawBuffers until then.

The other thing I noticed is that you're using the EXT_framebuffer_object extension. FBOs are part of core OpenGL now and have been some time. I'd recommend using the core version of the feature rather than the extension if you can.

Cheers,

Graham

0 Likes
sherrick01821
Journeyman III

Re: Offscreen rendering with OpenGL

Graham:

Thanks for the reply. I need help on speeding up the drawing on triangles on the GPU. Instead of the glBegin().. glend() I would like to use vertex buffer objects from what I find out by my research. If this is true then I need to know the best way to do it. My question I have is do I need a normal for every vertex point? I am drawing triangular facets and I have a x,y,z coordinate for each vertex point but I have only 1 normal for each facet right now. Do you have any example code showing how to properly implement vertex buffer objects or is there another , better way to draw triangles?

Thanks,

Steve

From: gsellers

Sent: Friday, June 01, 2012 7:35 AM

To: Steven Herrick

Subject: Re: Offscreen rendering with OpenGL | AMD Developer Forums

AMD Developer Forums

Re: Offscreen rendering with OpenGL

in Graphics Programming

0 Likes
sherrick01821
Journeyman III

Re: Offscreen rendering with OpenGL

Graham:

Does glDrawArrays require the indices in order to properly draw triangles? I have them available if need be. The code that does glBegin() ... glEnd() only has the vertex and normal data

Steve

From: gsellers

Sent: Friday, June 01, 2012 7:35 AM

To: Steven Herrick

Subject: Re: Offscreen rendering with OpenGL | AMD Developer Forums

AMD Developer Forums

Re: Offscreen rendering with OpenGL

in Graphics Programming

0 Likes
gsellers
Staff
Staff

Re: Offscreen rendering with OpenGL

Hi Steve,

Yes, glDrawArrays ignores indices and effectively generates it's own, in order. If that's how your triangles are ordered, then this is the right function for you to use and you don't need to supply indices at all. If you have indices in some arbitrary order, you can use glDrawElements. To do this, place your indices in a buffer object and bind it the the GL_ELEMENT_ARRAY_BUFFER binding point and call glDrawElements. The 'indices' parameter is then interpreted as an offset into that buffer. Either way (glDrawArrays or glDrawElements), it will be substantially faster than using immediate mode.

Cheers,

Graham

0 Likes
sherrick01821
Journeyman III

Re: Offscreen rendering with OpenGL

Graham:

Thanks for the reply. I was able to get the vertex buffer object working. I am now going to get the framebuffer object working. What is a renderbuffer used for when a texture is attached to a framebuffer object. I need both RGBA colors because I do a glReadPixels() for colors but also need depth processed as well. Would a render buffer be used for depth processing? How is the renderbuffer used in the architecture of a frame buffer object?

Thanks,

Steve

From: gsellers

Sent: Monday, June 04, 2012 10:49 AM

To: Steven Herrick

Subject: Re: Offscreen rendering with OpenGL | AMD Developer Forums

AMD Developer Forums

Re: Offscreen rendering with OpenGL

in Graphics Programming

0 Likes
gsellers
Staff
Staff

Re: Offscreen rendering with OpenGL

Hi Steve,

You can draw into a renderbuffer or a texture using an FBO. The main difference between a renderbuffer and a texture is that you cannot read from a renderbuffer in a shader like you can with a texture. This means that the driver can pick an internal storage representation for the renderbuffer that might be more efficient for rendering to because it doesn't really need to worry about reading from it. For the most part, it won't make a difference whether you use a renderbuffer or a texture. I would recommend that you just go ahead and use textures for everything as it will simplify your application.

You'll need at least two textures for your application. One should have an internal format of GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_COMPONENT and you should attach it to the GL_DEPTH_STENCIL_ATTACHMENT point on the FBO. This will become your depth buffer (assuming you need a depth buffer). The second should have a format such as GL_RGBA8 or GL_RGBA16F, for example, depending on the precision you need. The normal, operating system supplied back buffer is normally equivalent to GL_RGBA8.

Once you've set up your FBO, you can render to it as normal. You can use its attachments as textures, or you can read the data back using glReadPixels, glCopyTexSubImage or other such functions. There is no need to call SwapBuffers when you have an FBO bound. Also, you should never need to call functions like glFlush or glFinish with FBOs as functions like glReadPixels implicitly finish rendering before they execute.

Cheers,

Graham

0 Likes
sherrick01821
Journeyman III

Re: Offscreen rendering with OpenGL

Graham:

Thanks for the reply. Ok, so I have 2 textures , one has GL_DEPTH_COMPONENT internal format and the other has GL_RGBA8. If the depth one is attached to the FBO how is the 2nd one used? I need to call glReadPixels() and read back the GL_RGBA8 values as the code expects to read 4-bytes per pixel. Can 1 FBO be attached to 2 textures at the same time?

From: gsellers

Sent: Tuesday, June 05, 2012 9:49 AM

To: Steven Herrick

Subject: Re: Offscreen rendering with OpenGL | AMD Developer Forums

AMD Developer Forums

Re: Offscreen rendering with OpenGL

in Graphics Programming

0 Likes