44. Scene and Window¶
Learn how to customize Siv3D's scene and window.
44.1 Overview of Scene and Window¶
- In Siv3D, when you
.draw()
shapes, textures, text, etc., they are drawn to a virtual screen called a "scene" - Then,
System::Update()
transfers the scene image to the window, allowing users to see the drawing results in the window

- These processes are performed automatically, so until now you've been able to view the results of
.draw()
in the window without being particularly aware of it - This chapter delves deeper into the mechanisms of scenes and windows
44.2 "Three Sizes"¶
- To properly understand screen display in Siv3D programs, it's important to understand the following "three sizes":
- ① Scene size
- ② Virtual window size
- ③ Actual window size (frame buffer size)
① Scene Size¶
- The size of an independent scene that serves as the basis for drawing with
.draw()
and mouse cursor coordinates withCursor::Pos()
- By default, it's 800 × 600 and matches the "② virtual window size"
- When you take a screenshot using Siv3D's features, it's saved at this resolution
- Functions related to getting scene size are as follows:
Code | Return Value | Description |
---|---|---|
Scene::Size() |
Size |
Returns scene size |
Scene::Width() |
int32 |
Returns scene width |
Scene::Height() |
int32 |
Returns scene height |
Scene::Center() |
Point |
Returns scene center coordinates Same as Scene::Size() / 2 |
Scene::CenterF() |
Vec2 |
Returns scene center coordinates Same as Scene::Size() / 2.0 |
Scene::Rect() |
Rect |
Returns scene rectangle Same as Rect{ 0, 0, Scene::Size() } |
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << U"Scene::Size(): " << Scene::Size();
Print << U"Scene::Width(): " << Scene::Width();
Print << U"Scene::Height(): " << Scene::Height();
Print << U"Scene::Center(): " << Scene::Center();
Print << U"Scene::CenterF(): " << Scene::CenterF();
Print << U"Scene::Rect(): " << Scene::Rect();
}
}
② Virtual Window Size¶
- The apparent size of the window's client area (the area where drawing occurs, excluding the title bar and frame) on the user's desktop
- By default, it's 800 × 600
- Can be obtained with
Window::GetState().virtualSize
- Multiplying this virtual window size by the scaling factor set in the OS (150%, 200%, etc.) gives the "③ actual window size"
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
}
}
Note for Linux version
- The current Siv3D Linux version doesn't support OS scaling factors, so ② virtual window size and ③ actual window size are equal
③ Actual Window Size (Frame Buffer Size)¶
- The size of the window's client area measured in actual pixels on the monitor
- By default, it's 800 × 600 multiplied by the OS scaling factor
- Can be obtained with
Window::GetState().frameBufferSize
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
}
}
OS Scaling Factor¶
- The current OS scaling factor for the monitor displaying the window can be obtained with
Window::GetState().scaling
1.0
is 100%,1.25
is 125%,1.5
is 150%,2.0
is 200%
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
Print << U"Scaling: " << Window::GetState().scaling;
}
}
Relationship Between the Three Sizes¶
- Scene drawing results are scaled to fit the actual window size while maintaining aspect ratio and transferred to the window
- This automatically displays content at optimal size for the user's monitor environment
- For example, in high DPI environments with 200% OS scaling, a scene drawn at 800 × 600 is enlarged to 1600 × 1200 for display, preventing problems like "text is too small to play the game"
- The following table summarizes the relationship between the three sizes at various OS scaling factors:
OS Scaling Factor | ① Scene Size | ② Virtual Window Size | ③ Actual Window Size |
---|---|---|---|
100% | 800x600 | 800x600 | 800x600 |
125% | 800x600 | 800x600 | 1000x750 |
150% | 800x600 | 800x600 | 1200x900 |
200% | 800x600 | 800x600 | 1600x1200 |
- On the other hand, in high DPI environments, you may want to draw scenes at correspondingly high resolution for high-definition rendering
- For example, when the OS scaling factor is 200%, you might want to draw at 1600 × 1200 to match the actual window size
- To match scene size to actual window size, use resize mode
ResizeMode::Actual
explained in 44.3
44.3 Scene Resize Mode¶
- The following operations change the actual window size or virtual window size:
- Moving the window to a different monitor
- Calling window resize functions (44.4)
- User resizing a resizable window (44.5) with the mouse
- With these size changes, the scene size also needs updating
- The scene resize mode determines the new scene size when this happens
- There are three resize modes:
Resize Mode | Description |
---|---|
ResizeMode::Virtual |
Use virtual window size as new scene size (default) |
ResizeMode::Actual |
Use actual window size as new scene size |
ResizeMode::Keep |
Don't change scene size |
- The current resize mode can be obtained with
Scene::GetResizeMode()
- Set the resize mode with
Scene::SetResizeMode(ResizeMode)
- When set, the scene size is immediately updated to match the new resize mode
- The following sample changes the resize mode to
ResizeMode::Actual
immediately after program startup - When the OS scaling factor is greater than 100%, the scene size becomes larger than 800 × 600, allowing higher-definition drawing at that size
# include <Siv3D.hpp>
void Main()
{
Scene::SetResizeMode(ResizeMode::Actual);
while (System::Update())
{
ClearPrint();
Print << U"Scene::Size(): " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
// 100 px checkerboard pattern to check scene size
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if (IsEven(x + y))
{
Rect{ (x * 100), (y * 100), 100 }.draw(ColorF{ 0.4 });
}
}
}
}
}
44.4 Window Resizing¶
- You can change the virtual window size with
Window::Resize(width, height)
orWindow::Resize(size)
- With the virtual window size change, the actual window size changes and the scene size is updated according to the resize mode
- When using the default resize mode
ResizeMode::Virtual
, the new virtual window size specified byWindow::Resize()
becomes the new scene size, so it's not too complicated
# include <Siv3D.hpp>
void Main()
{
Window::Resize(1000, 600);
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
// 100 px checkerboard pattern to check scene size
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if (IsEven(x + y))
{
Rect{ (x * 100), (y * 100), 100 }.draw(ColorF{ 0.4 });
}
}
}
}
}
- When resize mode
ResizeMode::Keep
is set, the scene size doesn't change even withWindow::Resize()
- When the aspect ratios of scene size and actual window size differ, letterboxes (margin areas) appear on the left/right or top/bottom of the client area
# include <Siv3D.hpp>
void Main()
{
Scene::SetResizeMode(ResizeMode::Keep);
Window::Resize(1000, 600);
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
// 100 px checkerboard pattern to check scene size
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if (IsEven(x + y))
{
Rect{ (x * 100), (y * 100), 100 }.draw(ColorF{ 0.4 });
}
}
}
}
}
44.5 Manual Resizing¶
- To allow manual window resizing, set
Window::SetStyle(WindowStyle::Sizable)
- When actual window size and virtual window size are changed by user operations, the scene size is also updated according to the resize mode
- When using the default resize mode
ResizeMode::Virtual
, the new virtual window size becomes the new scene size
# include <Siv3D.hpp>
void Main()
{
Window::SetStyle(WindowStyle::Sizable);
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
// 100 px checkerboard pattern to check scene size
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if (IsEven(x + y))
{
Rect{ (x * 100), (y * 100), 100 }.draw(ColorF{ 0.4 });
}
}
}
}
}
- When resize mode
ResizeMode::Keep
is set, the scene size doesn't change even with manual window resizing - When the aspect ratios of scene size and actual window size differ, letterboxes appear on the left/right or top/bottom of the client area
# include <Siv3D.hpp>
void Main()
{
Scene::SetResizeMode(ResizeMode::Keep);
Window::SetStyle(WindowStyle::Sizable);
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
// 100 px checkerboard pattern to check scene size
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if (IsEven(x + y))
{
Rect{ (x * 100), (y * 100), 100 }.draw(ColorF{ 0.4 });
}
}
}
}
}
44.6 Changing Letterbox Color¶
- To change the letterbox color, specify a color with
Scene::SetLetterbox(color)
- Like
Scene::SetBackground(color)
, once you change the letterbox color, it remains the same until changed again
# include <Siv3D.hpp>
void Main()
{
// Change letterbox color
Scene::SetLetterbox(ColorF{ 0.8, 0.9, 1.0 });
Scene::SetResizeMode(ResizeMode::Keep);
Window::SetStyle(WindowStyle::Sizable);
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
// 100 px checkerboard pattern to check scene size
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if (IsEven(x + y))
{
Rect{ (x * 100), (y * 100), 100 }.draw(ColorF{ 0.4 });
}
}
}
}
}
44.7 Changing Only Scene Size¶
- When resize mode is set to
ResizeMode::Keep
, the scene size is not changed by window operations - Instead, use
Scene::Resize(width, height)
orScene::Resize(size)
to change the scene size - When scene and actual window sizes differ, use
Cursor::PosF()
instead ofCursor::Pos()
to get mouse cursor coordinates as the more informativeVec2
type
# include <Siv3D.hpp>
void Main()
{
Scene::SetResizeMode(ResizeMode::Keep);
// Resize scene to 1600x1200
Scene::Resize(1600, 1200);
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
// Get mouse cursor coordinates as Vec2 type
Print << Cursor::PosF();
// 100 px checkerboard pattern to check scene size
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if (IsEven(x + y))
{
Rect{ (x * 100), (y * 100), 100 }.draw(ColorF{ 0.4 });
}
}
}
}
}
44.8 Scene Scaling Filter¶
- When transferring a scene to the window, if the scene size and actual window size differ, the scene image is scaled to fit the client area while maintaining aspect ratio
- There are two texture filter options for scaling, which can be changed with
Scene::SetTextureFilter(texture filter)
- By default, bilinear interpolation
TextureFilter::Linear
is used- This is an interpolation method that smoothly filters and scales images
- On the other hand, scaling low-resolution scenes with nearest-neighbor interpolation
TextureFilter::Nearest
filter can maintain the pixel feeling without filtering
Texture Filter | Description |
---|---|
TextureFilter::Linear |
Bilinear interpolation of images (default) |
TextureFilter::Nearest |
Nearest-neighbor interpolation of images |
# include <Siv3D.hpp>
void Main()
{
Scene::SetResizeMode(ResizeMode::Keep);
// Set scene size to 200x150
Scene::Resize(200, 150);
// Set scene transfer scaling method to nearest-neighbor
Scene::SetTextureFilter(TextureFilter::Nearest);
const Texture texture{ U"🐈"_emoji };
while (System::Update())
{
Circle{ 120, 75, 50 }.draw();
texture.draw();
}
}
44.9 Hiding Window Frame¶
- To hide the window frame, set
WindowStyle::Frameless
withWindow::SetStyle()
- Manual window movement, resizing, and closing operations become unavailable
# include <Siv3D.hpp>
void Main()
{
// Hide window frame
Window::SetStyle(WindowStyle::Frameless);
while (System::Update())
{
Circle{ Cursor::Pos(), 100 }.draw();
}
}
44.10 Changing Title¶
- To change the window title, pass a string or value to
Window::SetTitle()
- During debug builds, in addition to the title, information like
(Debug Build)
, frame rate, window size, and scene size is also displayed
# include <Siv3D.hpp>
void Main()
{
// Change window title
Window::SetTitle(U"My Game");
while (System::Update())
{
}
}
Don't change title frequently during execution
- Changing the window title is a time-consuming operation
- Avoid setting different titles with
Window::SetTitle()
every frame - If you pass the same title that's already set to
Window::SetTitle()
, nothing happens so no cost is incurred
44.11 Moving Window (1)¶
Window::Centering()
moves the window to the center of the current monitor's work area
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
if (SimpleGUI::Button(U"Center", Vec2{ 20, 20 }))
{
// Move window to center
Window::Centering();
}
}
}
44.12 Moving Window (2)¶
Window::SetPos(x, y)
orWindow::SetPos(pos)
moves the window to a specified position- The current window position can be obtained with
Window::GetPos()
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
// Display window position on screen
Print << Window::GetPos();
if (SimpleGUI::Button(U"(0, 0)", Vec2{ 200, 20 }))
{
// Move window to screen (0, 0)
Window::SetPos(0, 0);
}
if (SimpleGUI::Button(U"(200, 200)", Vec2{ 300, 20 }))
{
// Move window to screen (200, 200)
Window::SetPos(200, 200);
}
}
}
44.13 Minimize and Maximize¶
- To minimize a window programmatically, call
Window::Minimize()
- To maximize, call
Window::Maximize()
- To maximize a window, the window style must be
WindowStyle::Sizable
- To restore a minimized/maximized window to its previous size, call
Window::Restore()
- Whether a window is minimized can be obtained with
Window::GetState().minimized
- Whether it's maximized can be obtained with
Window::GetState().maximized
# include <Siv3D.hpp>
void Main()
{
// Enable window maximization
Window::SetStyle(WindowStyle::Sizable);
// Variable to count during minimization
int32 count = 0;
while (System::Update())
{
ClearPrint();
Print << U"Scene Size: " << Scene::Size();
Print << U"Virtual Size: " << Window::GetState().virtualSize;
Print << U"Frame Buffer Size: " << Window::GetState().frameBufferSize;
Print << U"Minimized Frame Count: " << count;
Print << U"Maximized: " << Window::GetState().maximized;
if (Window::GetState().minimized)
{
++count;
}
// 100 px checkerboard pattern to check scene size
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if (IsEven(x + y))
{
Rect{ (x * 100), (y * 100), 100 }.draw(ColorF{ 0.4 });
}
}
}
if (SimpleGUI::Button(U"Minimize", Vec2{ 300, 40 }))
{
// Minimize window
Window::Minimize();
}
if (SimpleGUI::Button(U"Maximize", Vec2{ 300, 80 }))
{
// Maximize window
Window::Maximize();
}
if (SimpleGUI::Button(U"Restore", Vec2{ 300, 120 }))
{
// Restore minimized/maximized window to original size
Window::Restore();
}
}
}
44.14 Monitor Information¶
- To get a list of information about connected monitors, use
System::EnumerateMonitors()
- The result is obtained as
Array<MonitorInfo>
type - The member variables of
MonitorInfo
type are as follows:
Code | Description |
---|---|
String name |
Display name |
String id |
Display ID |
String displayDeviceName |
Internal display name |
Rect displayRect |
Position and size of entire display |
Rect workArea |
Position and size of available area excluding taskbar, etc. |
Size fullscreenResolution |
Resolution in fullscreen mode |
bool isPrimary |
true if main display, false otherwise |
Optional<Size> sizeMillimeter |
Physical size (mm), none if unavailable |
Optional<double> scaling |
UI scaling factor. none if unavailable |
Optional<double> refreshRate |
Refresh rate. none if unavailable |
# include <Siv3D.hpp>
void Main()
{
// Get list of connected monitor information
const Array<MonitorInfo> monitors = System::EnumerateMonitors();
for (const auto& monitor : monitors)
{
Print << U"name: " << monitor.name;
Print << U"displayRect: " << monitor.displayRect << U" workArea: " << monitor.workArea;
Print << U"fullscreenResolution: " << monitor.fullscreenResolution << U" sizeMillimeter: " << monitor.sizeMillimeter;
Print << U"scaling: " << monitor.scaling << U" refreshRate: " << monitor.refreshRate;
Print << U"isPrimary: " << monitor.isPrimary;
Print << U"-----";
}
while (System::Update())
{
}
}
- To get the monitor index where the current program's window exists, use
System::GetCurrentMonitorIndex()
- This index corresponds to the array returned by
System::EnumerateMonitors()
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << System::GetCurrentMonitorIndex();
}
}
44.15 Fullscreen Mode¶
- To put the application in fullscreen mode, call
Window::SetFullscreen(true)
- To return to windowed mode, call
Window::SetFullscreen(false)
- The second argument of
Window::SetFullscreen(true)
can specify the monitor index for fullscreen display - Whether the application is in fullscreen mode can be obtained with
Window::GetState().fullscreen
# include <Siv3D.hpp>
void Main()
{
while (System::Update())
{
ClearPrint();
Print << U"scene size: " << Scene::Size();
Print << U"virtualSize: " << Window::GetState().virtualSize;
Print << U"frameBufferSize: " << Window::GetState().frameBufferSize;
Print << U"fullscreen: " << Window::GetState().fullscreen;
// 100px checkerboard pattern
for (int32 y = 0; y < 50; ++y)
{
for (int32 x = 0; x < 50; ++x)
{
if ((x + y) % 2)
{
Rect{ x * 100, y * 100, 100 }.draw(ColorF{ 0.2, 0.3, 0.4 });
}
}
}
if (Window::GetState().fullscreen)
{
if (SimpleGUI::Button(U"Window mode", Vec2{ 300, 20 }))
{
// Switch to windowed mode
Window::SetFullscreen(false);
}
}
else
{
if (SimpleGUI::Button(U"Fullscreen mode", Vec2{ 300, 20 }))
{
// Switch to fullscreen mode
Window::SetFullscreen(true);
}
}
}
}
44.16 Full-screen Mode (Windows)¶
- On Windows, you can enter full-screen mode by pressing Alt+Enter while the application is running (Tutorial 5.5)
- The behavior is similar to fullscreen mode, but the scene resize mode is set to
Resize::Keep
and the scene size doesn't change - This is useful when you want to run applications that don't support fullscreen mode or resolution changes in full-screen with large display
- To disable this key operation, call
Window::SetToggleFullscreenEnabled(false)