我正在使用带有C#的OpenGL,为我们的项目使用CSGL12接口。我试图在内存中的位图上绘制一些4点自由变换图像。
有没有办法:
任何一种方法都必须适用于远程桌面,虚拟机和Panasonic CF-19 Toughbook(即OpenGL v1.1)。如果可能的话,提供与之相关的示例代码将会有很大帮助。
答案 0 :(得分:2)
你知道,OpenGL-1.1现在已经过时了。即使市场上最疯狂的GPU也可以立即使用OpenGL-1.4。首先应该知道的一点是,OpenGL设计用于在屏幕上获取图片,尽管输出后端的性质在规范中是抽象的。如果您想使用OpenGL来渲染加速的3D内容,那么不会渲染到位图。这将使您回到软件光栅化模式,非常慢因此使用PBuffer或Framebuffer对象。 Framebuffer对象很难使用。但PBuffers有点棘手。
在Windows中,您总是需要先绕过创建一个带有一些OpenGL上下文的虚拟窗口,以便您可以请求和使用OpenGL扩展。使用X11 / GLX可以创建没有该虚拟窗口的PBuffer。然而,PBuffer的常用用途是创建动态纹理内容的地方。
以下是我很久以前编写的一些代码,它默默地假设现有的,有效初始化的OpenGL上下文在当前线程上处于活动状态,并将配置PBuffer上下文以与原始上下文共享其OpenGL对象。它还取决于库 GLEW 。
pbuffer.h
#ifndef PBUFFER_H
#define PBUFFER_H
#ifdef WIN32
#include <GL/wglew.h>
#endif
#ifdef GLX
#ifdef NOGLEW
#include <GL/glx.h>
#else
#include <GL/glxew.h>
#endif
#endif
class PBuffer
{
public:
PBuffer(int width, int height);
virtual ~PBuffer();
void Use();
void Release();
int const get_width() const { return width; }
int const get_height() const { return height; }
private:
void Create();
void Destroy();
protected:
int width;
int height;
bool initialized;
#ifdef WIN32
HPBUFFERARB hPB;
HGLRC hPBRC;
HDC hPBDC;
HDC hGLDC;
HGLRC hGLRC;
#endif
#ifdef GLX
Display *dpy;
int scrnum;
GLXContext PBRC;
GLXPbuffer PBDC;
GLXContext FBRC;
GLXDrawable FBDC;
#endif
};
#endif/*PBUFFER_H*/
pbuffer.cpp
#include <stdexcept>
#include <GL/glew.h>
#include "pbuffer.h"
using namespace std;
#ifdef WIN32
PBuffer::PBuffer(int width, int height)
{
initialized=false;
this->width=width;
this->height=height;
hGLDC = wglGetCurrentDC();
hGLRC = wglGetCurrentContext();
Create();
}
PBuffer::~PBuffer()
{
Destroy();
}
void PBuffer::Use()
{
// make sure the pbuffer has been initialized
if (!initialized)
{
throw runtime_error("pbuffer is not initialized");
}
// make sure we haven't lost our pbuffer due to a display mode change
int flag = 0;
wglQueryPbufferARB(hPB, WGL_PBUFFER_LOST_ARB, &flag);
if (flag)
{
throw runtime_error("pbuffer became invalid");
}
wglMakeCurrent(hPBDC, hPBRC);
glViewport(0, 0, width, height);
glDrawBuffer(GL_FRONT);
glReadBuffer(GL_FRONT);
}
void PBuffer::Release()
{
// make sure the pbuffer has been initialized
if ( !initialized )
{
throw runtime_error("pbuffer is not initialized");
}
// make sure we haven't lost our pbuffer due to a display mode change
int flag = 0;
wglQueryPbufferARB(hPB, WGL_PBUFFER_LOST_ARB, &flag);
if (flag)
{
throw runtime_error("pbuffer became invalid");
}
wglMakeCurrent(hGLDC, hGLRC);
}
void PBuffer::Create()
{
if(initialized)
{
Destroy();
}
if (hGLDC == NULL)
{
throw runtime_error("unable to get device context");
}
if (hGLRC == NULL)
{
throw runtime_error("unable to get render context");
}
// define the minimum pixel format requirements we will need for our pbuffer
// a pbuffer is just like a frame buffer, it can have a depth buffer associated
// with it and it can be double buffered.
int attr[] =
{
WGL_SUPPORT_OPENGL_ARB, TRUE, // pbuffer will be used with gl
WGL_DRAW_TO_PBUFFER_ARB, TRUE, // enable render to pbuffer
WGL_RED_BITS_ARB, 16, // at least 8 bits for RED channel
WGL_GREEN_BITS_ARB, 16, // at least 8 bits for GREEN channel
WGL_BLUE_BITS_ARB, 16, // at least 8 bits for BLUE channel
WGL_ALPHA_BITS_ARB, 16, // at least 8 bits for ALPHA channel
WGL_DEPTH_BITS_ARB, 24, // at least 24 bits for depth buffer
WGL_DOUBLE_BUFFER_ARB, FALSE, // we dont require double buffering
0 // zero terminates the list
};
// choose a pixel format that meets our minimum requirements
unsigned int count = 0;
int pixelFormat;
wglChoosePixelFormatARB(hGLDC,(const int*)attr, NULL, 1,&pixelFormat,&count);
if(count == 0)
{
throw runtime_error("no matching pbuffer pixel format found");
}
int attribs[]={0,0};
// allocate the pbuffer
hPB = wglCreatePbufferARB(hGLDC, pixelFormat, width, height, attribs);
hPBDC = wglGetPbufferDCARB(hPB);
hPBRC = wglCreateContext(hPBDC);
wglShareLists(hGLRC, hPBRC);
initialized=true;
}
void PBuffer::Destroy()
{
// make sure the pbuffer has been initialized
if ( !initialized )
{
throw runtime_error("pbuffer is not initialized");
}
Release();
wglDeleteContext(hPBRC);
wglReleasePbufferDCARB(hPB, hPBDC);
wglDestroyPbufferARB(hPB);
initialized = false;
}
#endif
#ifdef GLX
PBuffer::PBuffer(int width, int height)
{
initialized=false;
this->width=width;
this->height=height;
dpy = glXGetCurrentDisplay();
scrnum = DefaultScreen( dpy );
FBRC = glXGetCurrentContext();
FBDC = glXGetCurrentDrawable();
Create();
}
PBuffer::~PBuffer()
{
Destroy();
}
void PBuffer::Use()
{
// make sure the pbuffer has been initialized
if (!initialized)
{
throw runtime_error("pbuffer is not initialized");
}
// make sure we haven't lost our pbuffer due to a display mode change
// resize view port. generally you'll want to set this to the
// size of your pbuffer so that you render to the entire pbuffer
// but there are cases where you might want to render to just a
// sub-region of the pbuffer.
glXMakeContextCurrent(dpy, PBDC, PBDC, PBRC);
glViewport(0, 0, width, height);
glDrawBuffer(GL_FRONT);
glReadBuffer(GL_FRONT);
}
void PBuffer::Release()
{
// make sure the pbuffer has been initialized
if ( !initialized )
{
throw runtime_error("pbuffer is not initialized");
}
// make sure we haven't lost our pbuffer due to a display mode change
glXMakeContextCurrent(dpy, FBDC, FBDC, FBRC);
}
void PBuffer::Create()
{
if(initialized)
{
Destroy();
}
if (dpy == NULL)
{
throw runtime_error("unable to get device context");
}
if (!FBDC)
{
throw runtime_error("unable to get render context");
}
// define the minimum pixel format requirements we will need for our pbuffer
// a pbuffer is just like a frame buffer, it can have a depth buffer associated
// with it and it can be double buffered.
/*int attr[] =
{
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
GLX_DOUBLEBUFFER, False,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_ALPHA_SIZE, 1,
GLX_DEPTH_SIZE, 1,
0 // zero terminates the list
};*/
int attrib[] =
{
GLX_DOUBLEBUFFER, False,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_STENCIL_SIZE, 1,
GLX_DEPTH_SIZE, 24,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
None
};
int PBattrib[] =
{
GLX_PBUFFER_WIDTH, width,
GLX_PBUFFER_HEIGHT, height,
GLX_LARGEST_PBUFFER, False,
None
};
// choose a pixel format that meets our minimum requirements
int count = 0;
//GLXFBConfigSGIX *config=
// glXChooseFBConfigSGIX(dpy, scrnum, attrib, &count);
GLXFBConfig *config=
glXChooseFBConfig(dpy, scrnum, attrib, &count);
if(config == NULL || count == 0)
{
throw runtime_error("no matching pbuffer pixel format found");
}
// allocate the pbuffer
//PBDC=glXCreateGLXPbufferSGIX(dpy, config[0], width, height, PBattrib);
//PBRC=glXCreateContextWithConfigSGIX(dpy, config[0], GLX_RGBA_TYPE_SGIX, FBRC, true);
PBDC=glXCreatePbuffer(dpy, config[0], PBattrib);
PBRC=glXCreateNewContext(dpy, config[0], GLX_RGBA_TYPE, FBRC, true);
XFree(config);
initialized=true;
}
void PBuffer::Destroy()
{
// make sure the pbuffer has been initialized
if ( !initialized )
{
throw runtime_error("pbuffer is not initialized");
}
Release();
glXDestroyContext(dpy, PBRC);
glXDestroyPbuffer(dpy, PBDC);
initialized = false;
}
#endif
答案 1 :(得分:0)
您可以使用Bitmap.LockBits
和glCopyPixels
从缓冲区(opengl调用屏幕外缓冲区“aux”)拉入位图。