加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 在OpenGL / GLFW 3.2中切换窗口和全屏

发布时间:2020-12-16 10:08:19 所属栏目:百科 来源:网络整理
导读:我正在学习 Linux上的OpenGL,但我不能让模式切换工作(窗口全屏和后退). 窗口似乎进入全屏但看起来不正确.要切换模式,正在创建一个新窗口,旧窗口将被销毁. void OpenGLWindow::FullScreen(bool fullScreen,int width,int height){ GLFWwindow *oldHandle = m_
我正在学习 Linux上的OpenGL,但我不能让模式切换工作(窗口全屏和后退).

窗口似乎进入全屏但看起来不正确.要切换模式,正在创建一个新窗口,旧窗口将被销毁.

void OpenGLWindow::FullScreen(bool fullScreen,int width,int height)
{
    GLFWwindow *oldHandle = m_window;

    m_fullscreen = fullScreen;
    m_width = width;
    m_height = height;

    m_window = glfwCreateWindow(width,height,m_caption.c_str(),fullScreen ? m_monitor : NULL,m_window);

    if (m_window == NULL)
    {
        glfwTerminate();
        throw std::runtime_error("Failed to recreate window.");
    }

    glfwDestroyWindow(oldHandle);

    m_camera->Invalidate();

    // Use entire window for rendering.
    glViewport(0,width,height);

    glfwMakeContextCurrent(m_window);
    glfwSwapInterval(1);

    if (m_keyboardHandler) SetKeyboardHandler(m_keyboardHandler);
}

初始窗口

enter image description here

全屏(不正确)

enter image description here

回到窗口

enter image description here

更新问题

我已更新代码以使用您的代码并获得相同的问题.在你的建议我现在更新相机,但再次无济于事:(

void OpenGLCamera::Invalidate()
{
    RecalculateProjection(m_perspProjInfo->Width(),m_perspProjInfo->Height());
    m_recalculateViewMatrix = true;
    m_recalculatePerspectiveMatrix = true;
    m_recalculateProjectionMatrix = true;
}

void OpenGLCamera::RecalculateProjection(int width,int height)
{
    float aspectRatio = float(width) / height;
    float frustumYScale = cotangent(degreesToRadians(
        m_perspProjInfo->FieldOfView() / 2));

    float frustumXScale = frustumYScale;

    if (width > height) 
    {
        // Shrink the x scale in eye-coordinate space,so that when geometry is
        // projected to ndc-space,it is widened out to become square.
        m_projectionMatrix[0][0] = frustumXScale / aspectRatio;
        m_projectionMatrix[1][1] = frustumYScale;
    }
    else {
        // Shrink the y scale in eye-coordinate space,it is widened out to become square.
        m_projectionMatrix[0][0] = frustumXScale;
        m_projectionMatrix[1][1] = frustumYScale * aspectRatio;
    }
}

Rabbid:当我调整大小时:

enter image description here

Rabbid:当我全屏播出时:

enter image description here

解决方法

在下文中,我将描述一个小而方便的类,它处理调整GLFW窗口的大小并处理开关全屏窗口的开关.
所有使用过的GLFW功能都在 GLFW documentation中有详细记载.

#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <array>
#include <stdexcept>

class OpenGLWindow
{
private:

    std::array< int,2 > _wndPos         {0,0};
    std::array< int,2 > _wndSize        {0,2 > _vpSize         {0,0};
    bool                 _updateViewport = true;
    GLFWwindow *         _wnd            = nullptr;
    GLFWmonitor *        _monitor        = nullptr;

    void Resize( int cx,int cy );

public:

    void Init( int width,int height );
    static void CallbackResize(GLFWwindow* window,int cx,int cy);
    void MainLoop ( void );
    bool IsFullscreen( void );
    void SetFullScreen( bool fullscreen );
};

在创建窗口时,则将用户函数指针(glfwSetWindowUserPointer)设置为窗口管理类.调整大小的回调由glfwSetWindowSizeCallback设置.创建窗口后,可以通过glfwGetWindowPos和glfwGetWindowSize获取当前大小和位置.

void OpenGLWindow::Init( int width,int height )
{
    _wnd = glfwCreateWindow( width,"OGL window",nullptr,nullptr );
    if ( _wnd == nullptr )
    {
        glfwTerminate();
        throw std::runtime_error( "error initializing window" ); 
    }

    glfwMakeContextCurrent( _wnd );

    glfwSetWindowUserPointer( _wnd,this );
    glfwSetWindowSizeCallback( _wnd,OpenGLWindow::CallbackResize );

    _monitor =  glfwGetPrimaryMonitor();
    glfwGetWindowSize( _wnd,&_wndSize[0],&_wndSize[1] );
    glfwGetWindowPos( _wnd,&_wndPos[0],&_wndPos[1] );
    _updateViewport = true;
}

当调整大小通知发生时,可以通过glfwGetWindowUserPointer获取指向窗口管理类的指针:

static void OpenGLWindow::CallbackResize(GLFWwindow* window,int cy)
{
    void *ptr = glfwGetWindowUserPointer( window );
    if ( OpenGLWindow *wndPtr = static_cast<OpenGLWindow*>( ptr ) )
        wndPtr->Resize( cx,cy );
}

通知窗口大小的任何更改并存储新的窗口大小(glfwGetWindowSize):

void OpenGLWindow::Resize( int cx,int cy )
{
    _updateViewport = true;
}

当窗口大小发生变化时,视口必须适合窗口大小(glViewport).这可以在应用程序的主循环中完成:

void OpenGLWindow::MainLoop ( void )
{
    while (!glfwWindowShouldClose(_wnd))
    {
        if ( _updateViewport )
        {
            glfwGetFramebufferSize( _wnd,&_vpSize[0],&_vpSize[1] );
            glViewport( 0,_vpSize[0],_vpSize[1] );
            _updateViewport = false;
        }

        // ..... render the scene

        glfwSwapBuffers(_wnd);
        glfwPollEvents();
    }
}

如果当前窗口处于全屏模式,可以通过询问窗口用于全屏模式的监视器(glfwGetWindowMonitor)来实现:

bool OpenGLWindow::IsFullscreen( void )
{
    return glfwGetWindowMonitor( _wnd ) != nullptr;
}

要打开和关闭全屏模式,必须使用全屏模式的监视器或使用nullptr调用glfwSetWindowMonitor:

void SetFullScreen( bool fullscreen )
{
    if ( IsFullscreen() == fullscreen )
    return;

    if ( fullscreen )
    {
        // backup windwo position and window size
        glfwGetWindowPos( _wnd,&_wndPos[1] );
        glfwGetWindowSize( _wnd,&_wndSize[1] );

        // get reolution of monitor
        const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());

        // swithc to full screen
        glfwSetWindowMonitor( _wnd,_monitor,mode->width,mode->height,0 );
    }
    else
    {
        // restore last window size and position
        glfwSetWindowMonitor( _wnd,_wndPos[0],_wndPos[1],_wndSize[0],_wndSize[1],0 );
    }

    _updateViewport = true;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读