【问题标题】:OpenGL + Visual Studio 2017 : rendering window not displayed (was OK with Visual 2010)OpenGL + Visual Studio 2017:不显示渲染窗口(Visual 2010 可以)
【发布时间】:2019-11-06 13:16:05
【问题描述】:

更新:

问题解决了!该解决方案的灵感来自 cmets 中的建议:

我刚刚更新了图形驱动程序,现在我的所有代码都可以正常工作。 有关信息,提到的驱动程序是“Inter(R) UHD Graphics 620”,我已更新到版本 25.20.10.6472 (10/12/2018)。

非常抱歉给您带来不便,并感谢您的支持。

使用 ScreenToGif(感谢 Strive Sun)如下所示:主 (OpenGL) 窗口是某种太空船的外部视图(带有彩色助推器),右下角的(GDI)窗口是 AI Pilote 的视图,它正在学习吃绿色口香糖并避免吃红色口香糖)。

如果您,StackOverflow 先生,认为这种胡言乱语不合适,请删除它...

下面是原问题:

我在 windows 下有一小段 OpenGL 代码示例,可以在 windows 7 + visual studio 2010 中正常工作。 但是在我的装有 windows 10 + visual studio 2017 的新 PC 上,没有显示 OpenGL 渲染窗口。 编译没问题,执行过程中没有返回错误。

因此,为了在此处发布它而不用大量内容打扰您,我编写了我的代码的简短摘录。 它仅使用标准 win API (gl.h/glu.h) 提供的基本原生 gdi+opengl 函数,而不使用任何附加库(如 glew/glut/freeglut/...)。

使用 Windows7+VS2010 我有 3 个窗口:一个 GDI 渲染、一个 OpenGL 渲染和一个控制台。

  • 第一个:一些交叉的蓝线(使用“LineTo”)。
  • 第二个:一个紫色三角形(使用“glVertex3d”)。
  • 在控制台上显示一条消息,告诉我所有函数都已正常返回。

在 Windows10+VS2017 中,OpenGL 窗口不可见。 当我使用 alt-tab 键玩游戏时,我什至看不到幽灵。

我认为 API 发生了一些变化,但我不知道是什么...

这是我的代码:

#include <windows.h>
#include <cstdio>
#include <GL/GLU.h>

static LRESULT CALLBACK win32callback ( HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam ) 
    {
    return DefWindowProcA( hWnd,message,wParam,lParam ) ;
    }

HWND create_window ( BOOL & ok , int x )
    {
    WNDCLASSEXA wcx ;
    memset( &wcx,0,sizeof( wcx )) ;
    wcx.cbSize        = sizeof( wcx ) ;
    wcx.lpfnWndProc   = win32callback ;
    wcx.lpszClassName = "spam" ;
    RegisterClassExA( &wcx ) ;

    HWND hwnd = CreateWindowExA( 0,"spam",NULL,WS_POPUP,x+10,10,500,500,NULL,NULL,NULL,NULL ) ;
    ok = ok && SetWindowPos( hwnd,HWND_TOPMOST,x+10,10,500,500,SWP_NOOWNERZORDER|SWP_SHOWWINDOW ) ;
    ok = ok && ShowWindow( hwnd,SW_SHOWNORMAL ) ;

    return hwnd ;
    }

void play_opengl ( HWND hwnd , BOOL & ok )
    {
    HDC dc = GetWindowDC( hwnd ) ;

    PIXELFORMATDESCRIPTOR pfd ;
    memset( &pfd,0,sizeof( PIXELFORMATDESCRIPTOR )) ;
    pfd.nSize      = sizeof( PIXELFORMATDESCRIPTOR ) ;
    pfd.nVersion   = 1 ;
    pfd.dwFlags    = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER ;
    pfd.iPixelType = PFD_TYPE_RGBA ;
    pfd.cColorBits = 24 ;
    pfd.cDepthBits = 32 ;
    pfd.iLayerType = PFD_MAIN_PLANE ;
    int PixFormat  = ChoosePixelFormat( dc,&pfd ) ;

    ok = ok && SetPixelFormat( dc,PixFormat,&pfd ) ;

    HGLRC glrc = wglCreateContext( dc ) ;
    ok = ok && wglMakeCurrent( dc,glrc ) ;

    glViewport( 0,0,500,500 ) ;
    glEnable( GL_COLOR_MATERIAL ) ;
    glMatrixMode( GL_PROJECTION ) ;
    gluPerspective( 70,1,0.1,1000 ) ;
    glMatrixMode( GL_MODELVIEW ) ;
    glLoadIdentity() ;
    glColor3b( 100,50,120 ) ;
    glTranslated( 0,0,-20 ) ;

    glBegin( GL_TRIANGLES ) ;
    glVertex3d( 0,0,0 ) ;
    glVertex3d( 5,5,0 ) ;
    glVertex3d( 0,5,0 ) ;
    glEnd() ;

    ok = ok && SwapBuffers( dc ) ;
    }

