Enabled MSAA

This commit is contained in:
parax0 2016-08-30 19:05:28 -06:00
parent 4fd3e9c437
commit 1de2691f33
8 changed files with 146 additions and 88 deletions

View File

@ -2,20 +2,22 @@
#include <Common/Log.h> #include <Common/Log.h>
CFramebuffer::CFramebuffer() CFramebuffer::CFramebuffer()
: mInitialized(false) : mpRenderbuffer(nullptr)
, mpTexture(nullptr)
, mWidth(0) , mWidth(0)
, mHeight(0) , mHeight(0)
, mpRenderbuffer(nullptr) , mEnableMultisampling(false)
, mpTexture(nullptr) , mInitialized(false)
{ {
} }
CFramebuffer::CFramebuffer(u32 Width, u32 Height) CFramebuffer::CFramebuffer(u32 Width, u32 Height)
: mInitialized(false) : mpRenderbuffer(nullptr)
, mpTexture(nullptr)
, mWidth(0) , mWidth(0)
, mHeight(0) , mHeight(0)
, mpRenderbuffer(nullptr) , mEnableMultisampling(false)
, mpTexture(nullptr) , mInitialized(false)
{ {
Resize(Width, Height); Resize(Width, Height);
} }
@ -44,30 +46,18 @@ void CFramebuffer::Init()
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
mpRenderbuffer = new CRenderbuffer(mWidth, mHeight); mpRenderbuffer = new CRenderbuffer(mWidth, mHeight);
mpRenderbuffer->Bind();
glFramebufferRenderbuffer(
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mpRenderbuffer->BufferID()
);
mpTexture = new CTexture(mWidth, mHeight); mpTexture = new CTexture(mWidth, mHeight);
mpTexture->Bind(0); mpRenderbuffer->SetMultisamplingEnabled(mEnableMultisampling);
glFramebufferTexture2D( mpTexture->SetMultisamplingEnabled(mEnableMultisampling);
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpTexture->TextureID(), 0 InitBuffers();
);
mStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (mStatus != GL_FRAMEBUFFER_COMPLETE)
Log::Error("Framebuffer not complete");
mInitialized = true; mInitialized = true;
} }
} }
void CFramebuffer::Bind() void CFramebuffer::Bind(GLenum Target /*= GL_FRAMEBUFFER*/)
{ {
if (!mInitialized) Init(); if (!mInitialized) Init();
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); glBindFramebuffer(Target, mFramebuffer);
} }
void CFramebuffer::Resize(u32 Width, u32 Height) void CFramebuffer::Resize(u32 Width, u32 Height)
@ -81,8 +71,31 @@ void CFramebuffer::Resize(u32 Width, u32 Height)
{ {
mpRenderbuffer->Resize(Width, Height); mpRenderbuffer->Resize(Width, Height);
mpTexture->Resize(Width, Height); mpTexture->Resize(Width, Height);
InitBuffers();
}
}
}
void CFramebuffer::SetMultisamplingEnabled(bool Enable)
{
if (mEnableMultisampling != Enable)
{
mEnableMultisampling = Enable;
if (mInitialized)
{
mpRenderbuffer->SetMultisamplingEnabled(Enable);
mpTexture->SetMultisamplingEnabled(Enable);
InitBuffers();
}
}
}
// ************ PROTECTED ************
void CFramebuffer::InitBuffers()
{
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
mpRenderbuffer->Bind(); mpRenderbuffer->Bind();
glFramebufferRenderbuffer( glFramebufferRenderbuffer(
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mpRenderbuffer->BufferID() GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mpRenderbuffer->BufferID()
@ -90,21 +103,19 @@ void CFramebuffer::Resize(u32 Width, u32 Height)
mpTexture->Bind(0); mpTexture->Bind(0);
glFramebufferTexture2D( glFramebufferTexture2D(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpTexture->TextureID(), 0 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, (mEnableMultisampling ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D), mpTexture->TextureID(), 0
); );
}
}
}
CTexture* CFramebuffer::Texture() mStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
{
return mpTexture; if (mStatus != GL_FRAMEBUFFER_COMPLETE)
Log::Error("Framebuffer not complete; error " + TString::HexString((u32) mStatus, 0));
} }
// ************ STATIC ************ // ************ STATIC ************
void CFramebuffer::BindDefaultFramebuffer() void CFramebuffer::BindDefaultFramebuffer(GLenum Target /*= GL_FRAMEBUFFER*/)
{ {
glBindFramebuffer(GL_FRAMEBUFFER, smDefaultFramebuffer); glBindFramebuffer(Target, smDefaultFramebuffer);
} }
GLint CFramebuffer::smDefaultFramebuffer; GLint CFramebuffer::smDefaultFramebuffer;

