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

View File

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

View File

@ -8,20 +8,23 @@ class CRenderbuffer
{
GLuint mRenderbuffer;
u32 mWidth, mHeight;
bool mEnableMultisampling;
bool mInitialized;
public:
CRenderbuffer::CRenderbuffer()
: mInitialized(false)
, mWidth(0)
: mWidth(0)
, mHeight(0)
, mEnableMultisampling(false)
, mInitialized(false)
{
}
CRenderbuffer::CRenderbuffer(u32 Width, u32 Height)
: mInitialized(false)
, mWidth(Width)
: mWidth(Width)
, mHeight(Height)
, mEnableMultisampling(false)
, mInitialized(false)
{
}
@ -33,10 +36,9 @@ public:
void CRenderbuffer::Init()
{
glGenRenderbuffers(1, &mRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
mInitialized = true;
glGenRenderbuffers(1, &mRenderbuffer);
InitStorage();
}
inline void CRenderbuffer::Resize(u32 Width, u32 Height)
@ -45,10 +47,7 @@ public:
mHeight = Height;
if (mInitialized)
{
Bind();
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
}
InitStorage();
}
inline void CRenderbuffer::Bind()
@ -66,6 +65,26 @@ public:
{
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

View File

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

View File

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

View File

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

View File

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

View File

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