void play_gdi ( HWND hwnd , BOOL & ok )
    {
    HDC     windc  = GetWindowDC( hwnd ) ;
    HDC     dc     = CreateCompatibleDC( windc ) ;
    HBITMAP bitmap = CreateCompatibleBitmap( windc,500,500 ) ;
    HPEN    pen    = CreatePen( PS_SOLID,1,0xffaa55 ) ;
    ok = ok && (SelectObject( dc,bitmap ) != NULL) ;
    ok = ok && (SelectObject( dc,pen ) != NULL) ;
    for ( int i = 0 ; i < 100 ; i++ )
        ok = ok && LineTo( dc,(i&1?i:100-i)*4,(i&1)*400 ) ;
    BitBlt( windc,0,0,500,500,dc,0,0,SRCCOPY ) ;
    }

void main ()
    {
    BOOL ok = TRUE ;
    HWND hwnd1 = create_window( ok,0 ) ;
    HWND hwnd2 = create_window( ok,600 ) ;
    play_gdi( hwnd1,ok ) ;
    play_opengl( hwnd2,ok ) ;
    // sorry I don't clean up anything...
    if (ok) printf("\n all correct!\n") ;
    printf("\n\n press ENTER") ; 
    getchar() ;
    }

【问题讨论】:

  • 如何添加一些错误处理以查看您进行的任何调用是否失败?如果他们这样做了,请告诉我们如何/有什么错误。现在,您的代码只是忽略了所有(潜在的)错误,并且无论如何都会伪造。还可以尝试在调试器中逐步运行它,并验证(返回和其他)值和控制流是否符合您的期望 - 如果不符合您的期望,请告诉我们它是如何/在哪里偏离的。
  • 1.您缺少消息循环,2. void main() 错误,3. ShowWindow(hwnd,TRUE) 也错误,4. DefWindowProc 使用 RegisterClassExA 时错误,4. 这是不是最小。所有这些 OpenGL 调用都是多余的。
  • 谢谢你们俩:我更新了我的代码以显示 GDI 和 OpenGL(只是为了检查窗口创建),测试所有函数返回(我在调试时已经这样做了),更正了一些参数并简化我的 OpenGL 调用。不幸的是它没有改变任何东西......
  • 您仍然缺少message loop,这是必需的。来自文档:If the thread creates one or more windows, a message loop must be provided。另请阅读 this 关于 void main() 的使用。
  • 感谢@Axalo,我用正确的main签名编辑了我的代码并添加了一个message loop,但结果总是一样的。 .. 我认为这是一个更基本/更烦人的问题,因为我发现它在具有相同 Win10+VS2017 的另一台 PC 上运行良好!也许是一些图形驱动程序问题......这完全改变了这篇文章的意义。也许我应该重写问题或将其发布为新问题...

标签: c++ winapi opengl visual-studio-2017


【解决方案1】:

你说的鬼窗口是由下面的代码创建的。

for ( int z = -n ; z <= n ; z++ )
        for ( int y = -n ; y <= n ; y++ )
            for ( int x = -n ; x <= n ; x++ )
                {
                printf(" %d,%d,%d%s",x,y,z,x?"":"\n") ;
                SwapBuffers( dc ) ;
                glTranslated( x,y,z ) ;
                gluSphere( quadric,4,5,5 ) ;
                glTranslated( -x,-y,-z ) ;
                }

我不知道你想用这段代码渲染哪个窗口,但就是这样。您的 for 循环一直在围绕球体矩阵循环。

出于测试目的,我正在尝试用我的代码替换您的一些代码。

#include <windows.h>
#include <cstdio>
#include <math.h>
#include <GL/GLU.h>

#pragma comment (lib,"Glu32.lib")
#pragma comment (lib,"Opengl32.lib")

void draw();

int width, height;      // the desired width and height of the CLIENT AREA
HDC dc;