View File

@ -11,6 +11,7 @@ class CFramebuffer
CRenderbuffer *mpRenderbuffer; CRenderbuffer *mpRenderbuffer;
CTexture *mpTexture; CTexture *mpTexture;
u32 mWidth, mHeight; u32 mWidth, mHeight;
bool mEnableMultisampling;
bool mInitialized; bool mInitialized;
GLenum mStatus; GLenum mStatus;
@ -22,11 +23,18 @@ public:
CFramebuffer(u32 Width, u32 Height); CFramebuffer(u32 Width, u32 Height);
~CFramebuffer(); ~CFramebuffer();
void Init(); void Init();
void Bind(); void Bind(GLenum Target = GL_FRAMEBUFFER);
void Resize(u32 Width, u32 Height); void Resize(u32 Width, u32 Height);
CTexture* Texture(); void SetMultisamplingEnabled(bool Enable);
static void BindDefaultFramebuffer();
// Accessors
inline CTexture* Texture() const { return mpTexture; }
// Static
static void BindDefaultFramebuffer(GLenum Target = GL_FRAMEBUFFER);
protected:
void InitBuffers();
}; };
#endif // CFRAMEBUFFER_H #endif // CFRAMEBUFFER_H

View File

@ -8,20 +8,23 @@ class CRenderbuffer
{ {
GLuint mRenderbuffer; GLuint mRenderbuffer;
u32 mWidth, mHeight; u32 mWidth, mHeight;
bool mEnableMultisampling;
bool mInitialized; bool mInitialized;
public: public:
CRenderbuffer::CRenderbuffer() CRenderbuffer::CRenderbuffer()
: mInitialized(false) : mWidth(0)
, mWidth(0)
, mHeight(0) , mHeight(0)
, mEnableMultisampling(false)
, mInitialized(false)
{ {
} }
CRenderbuffer::CRenderbuffer(u32 Width, u32 Height) CRenderbuffer::CRenderbuffer(u32 Width, u32 Height)
: mInitialized(false) : mWidth(Width)
, mWidth(Width)
, mHeight(Height) , mHeight(Height)
, mEnableMultisampling(false)
, mInitialized(false)
{ {
} }
@ -33,10 +36,9 @@ public:
void CRenderbuffer::Init() void CRenderbuffer::Init()
{ {
glGenRenderbuffers(1, &mRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
mInitialized = true; mInitialized = true;
glGenRenderbuffers(1, &mRenderbuffer);
InitStorage();
} }
inline void CRenderbuffer::Resize(u32 Width, u32 Height) inline void CRenderbuffer::Resize(u32 Width, u32 Height)
@ -45,10 +47,7 @@ public:
mHeight = Height; mHeight = Height;
if (mInitialized) if (mInitialized)
{ InitStorage();
Bind();
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
}
} }
inline void CRenderbuffer::Bind() inline void CRenderbuffer::Bind()
@ -66,6 +65,26 @@ public:
{ {
return mRenderbuffer; return mRenderbuffer;
} }
inline void SetMultisamplingEnabled(bool Enable)
{
if (mEnableMultisampling != Enable)
{
mEnableMultisampling = Enable;
InitStorage();
}
}
private:
void InitStorage()
{
Bind();
if (mEnableMultisampling)
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT24, mWidth, mHeight);
else
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
}
}; };
#endif // CRENDERBUFFER_H #endif // CRENDERBUFFER_H

View File

