使用Texture2D将OpenGL绘图到现有的HDC

时间:2016-06-23 12:46:30

标签: c opengl

我正在尝试使用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
};

2 个答案:

答案 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 将图像数据读入其中。