Save MSAA images. Fixes #101.

This commit is contained in:
Leonardo 2017-12-26 10:19:20 -08:00
parent dac8708bb6
commit 804e0f6f53
8 changed files with 138 additions and 71 deletions

View file

@ -32,7 +32,8 @@ lcContext::lcContext()
mTexCoordEnabled = false;
mColorEnabled = false;
mTexture = 0;
mTexture2D = 0;
mTexture2DMS = 0;
mLineWidth = 1.0f;
#ifndef LC_OPENGLES
mMatrixMode = GL_MODELVIEW;
@ -40,7 +41,9 @@ lcContext::lcContext()
#endif
mFramebufferObject = 0;
mFramebufferObjectMS = 0;
mFramebufferTexture = 0;
mFramebufferTextureMS = 0;
mDepthRenderbufferObject = 0;
mColor = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
@ -389,7 +392,9 @@ void lcContext::SetDefaultState()
mVertexBufferOffset = (char*)~0;
glBindTexture(GL_TEXTURE_2D, 0);
mTexture = 0;
mTexture2D = 0;
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
mTexture2DMS = 0;
glLineWidth(1.0f);
mLineWidth = 1.0f;
@ -416,7 +421,8 @@ void lcContext::ClearResources()
{
ClearVertexBuffer();
ClearIndexBuffer();
BindTexture(0);
BindTexture2D(0);
BindTexture2DMS(0);
}
void lcContext::SetMaterial(lcMaterialType MaterialType)
@ -498,13 +504,22 @@ void lcContext::SetSmoothShading(bool Smooth)
#endif
}
void lcContext::BindTexture(GLuint Texture)
void lcContext::BindTexture2D(GLuint Texture)
{
if (mTexture == Texture)
if (mTexture2D == Texture)
return;
glBindTexture(GL_TEXTURE_2D, Texture);
mTexture = Texture;
mTexture2D = Texture;
}
void lcContext::BindTexture2DMS(GLuint Texture)
{
if (mTexture2DMS == Texture)
return;
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, Texture);
mTexture2DMS = Texture;
}
void lcContext::SetColor(float Red, float Green, float Blue, float Alpha)
@ -536,25 +551,49 @@ bool lcContext::BeginRenderToTexture(int Width, int Height)
{
if (gSupportsFramebufferObjectARB)
{
int Samples = gSupportsTexImage2DMultisample ? QGLFormat::defaultFormat().samples() : 1;
glGenFramebuffers(1, &mFramebufferObject);
glGenTextures(1, &mFramebufferTexture);
glGenRenderbuffers(1, &mDepthRenderbufferObject);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferObject);
BindTexture(mFramebufferTexture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFramebufferTexture, 0);
glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferObject);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, Width, Height);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbufferObject);
BindTexture(0);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferObject);
if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
glGenTextures(1, &mFramebufferTexture);
BindTexture2D(mFramebufferTexture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
BindTexture2D(0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFramebufferTexture, 0);
glGenRenderbuffers(1, &mDepthRenderbufferObject);
if (Samples == 1)
{
glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferObject);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, Width, Height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbufferObject);
}
else
{
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
EndRenderToTexture();
return false;
}
glGenFramebuffers(1, &mFramebufferObjectMS);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferObjectMS);
glGenTextures(1, &mFramebufferTextureMS);
BindTexture2DMS(mFramebufferTextureMS);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Samples, GL_RGBA, Width, Height, GL_TRUE);
BindTexture2DMS(0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, mFramebufferTextureMS, 0);
glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferObject);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, Samples, GL_DEPTH_COMPONENT24, Width, Height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbufferObject);
}
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
EndRenderToTexture();
return false;
@ -569,7 +608,7 @@ bool lcContext::BeginRenderToTexture(int Width, int Height)
glGenFramebuffersEXT(1, &mFramebufferObject);
glGenTextures(1, &mFramebufferTexture);
BindTexture(mFramebufferTexture);
BindTexture2D(mFramebufferTexture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
@ -584,7 +623,7 @@ bool lcContext::BeginRenderToTexture(int Width, int Height)
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepthRenderbufferObject);
BindTexture(0);
BindTexture2D(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebufferObject);
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
@ -608,6 +647,10 @@ void lcContext::EndRenderToTexture()
mFramebufferObject = 0;
glDeleteTextures(1, &mFramebufferTexture);
mFramebufferTexture = 0;
glDeleteFramebuffers(1, &mFramebufferObjectMS);
mFramebufferObjectMS = 0;
glDeleteTextures(1, &mFramebufferTextureMS);
mFramebufferTextureMS = 0;
glDeleteRenderbuffers(1, &mDepthRenderbufferObject);
mDepthRenderbufferObject = 0;
@ -630,11 +673,30 @@ void lcContext::EndRenderToTexture()
QImage lcContext::GetRenderToTextureImage(int Width, int Height)
{
QImage Image(Width, Height, QImage::Format_ARGB32);
quint8* Buffer = Image.bits();
GetRenderToTextureImage(Width, Height, Image.bits());
return Image;
}
void lcContext::GetRenderToTextureImage(int Width, int Height, quint8* Buffer)
{
if (mFramebufferTextureMS)
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferObjectMS);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferObject);
glBlitFrameBuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferObject);
}
glFinish();
glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Buffer);
if (mFramebufferTextureMS)
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferObjectMS);
for (int y = 0; y < (Height + 1) / 2; y++)
{
quint8* Top = Buffer + ((Height - y - 1) * Width * 4);
@ -642,27 +704,16 @@ QImage lcContext::GetRenderToTextureImage(int Width, int Height)
for (int x = 0; x < Width; x++)
{
quint8 Red = Top[0];
quint8 Green = Top[1];
quint8 Blue = Top[2];
quint8 Alpha = Top[3];
QRgb TopColor = qRgba(Top[0], Top[1], Top[2], Top[3]);
QRgb BottomColor = qRgba(Bottom[0], Bottom[1], Bottom[2], Bottom[3]);
Top[0] = Bottom[2];
Top[1] = Bottom[1];
Top[2] = Bottom[0];
Top[3] = Bottom[3];
Bottom[0] = Blue;
Bottom[1] = Green;
Bottom[2] = Red;
Bottom[3] = Alpha;
*(QRgb*)Top = BottomColor;
*(QRgb*)Bottom = TopColor;
Top += 4;
Bottom += 4;
}
}
return Image;
}
bool lcContext::SaveRenderToTextureImage(const QString& FileName, int Width, int Height)

