Adds MSAA to anti-aliasing techniques.
Tested By: Freagarach, OptimusShepard, Stan Differential Revision: https://code.wildfiregames.com/D2812 This was SVN commit r24188.
This commit is contained in:
parent
25490bfec3
commit
9937116f2b
@ -125,7 +125,11 @@
|
||||
"config": "antialiasing",
|
||||
"list": [
|
||||
{ "value": "disabled", "label": "Disabled", "tooltip": "Do not use anti-aliasing." },
|
||||
{ "value": "fxaa", "label": "FXAA", "tooltip": "Fast, but simple anti-aliasing." }
|
||||
{ "value": "fxaa", "label": "FXAA", "tooltip": "Fast, but simple anti-aliasing." },
|
||||
{ "value": "msaa2", "label": "MSAA (x2)", "tooltip": "Slow, but high-quality anti-aliasing, uses 2 samples per pixel. Supported for GL3.3+." },
|
||||
{ "value": "msaa4", "label": "MSAA (x4)", "tooltip": "Slow, but high-quality anti-aliasing, uses 4 samples per pixel. Supported for GL3.3+." },
|
||||
{ "value": "msaa8", "label": "MSAA (x8)", "tooltip": "Slow, but high-quality anti-aliasing, uses 8 samples per pixel. Supported for GL3.3+." },
|
||||
{ "value": "msaa16", "label": "MSAA (x16)", "tooltip": "Slow, but high-quality anti-aliasing, uses 16 samples per pixel. Supported for GL3.3+." }
|
||||
],
|
||||
"function": "Renderer_UpdateAntiAliasingTechnique"
|
||||
},
|
||||
|
@ -144,6 +144,11 @@ typedef GLuint GLhandleARB;
|
||||
|
||||
#else
|
||||
|
||||
// We might not have multisample on macOS.
|
||||
#ifndef GL_TEXTURE_2D_MULTISAMPLE
|
||||
#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
|
||||
#endif
|
||||
|
||||
// were these defined as real functions in gl.h already?
|
||||
|
||||
// GL_EXT_draw_range_elements / GL1.2:
|
||||
@ -385,6 +390,9 @@ FUNC2(void, glGetQueryObjectui64v, glGetQueryObjectui64v, "3.3", (GLuint id, GLe
|
||||
FUNC2(void*, glMapBufferRange, glMapBufferRange, "3.0", (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access))
|
||||
FUNC2(void, glFlushMappedBufferRange, glFlushMappedBufferRange, "3.0", (GLenum target, GLintptr offset, GLsizeiptr length))
|
||||
|
||||
// GL_ARB_texture_multisample / GL3.3:
|
||||
FUNC2(void, glTexImage2DMultisample, glTexImage2DMultisample, "3.3", (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations))
|
||||
|
||||
// GL_GREMEDY_string_marker (from gDEBugger)
|
||||
FUNC(int, glStringMarkerGREMEDY, (GLsizei len, const GLvoid *string))
|
||||
|
||||
|
@ -32,13 +32,17 @@
|
||||
#include "ps/World.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/RenderingOptions.h"
|
||||
#include "tools/atlas/GameInterface/GameLoop.h"
|
||||
|
||||
#if !CONFIG2_GLES
|
||||
|
||||
CPostprocManager::CPostprocManager()
|
||||
: m_IsInitialized(false), m_PingFbo(0), m_PongFbo(0), m_PostProcEffect(L"default"), m_ColorTex1(0), m_ColorTex2(0),
|
||||
m_DepthTex(0), m_BloomFbo(0), m_BlurTex2a(0), m_BlurTex2b(0), m_BlurTex4a(0), m_BlurTex4b(0),
|
||||
m_BlurTex8a(0), m_BlurTex8b(0), m_WhichBuffer(true), m_Sharpness(0.3f)
|
||||
: m_IsInitialized(false), m_PingFbo(0), m_PongFbo(0), m_PostProcEffect(L"default"),
|
||||
m_ColorTex1(0), m_ColorTex2(0), m_DepthTex(0), m_BloomFbo(0), m_BlurTex2a(0),
|
||||
m_BlurTex2b(0), m_BlurTex4a(0), m_BlurTex4b(0), m_BlurTex8a(0), m_BlurTex8b(0),
|
||||
m_WhichBuffer(true), m_Sharpness(0.3f), m_UsingMultisampleBuffer(false),
|
||||
m_MultisampleFBO(0), m_MultisampleColorTex(0), m_MultisampleDepthTex(0),
|
||||
m_MultisampleCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -76,6 +80,14 @@ void CPostprocManager::Initialize()
|
||||
if (m_IsInitialized)
|
||||
return;
|
||||
|
||||
GLint maxSamples = 0;
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
|
||||
const GLsizei possibleSampleCounts[] = {2, 4, 8, 16};
|
||||
std::copy_if(
|
||||
std::begin(possibleSampleCounts), std::end(possibleSampleCounts),
|
||||
std::back_inserter(m_AllowedSampleCounts),
|
||||
[maxSamples](const GLsizei sampleCount) { return sampleCount <= maxSamples; } );
|
||||
|
||||
// The screen size starts out correct and then must be updated with Resize()
|
||||
m_Width = g_Renderer.GetWidth();
|
||||
m_Height = g_Renderer.GetHeight();
|
||||
@ -193,6 +205,12 @@ void CPostprocManager::RecreateBuffers()
|
||||
}
|
||||
*/
|
||||
|
||||
if (m_UsingMultisampleBuffer)
|
||||
{
|
||||
DestroyMultisampleBuffer();
|
||||
CreateMultisampleBuffer();
|
||||
}
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
@ -371,6 +389,13 @@ void CPostprocManager::CaptureRenderOutput()
|
||||
pglDrawBuffers(1, buffers);
|
||||
|
||||
m_WhichBuffer = true;
|
||||
|
||||
if (m_UsingMultisampleBuffer)
|
||||
{
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_MultisampleFBO);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
pglDrawBuffers(1, buffers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -576,13 +601,52 @@ void CPostprocManager::UpdateAntiAliasingTechnique()
|
||||
m_AAName = newAAName;
|
||||
m_AATech.reset();
|
||||
|
||||
if (m_UsingMultisampleBuffer)
|
||||
{
|
||||
m_UsingMultisampleBuffer = false;
|
||||
DestroyMultisampleBuffer();
|
||||
}
|
||||
|
||||
// We have to hardcode names in the engine, because anti-aliasing
|
||||
// techinques strongly depend on the graphics pipeline.
|
||||
// We might use enums in future though.
|
||||
const CStr msaaPrefix = "msaa";
|
||||
if (m_AAName == "fxaa")
|
||||
{
|
||||
m_AATech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("fxaa"));
|
||||
}
|
||||
else if (m_AAName.size() > msaaPrefix.size() && m_AAName.substr(0, msaaPrefix.size()) == msaaPrefix)
|
||||
{
|
||||
#if !CONFIG2_GLES
|
||||
// We don't want to enable MSAA in Atlas, because it uses wxWidgets and its canvas.
|
||||
if (g_AtlasGameLoop && g_AtlasGameLoop->running)
|
||||
return;
|
||||
const bool is_msaa_supported =
|
||||
ogl_HaveVersion("3.3") &&
|
||||
ogl_HaveExtension("GL_ARB_multisample") &&
|
||||
ogl_HaveExtension("GL_ARB_texture_multisample") &&
|
||||
!m_AllowedSampleCounts.empty() &&
|
||||
g_RenderingOptions.GetPreferGLSL();
|
||||
if (!is_msaa_supported)
|
||||
{
|
||||
LOGWARNING("MSAA is unsupported.");
|
||||
return;
|
||||
}
|
||||
std::stringstream ss(m_AAName.substr(msaaPrefix.size()));
|
||||
ss >> m_MultisampleCount;
|
||||
if (std::find(std::begin(m_AllowedSampleCounts), std::end(m_AllowedSampleCounts), m_MultisampleCount) ==
|
||||
std::end(m_AllowedSampleCounts))
|
||||
{
|
||||
m_MultisampleCount = 4;
|
||||
LOGWARNING("Wrong MSAA sample count: %s.", m_AAName.EscapeToPrintableASCII().c_str());
|
||||
}
|
||||
m_UsingMultisampleBuffer = true;
|
||||
CreateMultisampleBuffer();
|
||||
#else
|
||||
#warning TODO: implement and test MSAA for GLES
|
||||
LOGWARNING("MSAA is unsupported.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CPostprocManager::UpdateSharpeningTechnique()
|
||||
@ -614,6 +678,77 @@ void CPostprocManager::SetDepthBufferClipPlanes(float nearPlane, float farPlane)
|
||||
m_FarPlane = farPlane;
|
||||
}
|
||||
|
||||
void CPostprocManager::CreateMultisampleBuffer()
|
||||
{
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
glGenTextures(1, &m_MultisampleColorTex);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleColorTex);
|
||||
pglTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleCount, GL_RGBA, m_Width, m_Height, GL_TRUE);
|
||||
|
||||
// Allocate the Depth/Stencil texture.
|
||||
glGenTextures(1, &m_MultisampleDepthTex);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleDepthTex);
|
||||
pglTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleCount, GL_DEPTH24_STENCIL8_EXT, m_Width, m_Height, GL_TRUE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||
|
||||
ogl_WarnIfError();
|
||||
|
||||
// Set up the framebuffers with some initial textures.
|
||||
pglGenFramebuffersEXT(1, &m_MultisampleFBO);
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_MultisampleFBO);
|
||||
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleColorTex, 0);
|
||||
|
||||
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleDepthTex, 0);
|
||||
|
||||
GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
LOGWARNING("Multisample framebuffer object incomplete (A): 0x%04X", status);
|
||||
m_UsingMultisampleBuffer = false;
|
||||
DestroyMultisampleBuffer();
|
||||
}
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void CPostprocManager::DestroyMultisampleBuffer()
|
||||
{
|
||||
if (m_UsingMultisampleBuffer)
|
||||
return;
|
||||
if (m_MultisampleFBO)
|
||||
pglDeleteFramebuffersEXT(1, &m_MultisampleFBO);
|
||||
if (m_MultisampleColorTex)
|
||||
glDeleteTextures(1, &m_MultisampleColorTex);
|
||||
if (m_MultisampleDepthTex)
|
||||
glDeleteTextures(1, &m_MultisampleDepthTex);
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
bool CPostprocManager::IsMultisampleEnabled() const
|
||||
{
|
||||
return m_UsingMultisampleBuffer;
|
||||
}
|
||||
|
||||
void CPostprocManager::ResolveMultisampleFramebuffer()
|
||||
{
|
||||
if (!m_UsingMultisampleBuffer)
|
||||
return;
|
||||
|
||||
pglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
pglBlitFramebufferEXT(0, 0, m_Width, m_Height, 0, 0, m_Width, m_Height,
|
||||
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#warning TODO: implement PostprocManager for GLES
|
||||
@ -691,4 +826,21 @@ void CPostprocManager::ReleaseRenderOutput()
|
||||
{
|
||||
}
|
||||
|
||||
void CPostprocManager::CreateMultisampleBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void CPostprocManager::DestroyMultisampleBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
bool CPostprocManager::IsMultisampleEnabled() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPostprocManager::ResolveMultisampleFramebuffer()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -70,7 +70,15 @@ public:
|
||||
// @note CPostprocManager must be initialized first
|
||||
void ReleaseRenderOutput();
|
||||
|
||||
// Returns true if we render main scene in the MSAA framebuffer.
|
||||
bool IsMultisampleEnabled() const;
|
||||
|
||||
// Resolves the MSAA framebuffer into the regular one.
|
||||
void ResolveMultisampleFramebuffer();
|
||||
|
||||
private:
|
||||
void CreateMultisampleBuffer();
|
||||
void DestroyMultisampleBuffer();
|
||||
|
||||
// Two framebuffers, that we flip between at each shader pass.
|
||||
GLuint m_PingFbo, m_PongFbo;
|
||||
@ -99,6 +107,11 @@ private:
|
||||
|
||||
CStr m_AAName;
|
||||
CShaderTechniquePtr m_AATech;
|
||||
bool m_UsingMultisampleBuffer;
|
||||
GLuint m_MultisampleFBO;
|
||||
GLuint m_MultisampleColorTex, m_MultisampleDepthTex;
|
||||
GLsizei m_MultisampleCount;
|
||||
std::vector<GLsizei> m_AllowedSampleCounts;
|
||||
|
||||
// The current screen dimensions in pixels.
|
||||
int m_Width, m_Height;
|
||||
|
@ -1387,6 +1387,9 @@ void CRenderer::RenderSubmissions(const CBoundingBoxAligned& waterScissor)
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
|
||||
if (g_Renderer.GetPostprocManager().IsMultisampleEnabled())
|
||||
g_Renderer.GetPostprocManager().ResolveMultisampleFramebuffer();
|
||||
|
||||
// render debug-related terrain overlays
|
||||
ITerrainOverlay::RenderOverlaysAfterWater(cullGroup);
|
||||
ogl_WarnIfError();
|
||||
|
Loading…
Reference in New Issue
Block a user