不同的opengl上下文是不是有不同的opengl扩展?

Posted

技术标签:

【中文标题】不同的opengl上下文是不是有不同的opengl扩展?【英文标题】:Does different opengl context has different opengl extension?不同的opengl上下文是否有不同的opengl扩展? 【发布时间】:2016-09-17 16:55:49 【问题描述】:

我正在做一个使用opengl离屏渲染的项目。但是在我创建opengl上下文后,我发现一些opengl扩展无法使用。例如:

#include <windows.h>
#include <GL/glew.h> 
#include <iostream>
#include <gl/gl.h>
#include <gl/glu.h>
#include <string>
#include <time.h>

#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

void mGLRender()

    glClearColor(0.9f, 0.9f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(30.0, 1.0, 1.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0);
    glBegin(GL_TRIANGLES);
    glColor3d(1, 0, 0);
    glVertex3d(0, 1, 0);
    glColor3d(0, 1, 0);
    glVertex3d(-1, -1, 0);
    glColor3d(0, 0, 1);
    glVertex3d(1, -1, 0);
    glEnd();
    glFlush(); // remember to flush GL output!


void mGLRender1()

    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(30.0, 1.0, 1.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0);
    glBegin(GL_TRIANGLES);
    glColor3d(1, 0, 0);
    glVertex3d(0, 1, 0);
    glColor3d(0, 1, 0);
    glVertex3d(-1, -1, 0);
    glColor3d(0, 0, 1);
    glVertex3d(1, -1, 0);
    glEnd();
    glFlush(); // remember to flush GL output!



int main(int argc, char* argv[])

    clock_t  clockBegin, clockEnd;
    const int WIDTH = 400;
    const int HEIGHT = 400;

    // Create a memory DC compatible with the screen
    HDC hdc = CreateCompatibleDC(0);
    if (hdc == 0) cout << "Could not create memory device context";

    // Create a bitmap compatible with the DC
    // must use CreateDIBSection(), and this means all pixel ops must be synchronised
    // using calls to GdiFlush() (see CreateDIBSection() docs)
    BITMAPINFO bmi = 
         sizeof(BITMAPINFOHEADER), WIDTH, HEIGHT, 1, 32, BI_RGB, 0, 0, 0, 0, 0 ,
         0 
    ;
    unsigned char *pbits; // pointer to bitmap bits
    HBITMAP hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void **)&pbits,
    0, 0);
    if (hbm == 0) cout << "Could not create bitmap";

    //HDC hdcScreen = GetDC(0);
    //HBITMAP hbm = CreateCompatibleBitmap(hdcScreen,WIDTH,HEIGHT);

    // Select the bitmap into the DC
    HGDIOBJ r = SelectObject(hdc, hbm);
    if (r == 0) cout << "Could not select bitmap into DC";

    // Choose the pixel format
    PIXELFORMATDESCRIPTOR pfd = 
        sizeof(PIXELFORMATDESCRIPTOR), // struct size
        1, // Version number
        PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL, // use OpenGL drawing to BM
        PFD_TYPE_RGBA, // RGBA pixel values
        32, // color bits
        0, 0, 0, // RGB bits shift sizes...
        0, 0, 0, // Don't care about them
        0, 0, // No alpha buffer info
        0, 0, 0, 0, 0, // No accumulation buffer
        32, // depth buffer bits
        0, // No stencil buffer
        0, // No auxiliary buffers
        PFD_MAIN_PLANE, // Layer type
        0, // Reserved (must be 0)
        0, // No layer mask
        0, // No visible mask
        0, // No damage mask
    ;
    int pfid = ChoosePixelFormat(hdc, &pfd);
    if (pfid == 0) cout << "Pixel format selection failed";

    // Set the pixel format
    // - must be done *after* the bitmap is selected into DC
    BOOL b = SetPixelFormat(hdc, pfid, &pfd);
    if (!b) cout << "Pixel format set failed";

   // Create the OpenGL resource context (RC) and make it current to the thread
    HGLRC hglrc = wglCreateContext(hdc);
    if (hglrc == 0) cout << "OpenGL resource context creation failed";
    wglMakeCurrent(hdc, hglrc);

    GLenum err = glewInit();
    if (GLEW_OK != err)
    
        /* Problem: glewInit failed, something is seriously wrong. */
        std::cout << "glew init error" << std::endl;
        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
    
    std::cout << (glewGetExtension("GL_ARB_fragment_shader") == GL_TRUE);
    std::cout << (glewGetExtension("GL_ARB_shader_objects") == GL_TRUE);
    std::cout << (glewGetExtension("GL_ARB_shading_language_100") == GL_TRUE);
    // Draw using GL - remember to sync with GdiFlush()
    clockBegin = clock();
    GdiFlush();
    mGLRender();
    //SaveBmp(hbm,"output.bmp");
    clockEnd = clock();
    printf("%d\n", clockEnd - clockBegin);

    clockBegin = clock();
    GdiFlush();
    mGLRender1();
    //SaveBmp(hbm,"output1.bmp");
    clockEnd = clock();
    printf("%d\n", clockEnd - clockBegin);


    //opencv show img
    Mat img(HEIGHT, WIDTH, CV_8UC4, (void *)pbits);
    imshow("img", img);
    waitKey();
    destroyWindow("img");

    // Clean up
    wglDeleteContext(hglrc); // Delete RC
    SelectObject(hdc, r); // Remove bitmap from DC
    DeleteObject(hbm); // Delete bitmap
    DeleteDC(hdc); // Delete DC

    system("pause");

    return 0;