View file

@ -115,7 +115,8 @@ public:
void SetViewport(int x, int y, int Width, int Height);
void SetLineWidth(float LineWidth);
void SetSmoothShading(bool Smooth);
void BindTexture(GLuint Texture);
void BindTexture2D(GLuint Texture);
void BindTexture2DMS(GLuint Texture);
void SetColor(const lcVector4& Color)
{
@ -132,6 +133,7 @@ public:
bool BeginRenderToTexture(int Width, int Height);
void EndRenderToTexture();
QImage GetRenderToTextureImage(int Width, int Height);
void GetRenderToTextureImage(int Width, int Height, quint8* Buffer);
bool SaveRenderToTextureImage(const QString& FileName, int Width, int Height);
lcVertexBuffer CreateVertexBuffer(int Size, const void* Data);
@ -169,7 +171,8 @@ protected:
bool mTexCoordEnabled;
bool mColorEnabled;
GLuint mTexture;
GLuint mTexture2D;
GLuint mTexture2DMS;
float mLineWidth;
int mMatrixMode;
bool mTextureEnabled;
@ -187,6 +190,8 @@ protected:
GLuint mFramebufferObject;
GLuint mFramebufferTexture;
GLuint mFramebufferObjectMS;
GLuint mFramebufferTextureMS;
GLuint mDepthRenderbufferObject;
static lcProgram mPrograms[LC_NUM_MATERIALS];

View file

@ -5,6 +5,7 @@ bool gSupportsShaderObjects;
bool gSupportsVertexBufferObject;
bool gSupportsFramebufferObjectARB;
bool gSupportsFramebufferObjectEXT;
bool gSupportsTexImage2DMultisample;
bool gSupportsAnisotropic;
GLfloat gMaxAnisotropy;
@ -114,6 +115,9 @@ PFNGLUNIFORMMATRIX4FVPROC lcUniformMatrix4fv;
PFNGLVALIDATEPROGRAMPROC lcValidateProgram;
PFNGLVERTEXATTRIBPOINTERPROC lcVertexAttribPointer;
PFNGLTEXIMAGE2DMULTISAMPLEPROC lcTexImage2DMultisample;
PFNGLBLITFRAMEBUFFERPROC lcBlitFrameBuffer;
#endif
static bool lcIsGLExtensionSupported(const GLubyte* Extensions, const char* Name)
@ -331,7 +335,15 @@ void lcInitializeGLExtensions(const QGLContext* Context)
#endif
gSupportsShaderObjects = true;
}
if (VersionMajor > 3 || (VersionMajor == 3 && VersionMinor >= 2))
{
lcTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)Context->getProcAddress("glTexImage2DMultisample");
lcBlitFrameBuffer = (PFNGLBLITFRAMEBUFFERPROC)Context->getProcAddress("glBlitFramebuffer");
gSupportsTexImage2DMultisample = true;
}
#ifdef LC_OPENGLES
gSupportsVertexBufferObject = true;
gSupportsFramebufferObjectARB = true;