@ -176,6 +176,11 @@ void CRenderer::RenderBloom()
CGraphics::SetIdentityMVP(); CGraphics::SetIdentityMVP();
CGraphics::UpdateMVPBlock(); CGraphics::UpdateMVPBlock();
mPostProcessFramebuffer.Resize(mViewportWidth, mViewportHeight);
mSceneFramebuffer.Bind(GL_READ_FRAMEBUFFER);
mPostProcessFramebuffer.Bind(GL_DRAW_FRAMEBUFFER);
glBlitFramebuffer(0, 0, mViewportWidth, mViewportHeight, 0, 0, mViewportWidth, mViewportHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Pass 1: Alpha-blend the scene texture on a black background // Pass 1: Alpha-blend the scene texture on a black background
mBloomFramebuffers[0].Resize(BloomWidth, BloomHeight); mBloomFramebuffers[0].Resize(BloomWidth, BloomHeight);
mBloomFramebuffers[0].Bind(); mBloomFramebuffers[0].Bind();
@ -183,7 +188,7 @@ void CRenderer::RenderBloom()
CDrawUtil::UseTextureShader(); CDrawUtil::UseTextureShader();
glBlendFunc(GL_SRC_ALPHA, GL_ZERO); glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
mSceneFramebuffer.Texture()->Bind(0); mPostProcessFramebuffer.Texture()->Bind(0);
CDrawUtil::DrawSquare(); CDrawUtil::DrawSquare();
// Pass 2: Horizontal blur // Pass 2: Horizontal blur
@ -226,7 +231,7 @@ void CRenderer::RenderBloom()
} }
// Render result onto main scene framebuffer // Render result onto main scene framebuffer
mSceneFramebuffer.Bind(); mPostProcessFramebuffer.Bind();
glViewport(0, 0, mViewportWidth, mViewportHeight); glViewport(0, 0, mViewportWidth, mViewportHeight);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
@ -247,6 +252,11 @@ void CRenderer::RenderBloom()
CDrawUtil::DrawSquare(); CDrawUtil::DrawSquare();
} }
// Copy framebuffer back into the scene framebuffer for more rendering
mPostProcessFramebuffer.Bind(GL_READ_FRAMEBUFFER);
mSceneFramebuffer.Bind(GL_DRAW_FRAMEBUFFER);
glBlitFramebuffer(0, 0, mViewportWidth, mViewportHeight, 0, 0, mViewportWidth, mViewportHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Clean up // Clean up
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
} }
@ -310,6 +320,7 @@ void CRenderer::BeginFrame()
CGraphics::SetActiveContext(mContextIndex); CGraphics::SetActiveContext(mContextIndex);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mDefaultFramebuffer); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mDefaultFramebuffer);
mSceneFramebuffer.SetMultisamplingEnabled(true);
mSceneFramebuffer.Resize(mViewportWidth, mViewportHeight); mSceneFramebuffer.Resize(mViewportWidth, mViewportHeight);
mSceneFramebuffer.Bind(); mSceneFramebuffer.Bind();
@ -320,23 +331,11 @@ void CRenderer::BeginFrame()
void CRenderer::EndFrame() void CRenderer::EndFrame()
{ {
// Render result to screen // Copy result to the backbuffer
glBindFramebuffer(GL_FRAMEBUFFER, mDefaultFramebuffer); mSceneFramebuffer.Bind(GL_READ_FRAMEBUFFER);
InitFramebuffer(); CFramebuffer::BindDefaultFramebuffer(GL_DRAW_FRAMEBUFFER);
glViewport(0, 0, mViewportWidth, mViewportHeight); glViewport(0, 0, mViewportWidth, mViewportHeight);
glBlitFramebuffer(0, 0, mViewportWidth, mViewportHeight, 0, 0, mViewportWidth, mViewportHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
CGraphics::SetIdentityMVP();
CGraphics::UpdateMVPBlock();
glDisable(GL_DEPTH_TEST);
CDrawUtil::UseTextureShader();
glBlendFunc(GL_ONE, GL_ZERO);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
mSceneFramebuffer.Texture()->Bind(0);
CDrawUtil::DrawSquare();
glEnable(GL_DEPTH_TEST);
gDrawCount = 0; gDrawCount = 0;
} }

View File

@ -40,6 +40,7 @@ private:
float mBloomHScale, mBloomVScale; float mBloomHScale, mBloomVScale;
CFramebuffer mSceneFramebuffer; CFramebuffer mSceneFramebuffer;
CFramebuffer mPostProcessFramebuffer;
CFramebuffer mBloomFramebuffers[3]; CFramebuffer mBloomFramebuffers[3];
GLint mDefaultFramebuffer; GLint mDefaultFramebuffer;

View File

@ -8,6 +8,7 @@ CTexture::CTexture(CResourceEntry *pEntry /*= 0*/)
, mHeight(0) , mHeight(0)
, mNumMipMaps(0) , mNumMipMaps(0)
, mLinearSize(0) , mLinearSize(0)
, mEnableMultisampling(false)
, mBufferExists(false) , mBufferExists(false)
, mpImgDataBuffer(nullptr) , mpImgDataBuffer(nullptr)
, mImgDataSize(0) , mImgDataSize(0)
@ -22,6 +23,7 @@ CTexture::CTexture(u32 Width, u32 Height)
, mHeight((u16) Height) , mHeight((u16) Height)
, mNumMipMaps(1) , mNumMipMaps(1)
, mLinearSize(Width * Height * 4) , mLinearSize(Width * Height * 4)
, mEnableMultisampling(false)
, mBufferExists(false) , mBufferExists(false)
, mpImgDataBuffer(nullptr) , mpImgDataBuffer(nullptr)
, mImgDataSize(0) , mImgDataSize(0)
@ -36,8 +38,9 @@ CTexture::~CTexture()
bool CTexture::BufferGL() bool CTexture::BufferGL()
{ {
GLenum BindTarget = (mEnableMultisampling ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
glGenTextures(1, &mTextureID); glGenTextures(1, &mTextureID);
glBindTexture(GL_TEXTURE_2D, mTextureID); glBindTexture(BindTarget, mTextureID);
GLenum GLFormat, GLType; GLenum GLFormat, GLType;
bool IsCompressed = false; bool IsCompressed = false;
@ -81,9 +84,14 @@ bool CTexture::BufferGL()
GLvoid *pData = (mBufferExists) ? (mpImgDataBuffer + MipOffset) : NULL; GLvoid *pData = (mBufferExists) ? (mpImgDataBuffer + MipOffset) : NULL;
if (!IsCompressed) if (!IsCompressed)
glTexImage2D(GL_TEXTURE_2D, iMip, GLFormat, MipW, MipH, 0, GLFormat, GLType, pData); {
if (mEnableMultisampling)
glTexImage2DMultisample(BindTarget, 4, GLFormat, MipW, MipH, true);
else else
glCompressedTexImage2D(GL_TEXTURE_2D, iMip, GLFormat, MipW, MipH, 0, MipSize, pData); glTexImage2D(BindTarget, iMip, GLFormat, MipW, MipH, 0, GLFormat, GLType, pData);
}
else
glCompressedTexImage2D(BindTarget, iMip, GLFormat, MipW, MipH, 0, MipSize, pData);
MipW /= 2; MipW /= 2;
MipH /= 2; MipH /= 2;
@ -91,17 +99,17 @@ bool CTexture::BufferGL()
MipSize /= 4; MipSize /= 4;
} }
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(BindTarget, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mNumMipMaps - 1); glTexParameteri(BindTarget, GL_TEXTURE_MAX_LEVEL, mNumMipMaps - 1);
// Linear filtering on mipmaps: // Linear filtering on mipmaps:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(BindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(BindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// Anisotropic filtering: // Anisotropic filtering:
float MaxAnisotropy; float MaxAnisotropy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &MaxAnisotropy); glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &MaxAnisotropy);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, MaxAnisotropy); glTexParameterf(BindTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, MaxAnisotropy);
mGLBufferExists = true; mGLBufferExists = true;
return true; return true;
@ -114,7 +122,8 @@ void CTexture::Bind(u32 GLTextureUnit)
if (!mGLBufferExists) if (!mGLBufferExists)
BufferGL(); BufferGL();
glBindTexture(GL_TEXTURE_2D, mTextureID); GLenum BindTarget = (mEnableMultisampling ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
glBindTexture(BindTarget, mTextureID);
} }
void CTexture::Resize(u32 Width, u32 Height) void CTexture::Resize(u32 Width, u32 Height)
@ -323,13 +332,14 @@ void CTexture::CopyGLBuffer()
u32 MipW = mWidth, MipH = mHeight, MipOffset = 0; u32 MipW = mWidth, MipH = mHeight, MipOffset = 0;
float BytesPerPixel = FormatBPP(mTexelFormat) / 8.f; float BytesPerPixel = FormatBPP(mTexelFormat) / 8.f;
glBindTexture(GL_TEXTURE_2D, mTextureID); GLenum BindTarget = (mEnableMultisampling ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
glBindTexture(BindTarget, mTextureID);
for (u32 iMip = 0; iMip < mNumMipMaps; iMip++) for (u32 iMip = 0; iMip < mNumMipMaps; iMip++)
{ {
void *pData = mpImgDataBuffer + MipOffset; void *pData = mpImgDataBuffer + MipOffset;
glGetTexImage(GL_TEXTURE_2D, iMip, GL_RGBA, GL_UNSIGNED_BYTE, pData); glGetTexImage(BindTarget, iMip, GL_RGBA, GL_UNSIGNED_BYTE, pData);
MipOffset += (u32) (MipW * MipH * BytesPerPixel); MipOffset += (u32) (MipW * MipH * BytesPerPixel);
MipW /= 2; MipW /= 2;

View File

@ -21,6 +21,7 @@ class CTexture : public CResource
u32 mNumMipMaps; // The number of mipmaps this texture has u32 mNumMipMaps; // The number of mipmaps this texture has
u32 mLinearSize; // The size of the top level mipmap, in bytes u32 mLinearSize; // The size of the top level mipmap, in bytes
bool mEnableMultisampling; // Whether multisample should be enabled (if this texture is a render target).
bool mBufferExists; // Indicates whether image data buffer has valid data bool mBufferExists; // Indicates whether image data buffer has valid data
u8 *mpImgDataBuffer; // Pointer to image data buffer u8 *mpImgDataBuffer; // Pointer to image data buffer
u32 mImgDataSize; // Size of image data buffer u32 mImgDataSize; // Size of image data buffer
@ -39,7 +40,7 @@ public:
float ReadTexelAlpha(const CVector2f& rkTexCoord); float ReadTexelAlpha(const CVector2f& rkTexCoord);
bool WriteDDS(IOutputStream& rOut); bool WriteDDS(IOutputStream& rOut);
// Getters // Accessors
ETexelFormat TexelFormat() const { return mTexelFormat; } ETexelFormat TexelFormat() const { return mTexelFormat; }
ETexelFormat SourceTexelFormat() const { return mSourceTexelFormat; } ETexelFormat SourceTexelFormat() const { return mSourceTexelFormat; }
u32 Width() const { return (u32) mWidth; } u32 Width() const { return (u32) mWidth; }
@ -47,6 +48,14 @@ public:
u32 NumMipMaps() const { return mNumMipMaps; } u32 NumMipMaps() const { return mNumMipMaps; }
GLuint TextureID() const { return mTextureID; } GLuint TextureID() const { return mTextureID; }
inline void SetMultisamplingEnabled(bool Enable)
{
if (mEnableMultisampling != Enable)
DeleteBuffers();
mEnableMultisampling = Enable;
}
// Static // Static
static u32 FormatBPP(ETexelFormat Format); static u32 FormatBPP(ETexelFormat Format);

View File

@ -32,12 +32,13 @@ void CBasicViewport::initializeGL()
CGraphics::Initialize(); CGraphics::Initialize();
// Setting various GL flags // Setting various GL flags
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(0xFFFF);
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_FILL);
glEnable(GL_MULTISAMPLE);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(0xFFFF);
glPolygonOffset(1.f, 5.f); glPolygonOffset(1.f, 5.f);
glDepthFunc(GL_LEQUAL);
// Clear cached material // Clear cached material
CMaterial::KillCachedMaterial(); CMaterial::KillCachedMaterial();