如何缩放 glDrawPixels?

Posted

技术标签:

【中文标题】如何缩放 glDrawPixels?【英文标题】:How to scale glDrawPixels? 【发布时间】:2012-01-08 01:00:21 【问题描述】:

我需要缩放 glDrawPixels 图像的结果。

我正在 Qt QGLWidget 中使用 glDrawPixels 绘制一个 640x480 像素的图像缓冲区。

我尝试在 PaintGL 中执行以下操作:

glScalef(windowWidth/640, windowHeight/480, 0);
glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);

但它不起作用。

我将 OpenGL 视口和 glOrtho 设置为小部件的大小:

void WdtRGB::paintGL() 

         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

         // Setup the OpenGL viewpoint
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         glOrtho(0, windowWidth, windowHeight, 0, -1.0, 1.0);

    glDepthMask(0);
        //glRasterPos2i(0, 0);
        glScalef(windowWidth/640, windowHeight/480, 0);
        glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);
    

    //where windowWidth and windowHeight corresponds to the widget size.
    /the init functions are:

    void WdtRGB::initializeGL() 

        glClearColor ( 0.8, 0.8, 0.8, 0.0); // Background to a grey tone

        /* initialize viewing values  */
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        glOrtho(0, windowWidth, windowHeight, 0, -1.0, 1.0);

        glEnable (GL_DEPTH_TEST);

    

    void WdtRGB::resizeGL(int w, int h) 
        float aspect=(float)w/(float)h;

        windowWidth = w;
        windowHeight = h;
        glViewport (0, 0, (GLsizei) w, (GLsizei) h);
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();

        if( w <= h )
                glOrtho ( -5.0, 5.0, -5.0/aspect, 5.0/aspect, -5.0, 5.0);
        else
                glOrtho (-5.0*aspect, 5.0*aspect, -5.0, 5.0, -5.0, 5.0);

        //printf("\nresize");
        emit changeSize ( );
    

【问题讨论】:

【参考方案1】:

听起来您实际上需要做的而不是调用 glDrawPixels () 是将图像数据加载到纹理中并绘制窗口大小的带纹理的四边形。所以是这样的:

glGenTextures (1, &texID);
glBindTextures (GL_TEXTURE_RECTANGLE_EXT, texID);
glTexImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, 640, 480, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, frame);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (0, 0);
glTexCoord2f (640, 0);
glVertex2f (windowWidth, 0);
glTexCoord2f (640, 480);
glVertex2f (windowWidth, windowHeight);
glTexCoord2f (0, 480);
glVertex2f (0, windowHeight);
glEnd();

如果工作量太大,glPixelZoom (windowWidth / 640, windowHeight / 480) 也可以解决问题。

【讨论】:

我发现我需要在开始/结束处使用 glEnable/glDisable (GL_TEXTURE_RECTANGLE) 对来将纹理应用到四边形,并且我需要使用不带 _EXT 的 GL_TEXTURE_RECTANGLE,但否则这样可以对我来说也很完美,谢谢! :D【参考方案2】:

仅供参考:不要在glDrawPixels 之前执行glScalef(windowWidth/640, windowHeight/480, 0);,您应该进行像素缩放:

glRasterPos2i(0,0);
GLint iViewport[4];
glGetIntegerv(GL_VIEWPORT, iViewport);
glPixelZoom(iViewport[2]/640, iViewport[3]/480);
glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);

【讨论】:

【参考方案3】:

我需要缩放 glDrawPixels 图像的结果。

glDrawPixels 直接进入帧缓冲区。因此,每个输入像素都以 1:1 的比例映射到输出。有一个函数(啊,我为什么告诉你这个)glPixelZoom,它可以让你缩放 glDrawPixels。

但我劝你,不要使用 glDrawPixels!

改用纹理四边形。 glDrawPixels 是一个已弃用的函数,现代 OpenGL-3 不再支持。即使它没有被弃用,它仍然是一个非常缓慢的功能。带纹理的四边形在各个方面都更好。

【讨论】:

好的,我要检查一下,非常感谢您的帮助。我会改用纹理 @datenwolf 如何直接访问帧缓冲区?我想实时绘制我选择的 2d 缓冲区,使用 EGL 作为硬件加速的一个很好的代理。纹理适合这个吗? @rr-: OpenGL 不会直接给你(比如给你一个指向帧缓冲内存的指针)来写入。同样出于效率原因,应避免直接写入。您想异步写入帧缓冲区。并且使用 OpenGL 的任何变体,这是通过将图像加载到纹理中并为带纹理的四边形发出绘图命令来完成的。该命令排队并异步执行,因此您的 CPU 进程不会因必须等待的任何图形事件而停止。 谢谢,有道理。

以上是关于如何缩放 glDrawPixels?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使用 glDrawPixels 渲染单通道灰度图像?

glDrawPixels 访问冲突读取位置

glDrawPixels() 与 0.375 翻译

malloc() 和 glDrawPixels() 的访问冲突?

数组中的 gldrawpixel rgb 值

使用 glDrawPixels() 在 OpenGL 上绘制像素