以上代码在 vs2015 中运行良好。但是行:

std::cout << (glewGetExtension("GL_ARB_fragment_shader") == GL_TRUE);

原来 GL_ARB_fragment_shader 扩展是不可用的。但我确信我的 gpu 支持这个扩展。因为在一个简单的 freeglut 应用程序中,glewGetExtension("GL_ARB_fragment_shader") 返回 True。代码在这里:

#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
// Window attributes
static const unsigned int WIN_POS_X = 30;
static const unsigned int WIN_POS_Y = WIN_POS_X;
static const unsigned int WIN_WIDTH = 512;
static const unsigned int WIN_HEIGHT = WIN_WIDTH;

void glInit(int, char **);

int main(int argc, char * argv[])

    // Initialize OpenGL
    glInit(argc, argv);

    // A valid OpenGL context has been created.
    // You can call OpenGL functions from here on.
    GLenum err = glewInit();
    if (GLEW_OK != err)
    
        /* Problem: glewInit failed, something is seriously wrong. */
        std::cout << "glew init error" << std::endl;
        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
    
    std::cout << (glewGetExtension("GL_ARB_fragment_shader") == GL_TRUE);
    std::cout << (glewGetExtension("GL_ARB_shader_objects") == GL_TRUE);
    std::cout << (glewGetExtension("GL_ARB_shading_language_100") == GL_TRUE);
    glutMainLoop();

    return 0;


void Display()


 // end Display()

void glInit(int argc, char ** argv)

    // Initialize GLUT
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE);
    glutInitWindowPosition(WIN_POS_X, WIN_POS_Y);
    glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT);
    glutCreateWindow("Hello OpenGL!");
    glutDisplayFunc(Display);
    return;

以上代码在 vs2015 中运行良好。以及 glewGetExtension("GL_ARB_fragment_shader") 的值 是真的。那么不同的opengl上下文有不同的opengl扩展吗?请帮帮我。

【问题讨论】:

您要求的是最基本的上下文,而 GLEW 可能会要求更新的上下文。 glFlush(); // remember to flush GL output! 你几乎不需要这样做。 【参考方案1】:

是的,不同的 OpenGL 上下文可能支持不同的 OpenGL 版本和/或扩展。在您的特定情况下,您正在创建的屏幕外上下文将使用 GDI 软件光栅化器后备。 你创建上下文的方式永远不会被 GPU 加速!

如果你想创建一个 GPU 加速的 OpenGL 上下文,你要么必须这样做

使用 PBuffer(它为您提供没有窗口的 HDC)

在隐藏窗口上创建 OpenGL 上下文并渲染到 FBO(目前最常用的方法)

使用一种新的独立于操作系统的纯屏幕外上下文创建方法(例如,请参阅 https://devblogs.nvidia.com/parallelforall/egl-eye-opengl-visualization-without-x-server/ 了解如何在 NVidia 上执行此操作 - 也适用于 Windows)

然而,即使 OpenGL 上下文是 GPU 加速的,即使它们碰巧是在同一台机器和 GPU 上创建的,它们的版本和扩展支持也可能不同。

【讨论】:

以上是关于不同的opengl上下文是不是有不同的opengl扩展?的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenGL 和来自不同线程的输入

在 OS X 上的 OpenGL 上下文之间共享数据(不同的版本/配置文件)

是否可以在 opengl 中从 2 个不同的线程渲染 2 个不同的帧缓冲区对象?

在 Linux 上的上下文之间共享 OpenGL 对象

OpenGL OpenGL管线 与 可编程管线流程

使用类型类使OpenGL的int常量类型安全