我正在尝试使用OpenGL渲染到使用Windows API创建的窗口的现有渲染区域。我使用wglCreateContext和wglMakeCurrent获取HDC并创建一个opengl上下文。然后我创建一个纹理,然后绑定它。虽然我可以将缓冲区清除到我选择的任何颜色,但我无法渲染它。以下代码示例应该清楚我的问题是什么。
void draw(HDC dhdc){
static unsigned char render_on_device_image_once, odd;
static GLuint texture_id;
size_t sz;
odd = (odd + 1) % 2;
if(!render_on_device_image_once){
// DO ONCE
render_on_device_image_once = 1;
GLubyte pixels[] =
{
0, 0, 0, 255, 255, 255,
255, 255, 255, 0, 0, 0,
};
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(odd)
glClearColor(0.0, 0.0, 0.5, 1.0);
else
glClearColor(0.5, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0, 0, -5);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_id);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glDisable(GL_TEXTURE_2D);
SwapBuffers(dhdc);}
我从this answer获取(并稍加修改)的上述代码使窗口区域在红色和蓝色之间变化,但不渲染四边形。有没有人有类似的问题或者能发现我的错误?
感谢。
编辑:
要添加更多信息,我将HDC的像素格式设置为:
static PIXELFORMATDESCRIPTOR window_pixel_format_desc =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
PFD_TYPE_RGBA, //The kind of framebuffer. RGBA or palette.
8, //Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
32, //Number of bits for the depthbuffer
0, //Number of bits for the stencilbuffer
0, //Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0,
0, 0, 0
};
答案 0 :(得分:2)
两件事。
首先,你永远不会打电话给glViewport
。您需要这样做以设置渲染表面的大小。视口应设置为使用整个窗口,因此您需要使用Win32函数来查询窗口的客户端大小。
其次是:
glTranslatef(0, 0, -5);
那是为什么?这没有任何意义,它会导致三角形的Z分量变为-5。在OpenGL的默认状态下,这超出了[-1,1] Z范围。
答案 1 :(得分:1)
首先,如果你的目标是将像素从OpenGL变成DC"那么通过Window DC做这件事是非常有问题的。对于一个你完全依赖于窗口像素管理。像素所有权,窗口可见性,窗口剪裁等都会对渲染结果产生负面影响。
另一个需要考虑的重要事项是,您只能将一次设置为一个窗口的pixelformat!对于屏幕外渲染,您有2个选项(或3个,具体取决于主机系统是否支持EGL以及EGL环境是否为您提供屏幕外渲染):
创建一个隐藏/不可见的辅助窗口,为OpenGL提供DC并渲染为帧缓冲对象。到目前为止,这是当前数据(2016年)的优选解决方案
创建一个PBuffer来为DC提供OpenGL并呈现给DC
创建一个屏幕外EGL上下文。屏幕外EGL可以支持直接的屏幕外表面,因此不需要帧缓冲对象。或者没有主表面的屏幕外上下文因此严格要求帧缓冲对象。
在上述选项中仅,PBuffer方法为您提供了一种以DC方式 BitBlt 的可靠方式。然而,PBuffers与隐形窗口一样容易/难以创建,而帧缓冲对象可以为您提供更多控制。与PBuffers不同的是,禁止帧缓冲对象目标(纹理或渲染缓冲区)的内容突然“消失”#34; (PBuffers可能随时变为无效)。
将图像从OpenGL中提取出来的最可靠方法""可以与DC操作一起使用的是创建DIBSECTION( CreateDIBSection )并使用 glReadPixels 将图像数据读入其中。