Fixes big screenshots with water (reflection or refraction camera), adds big screenshot customization.
Commented By: Stan, wraitii Differential Revision: https://code.wildfiregames.com/D3557 This was SVN commit r24891.
This commit is contained in:
parent
44dc2ca6f2
commit
f175bc4f8d
@ -59,6 +59,11 @@ forceglprofile = "compatibility" ; Possible values: compatibility, core, es
|
||||
forceglmajorversion = 3
|
||||
forceglminorversion = 3
|
||||
|
||||
; Big screenshot tiles
|
||||
screenshot.tiles = 4
|
||||
screenshot.tilewidth = 480
|
||||
screenshot.tileheight = 270
|
||||
|
||||
; Emulate right-click with Ctrl+Click on Mac mice
|
||||
macmouse = false
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -208,7 +208,14 @@ static InReaction MainInputHandler(const SDL_Event_* ev)
|
||||
}
|
||||
else if (hotkey == "bigscreenshot")
|
||||
{
|
||||
WriteBigScreenshot(L".bmp", 10);
|
||||
int tiles = 4, tileWidth = 256, tileHeight = 256;
|
||||
CFG_GET_VAL("screenshot.tiles", tiles);
|
||||
CFG_GET_VAL("screenshot.tilewidth", tileWidth);
|
||||
CFG_GET_VAL("screenshot.tileheight", tileHeight);
|
||||
if (tiles > 0 && tileWidth > 0 && tileHeight > 0)
|
||||
WriteBigScreenshot(L".bmp", tiles, tileWidth, tileHeight);
|
||||
else
|
||||
LOGWARNING("Invalid big screenshot size: tiles=%d tileWidth=%d tileHeight=%d", tiles, tileWidth, tileHeight);
|
||||
return IN_HANDLED;
|
||||
}
|
||||
else if (hotkey == "togglefullscreen")
|
||||
|
@ -298,11 +298,15 @@ void WriteScreenshot(const VfsPath& extension)
|
||||
|
||||
|
||||
|
||||
// Similar to WriteScreenshot, but generates an image of size 640*tiles x 480*tiles.
|
||||
void WriteBigScreenshot(const VfsPath& extension, int tiles)
|
||||
// Similar to WriteScreenshot, but generates an image of size tileWidth*tiles x tileHeight*tiles.
|
||||
void WriteBigScreenshot(const VfsPath& extension, int tiles, int tileWidth, int tileHeight)
|
||||
{
|
||||
// If the game hasn't started yet then use WriteScreenshot to generate the image.
|
||||
if(g_Game == NULL){ WriteScreenshot(L".bmp"); return; }
|
||||
if (g_Game == nullptr)
|
||||
{
|
||||
WriteScreenshot(L".bmp");
|
||||
return;
|
||||
}
|
||||
|
||||
// get next available numbered filename
|
||||
// note: %04d -> always 4 digits, so sorting by filename works correctly.
|
||||
@ -313,10 +317,9 @@ void WriteBigScreenshot(const VfsPath& extension, int tiles)
|
||||
|
||||
// Slightly ugly and inflexible: Always draw 640*480 tiles onto the screen, and
|
||||
// hope the screen is actually large enough for that.
|
||||
const int tile_w = 640, tile_h = 480;
|
||||
ENSURE(g_xres >= tile_w && g_yres >= tile_h);
|
||||
ENSURE(g_xres >= tileWidth && g_yres >= tileHeight);
|
||||
|
||||
const int img_w = tile_w*tiles, img_h = tile_h*tiles;
|
||||
const int img_w = tileWidth * tiles, img_h = tileHeight * tiles;
|
||||
const int bpp = 24;
|
||||
GLenum fmt = GL_RGB;
|
||||
int flags = TEX_BOTTOM_UP;
|
||||
@ -331,7 +334,7 @@ void WriteBigScreenshot(const VfsPath& extension, int tiles)
|
||||
}
|
||||
|
||||
const size_t img_size = img_w * img_h * bpp/8;
|
||||
const size_t tile_size = tile_w * tile_h * bpp/8;
|
||||
const size_t tile_size = tileWidth * tileHeight * bpp/8;
|
||||
const size_t hdr_size = tex_hdr_size(filename);
|
||||
void* tile_data = malloc(tile_size);
|
||||
if(!tile_data)
|
||||
@ -340,7 +343,7 @@ void WriteBigScreenshot(const VfsPath& extension, int tiles)
|
||||
return;
|
||||
}
|
||||
shared_ptr<u8> img_buf;
|
||||
AllocateAligned(img_buf, hdr_size+img_size, maxSectorSize);
|
||||
AllocateAligned(img_buf, hdr_size + img_size, maxSectorSize);
|
||||
|
||||
Tex t;
|
||||
GLvoid* img = img_buf.get() + hdr_size;
|
||||
@ -356,8 +359,8 @@ void WriteBigScreenshot(const VfsPath& extension, int tiles)
|
||||
|
||||
// Resize various things so that the sizes and aspect ratios are correct
|
||||
{
|
||||
g_Renderer.Resize(tile_w, tile_h);
|
||||
SViewPort vp = { 0, 0, tile_w, tile_h };
|
||||
g_Renderer.Resize(tileWidth, tileHeight);
|
||||
SViewPort vp = { 0, 0, tileWidth, tileHeight };
|
||||
g_Game->GetView()->SetViewport(vp);
|
||||
}
|
||||
|
||||
@ -380,6 +383,7 @@ void WriteBigScreenshot(const VfsPath& extension, int tiles)
|
||||
// Render each tile
|
||||
CMatrix3D projection;
|
||||
projection.SetIdentity();
|
||||
const float aspectRatio = 1.0f * tileWidth / tileHeight;
|
||||
for (int tile_y = 0; tile_y < tiles; ++tile_y)
|
||||
{
|
||||
for (int tile_x = 0; tile_x < tiles; ++tile_x)
|
||||
@ -387,7 +391,7 @@ void WriteBigScreenshot(const VfsPath& extension, int tiles)
|
||||
// Adjust the camera to render the appropriate region
|
||||
if (oldCamera.GetProjectionType() == CCamera::PERSPECTIVE)
|
||||
{
|
||||
projection.SetPerspectiveTile(oldCamera.GetFOV(), oldCamera.GetAspectRatio(), oldCamera.GetNearPlane(), oldCamera.GetFarPlane(), tiles, tile_x, tile_y);
|
||||
projection.SetPerspectiveTile(oldCamera.GetFOV(), aspectRatio, oldCamera.GetNearPlane(), oldCamera.GetFarPlane(), tiles, tile_x, tile_y);
|
||||
}
|
||||
g_Game->GetView()->GetCamera()->SetProjection(projection);
|
||||
|
||||
@ -398,12 +402,12 @@ void WriteBigScreenshot(const VfsPath& extension, int tiles)
|
||||
RenderLogger(true);
|
||||
|
||||
// Copy the tile pixels into the main image
|
||||
glReadPixels(0, 0, tile_w, tile_h, fmt, GL_UNSIGNED_BYTE, tile_data);
|
||||
for (int y = 0; y < tile_h; ++y)
|
||||
glReadPixels(0, 0, tileWidth, tileHeight, fmt, GL_UNSIGNED_BYTE, tile_data);
|
||||
for (int y = 0; y < tileHeight; ++y)
|
||||
{
|
||||
void* dest = (char*)img + ((tile_y*tile_h + y) * img_w + (tile_x*tile_w)) * bpp/8;
|
||||
void* src = (char*)tile_data + y * tile_w * bpp/8;
|
||||
memcpy(dest, src, tile_w * bpp/8);
|
||||
void* dest = static_cast<char*>(img) + ((tile_y * tileHeight + y) * img_w + (tile_x * tileWidth)) * bpp / 8;
|
||||
void* src = static_cast<char*>(tile_data) + y * tileWidth * bpp / 8;
|
||||
memcpy(dest, src, tileWidth * bpp / 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2018 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -30,7 +30,7 @@ const wchar_t* ErrorString(int err);
|
||||
OsPath createDateIndexSubdirectory(const OsPath& parentDir);
|
||||
|
||||
void WriteScreenshot(const VfsPath& extension);
|
||||
void WriteBigScreenshot(const VfsPath& extension, int tiles);
|
||||
void WriteBigScreenshot(const VfsPath& extension, int tiles = 4, int tileWidth = 640, int tileHeight = 480);
|
||||
|
||||
Status tex_write(Tex* t, const VfsPath& filename);
|
||||
|
||||
|
@ -926,13 +926,17 @@ void CRenderer::ComputeReflectionCamera(CCamera& camera, const CBoundingBoxAlign
|
||||
{
|
||||
WaterManager& wm = m->waterManager;
|
||||
|
||||
ENSURE(m_ViewCamera.GetProjectionType() == CCamera::PERSPECTIVE);
|
||||
float fov = m_ViewCamera.GetFOV();
|
||||
|
||||
CMatrix3D projection;
|
||||
if (m_ViewCamera.GetProjectionType() == CCamera::PERSPECTIVE)
|
||||
{
|
||||
const float aspectRatio = 1.0f;
|
||||
// Expand fov slightly since ripples can reflect parts of the scene that
|
||||
// are slightly outside the normal camera view, and we want to avoid any
|
||||
// noticeable edge-filtering artifacts
|
||||
fov *= 1.05f;
|
||||
projection.SetPerspective(m_ViewCamera.GetFOV() * 1.05f, aspectRatio, m_ViewCamera.GetNearPlane(), m_ViewCamera.GetFarPlane());
|
||||
}
|
||||
else
|
||||
projection = m_ViewCamera.GetProjection();
|
||||
|
||||
camera = m_ViewCamera;
|
||||
|
||||
@ -942,7 +946,7 @@ void CRenderer::ComputeReflectionCamera(CCamera& camera, const CBoundingBoxAlign
|
||||
// the whole screen despite being rendered into a square, and cover slightly more
|
||||
// of the view so we can see wavy reflections of slightly off-screen objects.
|
||||
camera.m_Orientation.Scale(1, -1, 1);
|
||||
camera.m_Orientation.Translate(0, 2*wm.m_WaterHeight, 0);
|
||||
camera.m_Orientation.Translate(0, 2 * wm.m_WaterHeight, 0);
|
||||
camera.UpdateFrustum(scissor);
|
||||
// Clip slightly above the water to improve reflections of objects on the water
|
||||
// when the reflections are distorted.
|
||||
@ -954,27 +958,30 @@ void CRenderer::ComputeReflectionCamera(CCamera& camera, const CBoundingBoxAlign
|
||||
vp.m_X = 0;
|
||||
vp.m_Y = 0;
|
||||
camera.SetViewPort(vp);
|
||||
camera.SetPerspectiveProjection(m_ViewCamera.GetNearPlane(), m_ViewCamera.GetFarPlane(), fov);
|
||||
camera.SetProjection(projection);
|
||||
CMatrix3D scaleMat;
|
||||
scaleMat.SetScaling(m_Height/float(std::max(1, m_Width)), 1.0f, 1.0f);
|
||||
scaleMat.SetScaling(m_Height / static_cast<float>(std::max(1, m_Width)), 1.0f, 1.0f);
|
||||
camera.SetProjection(scaleMat * camera.GetProjection());
|
||||
|
||||
CVector4D camPlane(0, 1, 0, -wm.m_WaterHeight + 0.5f);
|
||||
SetObliqueFrustumClipping(camera, camPlane);
|
||||
|
||||
}
|
||||
|
||||
void CRenderer::ComputeRefractionCamera(CCamera& camera, const CBoundingBoxAligned& scissor) const
|
||||
{
|
||||
WaterManager& wm = m->waterManager;
|
||||
|
||||
ENSURE(m_ViewCamera.GetProjectionType() == CCamera::PERSPECTIVE);
|
||||
float fov = m_ViewCamera.GetFOV();
|
||||
|
||||
CMatrix3D projection;
|
||||
if (m_ViewCamera.GetProjectionType() == CCamera::PERSPECTIVE)
|
||||
{
|
||||
const float aspectRatio = 1.0f;
|
||||
// Expand fov slightly since ripples can reflect parts of the scene that
|
||||
// are slightly outside the normal camera view, and we want to avoid any
|
||||
// noticeable edge-filtering artifacts
|
||||
fov *= 1.05f;
|
||||
projection.SetPerspective(m_ViewCamera.GetFOV() * 1.05f, aspectRatio, m_ViewCamera.GetNearPlane(), m_ViewCamera.GetFarPlane());
|
||||
}
|
||||
else
|
||||
projection = m_ViewCamera.GetProjection();
|
||||
|
||||
camera = m_ViewCamera;
|
||||
|
||||
@ -991,9 +998,9 @@ void CRenderer::ComputeRefractionCamera(CCamera& camera, const CBoundingBoxAlign
|
||||
vp.m_X = 0;
|
||||
vp.m_Y = 0;
|
||||
camera.SetViewPort(vp);
|
||||
camera.SetPerspectiveProjection(m_ViewCamera.GetNearPlane(), m_ViewCamera.GetFarPlane(), fov);
|
||||
camera.SetProjection(projection);
|
||||
CMatrix3D scaleMat;
|
||||
scaleMat.SetScaling(m_Height/float(std::max(1, m_Width)), 1.0f, 1.0f);
|
||||
scaleMat.SetScaling(m_Height / static_cast<float>(std::max(1, m_Width)), 1.0f, 1.0f);
|
||||
camera.SetProjection(scaleMat * camera.GetProjection());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user