|
1.在一个Opengl Context(HGLRC)里创建的Texture不能在另一个Opengl Context中使用.
2.HPBUFFERARB PBuffer对象提供了一种Offsceen Render Target机制,类似于GDI的内存位图,DX的RenderSurface.属Opengl 1.3规范,wgl扩展形式.
2.创建PBuffer: a.使用wglChoosePixelFormatARB获得指定属性特点的象素格式列表,随便选择1个,使用wglCreatePbufferARB创建一个OBuffer对象,取得该PBuffer的关联DC,创建一个Opengl Context,即PBuffer所关联的环境. b.进入该PBuffer的Opengl context,作图. 3.使用wglBindTexImageARB将1个PBuffer关联到当前的纹理对象上,此后若渲染该纹理时将渲染PBuffer表面的数据,此时纹理对象仅是个傀儡,其关联的PBuffer才是真正的数据源.wglBindTexImageARB应该在PBuffer Context之外的Opengl context中调用.
4.使用wglReleaseTexImageARB把PBuffer从其之前关联的Texture对象上释放.在PBuffer被绑定到某Texture后,未释放之前,不得进入PBuffer的Context进行渲染.显然wglReleaseTexImageARB也应该在PBuffer Context之外的Opengl context中调用
5.Render to texture 仅是PBuffer的一种使用方式. 技巧: a.使用glReadPixels读出PBuffer数据,然后在外部Context进行glDrawPixels,或glTexImageData,或直接图像输出,不会有Window Overlayclip 的限制.
6.使用glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE),使得渲染出的纹理数据自动构造为Mipmap.
7.Designed for offscreen rendering - similar to windows, but non-visible! It is a Windows system specific extentsion!
8.Problems:(From GDC Nvida) • Each pbuffer usually has its own OpenGL context context – (Assuming they have different pixel formats) – Can share texture objects, display lists between pbuffers using wglShareLists () – Painful to manage, causes lots of bugs • Switching between pbuffers is expensive – wglMakeCurrent causes context switch • Each pbuffer has its own depth, stencil, aux buffers – Cannot share depth buffers between pbuffers
9.Nvidia Sample http://download.developer.nvidia.com/developer/SDK/Individual_Samples/samples.html
#ifndef __OGL_RENDER_TEXTURE_H__
#define __OGL_RENDER_TEXTURE_H__

struct OglRenderTexture
  {
public:
 enum { MAX_ATTRIBS = 256, MAX_PFORMATS = 256 };

public:
HDC m_hWinDC;
HDC m_hBufDC;
HGLRC m_hWinGLRC;
HGLRC m_hBufGLRC;
HPBUFFERARB m_hpBuffer;
public:
OglRenderTexture()
 {
m_hWinDC = NULL;
m_hBufDC = NULL;
m_hWinGLRC = NULL;
m_hBufGLRC = NULL;
m_hpBuffer = NULL;
}
bool Create(int nWidth, int nHeight)
 {
// Record current context
m_hWinDC = wglGetCurrentDC();
m_hWinGLRC = wglGetCurrentContext();
if(!m_hWinGLRC) return false;
// Query for a suitable pixel format based on the specified mode.
int iAttributes[2*MAX_ATTRIBS];
float fAttributes[2*MAX_ATTRIBS];
memset(iAttributes, 0, sizeof(int)*2*MAX_ATTRIBS);
memset(fAttributes, 0, sizeof(float)*2*MAX_ATTRIBS);
int nIndex = 0;
iAttributes[nIndex++] = WGL_DRAW_TO_PBUFFER_ARB;
iAttributes[nIndex++] = GL_TRUE;
iAttributes[nIndex++] = WGL_BIND_TO_TEXTURE_RGBA_ARB;
iAttributes[nIndex++] = GL_TRUE;
unsigned int nFormats;
int pFormats[MAX_PFORMATS];
glext::wglChoosePixelFormatARB(m_hWinDC, iAttributes, fAttributes, MAX_PFORMATS, pFormats, &nFormats);
CHECKF(nFormats);
// Choose the first one format
int format = pFormats[0];
// Set up the pbuffer attributes
nIndex = 0;
memset(iAttributes, 0, sizeof(int)*2*MAX_ATTRIBS);
iAttributes[nIndex++] = WGL_TEXTURE_FORMAT_ARB;
iAttributes[nIndex++] = WGL_TEXTURE_RGBA_ARB;
iAttributes[nIndex++] = WGL_TEXTURE_TARGET_ARB;
iAttributes[nIndex++] = WGL_TEXTURE_2D_ARB;
iAttributes[nIndex++] = WGL_MIPMAP_TEXTURE_ARB;
iAttributes[nIndex++] = TRUE;
iAttributes[nIndex++] = WGL_PBUFFER_LARGEST_ARB;
iAttributes[nIndex++] = FALSE;
// Create the p-buffer.
m_hpBuffer = glext::wglCreatePbufferARB(m_hWinDC, format, nWidth, nHeight, iAttributes);
if(m_hpBuffer)
 {
// Create pbuffer context
m_hBufDC = glext::wglGetPbufferDCARB(m_hpBuffer);
m_hBufGLRC = wglCreateContext(m_hBufDC);

glext::wglQueryPbufferARB(m_hpBuffer, WGL_PBUFFER_WIDTH_ARB, &nWidth);
glext::wglQueryPbufferARB(m_hpBuffer, WGL_PBUFFER_HEIGHT_ARB, &nHeight);
// 仅使用 2D 模式
wglMakeCurrent(m_hBufDC, m_hBufGLRC);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, nWidth, 0, nHeight, -1, 1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
wglMakeCurrent(m_hWinDC, m_hWinGLRC);

return true;
}
else return false;
}
void Destroy()
 {
if(m_hpBuffer)
 {
// Clean up all resource
wglDeleteContext(m_hBufGLRC);
glext::wglReleasePbufferDCARB(m_hpBuffer, m_hBufDC);
glext::wglDestroyPbufferARB(m_hpBuffer);
m_hBufDC = NULL;
m_hBufGLRC = NULL;
m_hpBuffer = NULL;
}
m_hWinDC = NULL;
m_hWinGLRC = NULL;
}
bool BeginRender(GLuint texture)
 {
if(m_hpBuffer && m_hBufDC && m_hBufGLRC)
 {
// Record current context
m_hWinDC = wglGetCurrentDC();
m_hWinGLRC = wglGetCurrentContext();
// Ensure this texture will be bound in EndRender!
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
// Release the pbuffer from the texture before render to it again!
glext::wglReleaseTexImageARB(m_hpBuffer, WGL_FRONT_LEFT_ARB);
// Switch to pbuffer context
wglMakeCurrent(m_hBufDC, m_hBufGLRC);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
return true;
}
else return false;
}
void EndRender()
 {
// Switch to original main window render context
wglMakeCurrent(m_hWinDC, m_hWinGLRC);
// Bind to texture
glext::wglBindTexImageARB(m_hpBuffer, WGL_FRONT_LEFT_ARB);
}

void RectangleTexture(GLuint texture, int left, int bottom, int width, int height)
 {
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.0f, 0.0f); glVertex2i(left, bottom);
glTexCoord2f(1.0f, 0.0f); glVertex2i(left + width, bottom);
glTexCoord2f(1.0f, 1.0f); glVertex2i(left + width, bottom + height);
glTexCoord2f(0.0f, 1.0f); glVertex2i(left, bottom + height);
glEnd();
}
};

#endif//__OGL_RENDER_TEXTURE_H__
|