Jump to content
  • Advertisement
Sign in to follow this  
Tree Penguin

RTT and pbuffers

This topic is 4653 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

Hi, i got some questions regarding the extensions WGL_ARB_render_texture and WGL_ARB_pbuffer, i couldn't find much documentation on it other than the spec and some documentationless examples. 1. Do i have to use a pbuffer to render to a texture without writing to the framebuffer? 2. Is it possible to use the framebuffer's stencil buffer and depth buffer to render to a texture? 3. If not, what would be the best way to do so (except for rendering the depth buffer to the pbuffer's depth buffer)? Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Unless your card/driver doesn't support it, use the newer GL_EXT_framebuffer_object extension. Here is a sample helper class you may use for it:


class CGLFrameBufferObject
{
protected:
GLuint m_nTextureObject; // The texture object ID
GLuint m_nDepthTextureObject; // The depth texture object ID
GLuint m_nFrameBufferObject; // The frame buffer object ID
GLuint m_nDepthBufferObject; // The depth buffer object ID
GLuint m_nStencilBufferObject; // The stencil buffer object ID

// texture dimensions
GLuint m_nWidth, m_nHeight; // The texture's dimensions
GLenum m_nInternalFormat; // The texture's internal format (i.e. GL_RGBA, GL_RGBA16, GL_RGBA16F_ARB)
GLenum m_nTextureTarget; // The texture target (i.e. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV)
GLenum m_nFilterMode; // The texture filter mode (i.e. GL_NEAREST, GL_LINEAR)

bool CheckFramebufferStatus()
{
GLenum status = (GLenum)glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
LogDebug("Framebuffer complete");
return true;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
LogError("Unsupported framebuffer format");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
LogError("Framebuffer incomplete, missing attachment");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
LogError("Framebuffer incomplete, duplicate attachment");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
LogError("Framebuffer incomplete, attached images must have same dimensions");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
LogError("Framebuffer incomplete, attached images must have same format");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
LogError("Framebuffer incomplete, missing draw buffer");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
LogError("Framebuffer incomplete, missing read buffer");
break;
default:
LogError("Unknown framebuffer status!");
break;
}
return false;
}


public:
CGLFrameBufferObject()
{
m_nTextureObject = 0;
m_nFrameBufferObject = 0;
m_nDepthBufferObject = 0;
m_nStencilBufferObject = 0;
}
~CGLFrameBufferObject() {}

bool IsSupported() { return m_nFrameBufferObject != 0; }

void Cleanup()
{
if(m_nStencilBufferObject)
glDeleteRenderbuffersEXT(1, &m_nStencilBufferObject);
if(m_nDepthBufferObject)
glDeleteRenderbuffersEXT(1, &m_nDepthBufferObject);
if(m_nFrameBufferObject)
glDeleteFramebuffersEXT(1, &m_nFrameBufferObject);
if(m_nDepthTextureObject)
glDeleteTextures(1, &m_nDepthTextureObject);
if(m_nTextureObject)
glDeleteTextures(1, &m_nTextureObject);
m_nTextureObject = 0;
m_nFrameBufferObject = 0;
m_nDepthBufferObject = 0;
m_nStencilBufferObject = 0;
}

bool Init(int nWidth, int nHeight, int nInternalFormat, bool bDepthBuffer=true, bool bStencilBuffer=false)
{
Cleanup();
if(strstr((const char *)glGetString(GL_EXTENSIONS), "GL_EXT_framebuffer_object") == NULL)
{
LogWarning("Framebuffer objects not supported, unable to create fame buffer");
return false;
}

m_nWidth = nWidth;
m_nHeight = nHeight;
m_nInternalFormat = nInternalFormat;
m_nTextureTarget = m_nWidth == m_nHeight ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_NV;
m_nFilterMode = m_nTextureTarget == GL_TEXTURE_RECTANGLE_NV ? GL_NEAREST : GL_LINEAR;

// Generate the texture object
glGenTextures(1, &m_nTextureObject);
glBindTexture(m_nTextureTarget, m_nTextureObject);
glTexImage2D(m_nTextureTarget, 0, m_nInternalFormat, m_nWidth, m_nHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf(m_nTextureTarget, GL_TEXTURE_MIN_FILTER, m_nFilterMode);
glTexParameterf(m_nTextureTarget, GL_TEXTURE_MAG_FILTER, m_nFilterMode);
glTexParameterf(m_nTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(m_nTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
LOG_GLERROR();

// Generate the frame buffer object
glGenFramebuffersEXT(1, &m_nFrameBufferObject);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_nFrameBufferObject);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, m_nTextureTarget, m_nTextureObject, 0);
LOG_GLERROR();

if(bDepthBuffer)
{
// Generate the depth buffer object
glGenRenderbuffersEXT(1, &m_nDepthBufferObject);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_nDepthBufferObject);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_nWidth, m_nHeight);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_nDepthBufferObject);

// create depth texture & attach to FBO
glGenTextures(1, &m_nDepthTextureObject);
glBindTexture(m_nTextureTarget, m_nDepthTextureObject);
glTexImage2D(m_nTextureTarget, 0, GL_DEPTH_COMPONENT, m_nWidth, m_nHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(m_nTextureTarget, GL_TEXTURE_MAG_FILTER, m_nFilterMode);
glTexParameteri(m_nTextureTarget, GL_TEXTURE_MIN_FILTER, m_nFilterMode);
glTexParameteri(m_nTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(m_nTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, m_nTextureTarget, m_nDepthTextureObject, 0);

LOG_GLERROR();
}

if(bStencilBuffer)
{
// Generate the stencil buffer object
glGenRenderbuffersEXT(1, &m_nStencilBufferObject);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_nStencilBufferObject);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX16_EXT, m_nWidth, m_nHeight);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_nStencilBufferObject);
LOG_GLERROR();
}

bool bSuccess = CheckFramebufferStatus();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
if(!bSuccess)
Cleanup();
return bSuccess;
}

void EnableFrameBuffer() { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_nFrameBufferObject); }
void DisableFrameBuffer() { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); }

void EnableTexture() { glBindTexture(m_nTextureTarget, m_nTextureObject); glEnable(m_nTextureTarget); }
void DisableTexture() { glDisable(m_nTextureTarget); glBindTexture(m_nTextureTarget, 0); }
};




EDIT: I don't think the depth texture code above works on GeForce FX level cards, but if you comment it out, the rest should work on an FX card. You can still write to a depth buffer on the FX, but it can't use render-to-texture like the main frame buffer.

Share this post


Link to post
Share on other sites
Ok, i might get it totally wrong, but i guess i can temporarily replace (or is it still writing to both?) the color, depth or stencil buffer of the framebuffer with one of a framebufferobject, am i right?

Anyway, as i will probably use it for the 4E4 contest to it has to run on GF3s and Radeon7500s too, so any other ideas?

[Edited by - Tree Penguin on September 25, 2005 6:04:09 AM]

Share this post


Link to post
Share on other sites
The framebuffer extension is a replacement of the pbuffer extension, but it is platform-independent, and it has some improvements over pbuffers. If the target video card supports the pbuffer extension, then the latest drivers for it may support the framebuffer extension as well.

Without using pbuffers or framebuffers, you may be able to use functions like glCopyPixels, glDrawPixels, and glReadPixels. I believe using them would be very slow.

EDIT: When writing to a pbuffer or framebuffer, you are writing only to the specified buffer (and not to the normal back buffer).

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!