View file

@ -6,6 +6,7 @@ extern bool gSupportsShaderObjects;
extern bool gSupportsVertexBufferObject;
extern bool gSupportsFramebufferObjectARB;
extern bool gSupportsFramebufferObjectEXT;
extern bool gSupportsTexImage2DMultisample;
extern bool gSupportsAnisotropic;
extern GLfloat gMaxAnisotropy;
@ -119,6 +120,9 @@ extern PFNGLUNIFORMMATRIX4FVPROC lcUniformMatrix4fv;
extern PFNGLVALIDATEPROGRAMPROC lcValidateProgram;
extern PFNGLVERTEXATTRIBPOINTERPROC lcVertexAttribPointer;
extern PFNGLTEXIMAGE2DMULTISAMPLEPROC lcTexImage2DMultisample;
extern PFNGLBLITFRAMEBUFFERPROC lcBlitFrameBuffer;
#define glBindBuffer lcBindBufferARB
#define glDeleteBuffers lcDeleteBuffersARB
#define glGenBuffers lcGenBuffersARB
@ -223,5 +227,7 @@ extern PFNGLVERTEXATTRIBPOINTERPROC lcVertexAttribPointer;
#define glValidateProgram lcValidateProgram
#define glVertexAttribPointer lcVertexAttribPointer
#endif
#define glTexImage2DMultisample lcTexImage2DMultisample
#define glBlitFrameBuffer lcBlitFrameBuffer
#endif

View file

@ -1278,7 +1278,7 @@ void lcModel::DrawBackground(lcGLWidget* Widget)
}
else if (mProperties.mBackgroundType == LC_BACKGROUND_IMAGE)
{
Context->BindTexture(mBackgroundTexture->mTexture);
Context->BindTexture2D(mBackgroundTexture->mTexture);
float TileWidth = 1.0f, TileHeight = 1.0f;

View file

@ -187,7 +187,7 @@ void lcScene::DrawRenderMeshes(lcContext* Context, int PrimitiveTypes, bool Enab
{
VertexBufferOffset += Mesh->mNumVertices * sizeof(lcVertex);
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 2, 0, EnableNormals);
Context->BindTexture(Texture->mTexture);
Context->BindTexture2D(Texture->mTexture);
}
GLenum DrawPrimitiveType = Section->PrimitiveType & (LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES) ? GL_TRIANGLES : GL_LINES;
@ -231,7 +231,7 @@ void lcScene::Draw(lcContext* Context) const
if (ShadingMode == LC_SHADING_WIREFRAME)
{
Context->BindTexture(0);
Context->BindTexture2D(0);
Context->SetMaterial(LC_MATERIAL_UNLIT_COLOR);
@ -248,13 +248,13 @@ void lcScene::Draw(lcContext* Context) const
DrawRenderMeshes(Context, LC_MESH_TEXTURED_LINES, false, false, false);
Context->BindTexture(0);
Context->BindTexture2D(0);
}
}
else if (ShadingMode == LC_SHADING_FLAT)
{
bool DrawLines = lcGetPreferences().mDrawEdgeLines;
Context->BindTexture(0);
Context->BindTexture2D(0);
Context->SetMaterial(LC_MATERIAL_UNLIT_COLOR);
@ -301,13 +301,13 @@ void lcScene::Draw(lcContext* Context) const
glDisable(GL_BLEND);
}
Context->BindTexture(0);
Context->BindTexture2D(0);
}
}
else
{
bool DrawLines = lcGetPreferences().mDrawEdgeLines;
Context->BindTexture(0);
Context->BindTexture2D(0);
if (DrawLines)
{
@ -356,7 +356,7 @@ void lcScene::Draw(lcContext* Context) const
glDisable(GL_BLEND);
}
Context->BindTexture(0);
Context->BindTexture2D(0);
}
}
}

