下面,我将描述一个小但方便的类,它处理调整 GLFW 窗口的大小并处理全屏窗口的打开和关闭。
所有使用的 GLFW 函数都详细记录在GLFW 文档.
#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, 0};
std::array< int, 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
and glfwGetWindowSize
.
void OpenGLWindow::Init( int width, int height )
{
_wnd = glfwCreateWindow( width, height, "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 cx, 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, 0, _vpSize[0], _vpSize[1] );
_updateViewport = false;
}
// ..... render the scene
glfwSwapBuffers(_wnd);
glfwPollEvents();
}
}
如果当前窗口处于全屏模式,可以通过询问窗口用于全屏模式的监视器来实现(glfwGetWindowMonitor
):
bool OpenGLWindow::IsFullscreen( void )
{
return glfwGetWindowMonitor( _wnd ) != nullptr;
}
要打开和关闭全屏模式,glfwSetWindowMonitor
必须使用全屏模式的监视器或使用nullptr
:
void OpenGLWindow::SetFullScreen( bool fullscreen )
{
if ( IsFullscreen() == fullscreen )
return;
if ( fullscreen )
{
// backup window position and window size
glfwGetWindowPos( _wnd, &_wndPos[0], &_wndPos[1] );
glfwGetWindowSize( _wnd, &_wndSize[0], &_wndSize[1] );
// get resolution of monitor
const GLFWvidmode * mode = glfwGetVideoMode(_monitor);
// switch to full screen
glfwSetWindowMonitor( _wnd, _monitor, 0, 0, mode->width, mode->height, 0 );
}
else
{
// restore last window size and position
glfwSetWindowMonitor( _wnd, nullptr, _wndPos[0], _wndPos[1], _wndSize[0], _wndSize[1], 0 );
}
_updateViewport = true;
}