static LRESULT CALLBACK win32callback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc(hWnd, message, wParam, lParam);
}
void main()
{
    WNDCLASSEXA wcx;
    memset(&wcx, 0, sizeof(wcx));
    wcx.cbSize = sizeof(wcx);
    wcx.lpfnWndProc = win32callback;
    wcx.lpszClassName = "spam";
    RegisterClassExA(&wcx);

    HWND hwnd = CreateWindowExA(0, "spam", NULL, WS_POPUP, 10, 10, 500, 500, NULL, NULL, NULL, NULL);
    SetWindowPos(hwnd, HWND_TOPMOST, 10, 10, 800, 500, SWP_NOOWNERZORDER | SWP_SHOWWINDOW);
    ShowWindow(hwnd, TRUE);
    SetFocus(hwnd);

    dc = GetWindowDC(hwnd);

    RECT rect;
    SetRect(&rect, 50,  // left
        50,  // top
        850, // right
        650); // bottom

// Save width and height off.
    width = rect.right - rect.left;
    height = rect.bottom - rect.top;

    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 24;
    int PixFormat = ChoosePixelFormat(dc, &pfd);

    PIXELFORMATDESCRIPTOR bestMatch_pfd;
    DescribePixelFormat(dc, PixFormat, sizeof(pfd), &bestMatch_pfd);
    SetPixelFormat(dc, PixFormat, &pfd);

    HGLRC glrc = wglCreateContext(dc); 
    wglMakeCurrent(dc, glrc); 


    while (1)
    {
        draw();
    }    
    DestroyWindow(hwnd);
    wglMakeCurrent(0, 0);
    wglDeleteContext(glrc);
}

void draw()
{
    // 1. set up the viewport
    glViewport(0, 0, g.width, g.height); // set viewport

    // 2. projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (float)g.width / (float)g.height, 1, 1000);

    // 3. viewing transformation
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    gluLookAt(0, 0, 10,
        0, 0, 0,
        0, 1, 0);

    // 4. modelling transformation and drawing
    glClearColor(0.5, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    static float i = 0.01f;


    i += 0.001f;     // increase i by 0.001 from its
    // it had on the LAST FUNCTION CALL to the draw() function

    float c = cos(i);
    float s = sin(i);

    glBegin(GL_TRIANGLES);
    glColor3f(c, 0, 0);      // red
    glVertex3f(1 + c, 0 + s, 0);

    glColor3f(c, s, 0);      // yellow
    glVertex3f(0 + c, 1 + s, 0);

    glColor3f(s, 0.1f, s);   // magenta
    glVertex3f(-1 + c, 0 + s, 0);
    glEnd();

    //7.  SWAP BUFFERS.
    SwapBuffers(dc);

}

可以看到效果很好,我的环境配置:VS2017 Window 10

更新:

尝试链接“Glu32.lib”和“Opengl32.lib”

更新:

尝试以下两种方法:

  1. 显卡不支持当前OpenGL版本,下载EVEREST终极版,安装运行后依次点击显示设备>OpenGL查看是否支持相关信息,如果不支持,只能更换显卡或者更换支持的OpenGL版本解决问题。

  2. 显卡驱动程序不受支持。更新显卡驱动就够了。

【讨论】:

  • 非常感谢您的努力!我试过你的代码(只是抑制了“g.”)。但结果和我的一样:没有出现任何窗口……我一定是我的新 PC 的配置中的一些东西。我试过“OpenGL Extensions Viewer 5.1”:它告诉我我有 OpenGL 4.5。这个非常简单的演示应该足够了:-(
  • @Captain'Flam 我在发布代码之前做了一些删除。我没有正确定义变量。我已经更正了。
  • @Captain'Flam 您似乎没有链接到“Glu32.lib”和“Opengl32.lib”,请查看我的更新答案。
  • 再次感谢奋斗太阳!关于库:我使用旧学校的方式来链接它们(来自项目选项)。顺便说一句,如果这是障碍,我在编译过程中遇到了一些链接错误......但是哇!如何从屏幕截图中获取 GIF?
  • 关于主要问题(既不是链接也不是三角形也不是球体)我认为它更严重:它在具有相同配置的另一台 PC 上运行良好。也许一些图形驱动程序问题。这真的很烦人,因为我是开发人员,而不是 IT 人员......
猜你喜欢
  • 2019-06-06
  • 2018-04-15
  • 1970-01-01
  • 2018-02-19
  • 1970-01-01
  • 1970-01-01
  • 2018-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多