View file

@ -112,7 +112,7 @@ bool TexFont::Load(lcContext* Context)
mFontHeight = 16;
glGenTextures(1, &mTexture);
Context->BindTexture(mTexture);
Context->BindTexture2D(mTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

View file

@ -728,29 +728,22 @@ void View::OnDraw()
quint8* Buffer = (quint8*)malloc(mWidth * mHeight * 4);
uchar* ImageBuffer = mRenderImage.bits();
glFinish();
glReadPixels(0, 0, CurrentTileWidth, CurrentTileHeight, GL_RGBA, GL_UNSIGNED_BYTE, Buffer);
mContext->GetRenderToTextureImage(mWidth, mHeight, Buffer);
quint32 TileY = 0;
quint32 TileY = 0, SrcY = 0;
if (CurrentTileRow != TotalTileRows - 1)
TileY = (TotalTileRows - CurrentTileRow - 1) * mHeight - (mHeight - mRenderImage.height() % mHeight);
else
SrcY = mHeight - mRenderImage.height() % mHeight;
qDebug() << SrcY << TileY;
quint32 TileStart = ((CurrentTileColumn * mWidth) + (TileY * mRenderImage.width())) * 4;
for (int y = 0; y < CurrentTileHeight; y++)
{
quint8* src = Buffer + (CurrentTileHeight - y - 1) * CurrentTileWidth * 4;
quint8* src = Buffer + (SrcY + y) * CurrentTileWidth * 4;
quint8* dst = ImageBuffer + TileStart + y * mRenderImage.width() * 4;
for (int x = 0; x < CurrentTileWidth; x++)
{
*dst++ = src[2];
*dst++ = src[1];
*dst++ = src[0];
*dst++ = src[3];
src += 4;
}
memcpy(dst, src, CurrentTileWidth * 4);
}
free(Buffer);
@ -1251,7 +1244,7 @@ void View::DrawRotateOverlay()
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f));
mContext->BindTexture(gTexFont.GetTexture());
mContext->BindTexture2D(gTexFont.GetTexture());
glEnable(GL_BLEND);
char buf[32];
@ -1565,7 +1558,7 @@ void View::DrawGrid()
if (Preferences.mDrawGridStuds)
{
mContext->BindTexture(gGridTexture->mTexture);
mContext->BindTexture2D(gGridTexture->mTexture);
glEnable(GL_BLEND);
mContext->SetMaterial(LC_MATERIAL_UNLIT_TEXTURE_MODULATE);
@ -1640,7 +1633,7 @@ void View::DrawAxes()
mContext->SetMaterial(LC_MATERIAL_UNLIT_TEXTURE_MODULATE);
mContext->SetViewMatrix(TranslationMatrix);
mContext->BindTexture(gTexFont.GetTexture());
mContext->BindTexture2D(gTexFont.GetTexture());
glEnable(GL_BLEND);
float TextBuffer[6 * 5 * 3];
@ -1686,7 +1679,7 @@ void View::DrawViewport()
{
mContext->SetMaterial(LC_MATERIAL_UNLIT_TEXTURE_MODULATE);
mContext->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
mContext->BindTexture(gTexFont.GetTexture());
mContext->BindTexture2D(gTexFont.GetTexture());
glEnable(GL_BLEND);