Fixed pause blur with MSAA

issue #656
master
krzys-h 2016-06-19 11:45:56 +02:00
parent 543df84db6
commit 9d9131c3fb
2 changed files with 116 additions and 111 deletions

View File

@ -3163,6 +3163,10 @@ void CEngine::Render()
UseMSAA(false);
// marked to capture currently rendered world
if (m_captureWorld)
Capture3DScene();
m_app->StartPerformanceCounter(PCNT_RENDER_INTERFACE);
DrawInterface();
m_app->StopPerformanceCounter(PCNT_RENDER_INTERFACE);
@ -3171,6 +3175,116 @@ void CEngine::Render()
m_device->EndScene();
}
void CEngine::Capture3DScene()
{
// destroy existing texture
if (m_capturedWorldTexture.Valid())
{
m_device->DestroyTexture(m_capturedWorldTexture);
m_capturedWorldTexture = Texture();
}
// obtain pixels from screen
int width = m_size.x;
int height = m_size.y;
auto pixels = m_device->GetFrameBufferPixels();
unsigned char* data = reinterpret_cast<unsigned char*>(pixels->GetPixelsData());
// calculate 2nd mipmap
int newWidth = width / 4;
int newHeight = height / 4;
std::unique_ptr<unsigned char[]> mipmap(new unsigned char[4 * newWidth * newHeight]);
for (int x = 0; x < newWidth; x++)
{
for (int y = 0; y < newHeight; y++)
{
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
int index = 4 * ((4 * x + i) + width * (4 * y + j));
for (int k = 0; k < 4; k++)
color[k] += data[index + k];
}
}
int index = 4 * (x + newWidth * y);
for (int k = 0; k < 4; k++)
{
mipmap[index + k] = static_cast<unsigned char>(color[k] * (1.0f / 16.0f));
}
}
}
// calculate Gaussian blur
std::unique_ptr<unsigned char[]> blured(new unsigned char[4 * newWidth * newHeight]);
float matrix[7][7] =
{
{ 0.00000067f, 0.00002292f, 0.00019117f, 0.00038771f, 0.00019117f, 0.00002292f, 0.00000067f },
{ 0.00002292f, 0.00078634f, 0.00655965f, 0.01330373f, 0.00655965f, 0.00078633f, 0.00002292f },
{ 0.00019117f, 0.00655965f, 0.05472157f, 0.11098164f, 0.05472157f, 0.00655965f, 0.00019117f },
{ 0.00038771f, 0.01330373f, 0.11098164f, 0.22508352f, 0.11098164f, 0.01330373f, 0.00038771f },
{ 0.00019117f, 0.00655965f, 0.05472157f, 0.11098164f, 0.05472157f, 0.00655965f, 0.00019117f },
{ 0.00002292f, 0.00078633f, 0.00655965f, 0.01330373f, 0.00655965f, 0.00078633f, 0.00002292f },
{ 0.00000067f, 0.00002292f, 0.00019117f, 0.00038771f, 0.00019117f, 0.00002292f, 0.00000067f }
};
for (int x = 0; x < newWidth; x++)
{
for (int y = 0; y < newHeight; y++)
{
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
for (int i = -3; i <= 3; i++)
{
for (int j = -3; j <= 3; j++)
{
int xp = Math::Clamp(x + i, 0, newWidth - 1);
int yp = Math::Clamp(y + j, 0, newHeight - 1);
float weight = matrix[i + 3][j + 3];
int index = 4 * (newWidth * yp + xp);
for (int k = 0; k < 4; k++)
color[k] += weight * mipmap[index + k];
}
}
int index = 4 * (newWidth * y + x);
for (int k = 0; k < 4; k++)
{
float value = Math::Clamp(color[k], 0.0f, 255.0f);
blured[index + k] = static_cast<unsigned char>(value);
}
}
}
// create SDL surface and final texture
ImageData image;
image.surface = SDL_CreateRGBSurfaceFrom(blured.get(), newWidth, newHeight, 32, 0, 0, 0, 0, 0xFF000000);
TextureCreateParams params;
params.filter = TEX_FILTER_BILINEAR;
params.format = TEX_IMG_RGBA;
params.mipmap = false;
m_capturedWorldTexture = m_device->CreateTexture(&image, params);
SDL_FreeSurface(image.surface);
m_captureWorld = false;
m_worldCaptured = true;
}
void CEngine::Draw3DScene()
{
// use currently captured scene for world
@ -3451,117 +3565,6 @@ void CEngine::Draw3DScene()
DrawForegroundImage(); // draws the foreground
if (! m_overFront) DrawOverColor(); // draws the foreground color
// marked to capture currently rendered world
if (m_captureWorld)
{
// destroy existing texture
if (m_capturedWorldTexture.Valid())
{
m_device->DestroyTexture(m_capturedWorldTexture);
m_capturedWorldTexture = Texture();
}
// obtain pixels from screen
int width = m_size.x;
int height = m_size.y;
auto pixels = m_device->GetFrameBufferPixels();
unsigned char* data = reinterpret_cast<unsigned char*>(pixels->GetPixelsData());
// calculate 2nd mipmap
int newWidth = width / 4;
int newHeight = height / 4;
std::unique_ptr<unsigned char[]> mipmap(new unsigned char[4 * newWidth * newHeight]);
for (int x = 0; x < newWidth; x++)
{
for (int y = 0; y < newHeight; y++)
{
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
int index = 4 * ((4 * x + i) + width * (4 * y + j));
for (int k = 0; k < 4; k++)
color[k] += data[index + k];
}
}
int index = 4 * (x + newWidth * y);
for (int k = 0; k < 4; k++)
{
mipmap[index + k] = static_cast<unsigned char>(color[k] * (1.0f / 16.0f));
}
}
}
// calculate Gaussian blur
std::unique_ptr<unsigned char[]> blured(new unsigned char[4 * newWidth * newHeight]);
float matrix[7][7] =
{
{ 0.00000067f, 0.00002292f, 0.00019117f, 0.00038771f, 0.00019117f, 0.00002292f, 0.00000067f },
{ 0.00002292f, 0.00078634f, 0.00655965f, 0.01330373f, 0.00655965f, 0.00078633f, 0.00002292f },
{ 0.00019117f, 0.00655965f, 0.05472157f, 0.11098164f, 0.05472157f, 0.00655965f, 0.00019117f },
{ 0.00038771f, 0.01330373f, 0.11098164f, 0.22508352f, 0.11098164f, 0.01330373f, 0.00038771f },
{ 0.00019117f, 0.00655965f, 0.05472157f, 0.11098164f, 0.05472157f, 0.00655965f, 0.00019117f },
{ 0.00002292f, 0.00078633f, 0.00655965f, 0.01330373f, 0.00655965f, 0.00078633f, 0.00002292f },
{ 0.00000067f, 0.00002292f, 0.00019117f, 0.00038771f, 0.00019117f, 0.00002292f, 0.00000067f }
};
for (int x = 0; x < newWidth; x++)
{
for (int y = 0; y < newHeight; y++)
{
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
for (int i = -3; i <= 3; i++)
{
for (int j = -3; j <= 3; j++)
{
int xp = Math::Clamp(x + i, 0, newWidth - 1);
int yp = Math::Clamp(y + j, 0, newHeight - 1);
float weight = matrix[i + 3][j + 3];
int index = 4 * (newWidth * yp + xp);
for (int k = 0; k < 4; k++)
color[k] += weight * mipmap[index + k];
}
}
int index = 4 * (newWidth * y + x);
for (int k = 0; k < 4; k++)
{
float value = Math::Clamp(color[k], 0.0f, 255.0f);
blured[index + k] = static_cast<unsigned char>(value);
}
}
}
// create SDL surface and final texture
ImageData image;
image.surface = SDL_CreateRGBSurfaceFrom(blured.get(), newWidth, newHeight, 32, 0, 0, 0, 0, 0xFF000000);
TextureCreateParams params;
params.filter = TEX_FILTER_BILINEAR;
params.format = TEX_IMG_RGBA;
params.mipmap = false;
m_capturedWorldTexture = m_device->CreateTexture(&image, params);
SDL_FreeSurface(image.surface);
m_captureWorld = false;
m_worldCaptured = true;
}
}
void CEngine::DrawCrashSpheres()

View File

@ -1214,6 +1214,8 @@ protected:
//! Prepares the interface for 3D scene
void Draw3DScene();
//! Capture the 3D scene for pause blur
void Capture3DScene();
//! Renders shadow map
void RenderShadowMap();
//! Enables or disables shadow mapping