mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-20 23:23:47 +00:00
Update GFXTextureManager and GBitmap
GBitmap Changes: Added all other formats to gbitmap that we support gbitmap now supports cubemaps added converters for all these other formats added stb_image_resize for extrudemips so we can extrude mipmaps for all other formats GFXTextureManager Can now directly make cubemaps and texture arrays based on the GFXTextureProfile API implementations for all functions that cubemaps and arrays needed
This commit is contained in:
parent
975fc924cc
commit
3aef90a6bc
66 changed files with 4235 additions and 2590 deletions
|
|
@ -38,9 +38,9 @@ public:
|
|||
mipLevel(_mipLevel), zOffset(_zOffset)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~_GFXGLTargetDesc() {}
|
||||
|
||||
|
||||
virtual U32 getHandle() = 0;
|
||||
virtual U32 getWidth() = 0;
|
||||
virtual U32 getHeight() = 0;
|
||||
|
|
@ -49,10 +49,10 @@ public:
|
|||
virtual GLenum getBinding() = 0;
|
||||
virtual GFXFormat getFormat() = 0;
|
||||
virtual bool isCompatible(const GFXGLTextureObject* tex) = 0;
|
||||
|
||||
|
||||
U32 getMipLevel() { return mipLevel; }
|
||||
U32 getZOffset() { return zOffset; }
|
||||
|
||||
|
||||
private:
|
||||
U32 mipLevel;
|
||||
U32 zOffset;
|
||||
|
|
@ -62,19 +62,21 @@ private:
|
|||
class _GFXGLTextureTargetDesc : public _GFXGLTargetDesc
|
||||
{
|
||||
public:
|
||||
_GFXGLTextureTargetDesc(GFXGLTextureObject* tex, U32 _mipLevel, U32 _zOffset)
|
||||
: _GFXGLTargetDesc(_mipLevel, _zOffset), mTex(tex)
|
||||
|
||||
_GFXGLTextureTargetDesc(GFXGLTextureObject* tex, U32 _mipLevel, U32 _zOffset, U32 _face = 0, bool isCube = false)
|
||||
: _GFXGLTargetDesc(_mipLevel, _zOffset), mTex(tex), mFace(_face), mIsCube(isCube)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~_GFXGLTextureTargetDesc() {}
|
||||
|
||||
|
||||
U32 getHandle() override { return mTex->getHandle(); }
|
||||
U32 getWidth() override { return mTex->getWidth(); }
|
||||
U32 getHeight() override { return mTex->getHeight(); }
|
||||
U32 getDepth() override { return mTex->getDepth(); }
|
||||
U32 getFace() { return mFace; }
|
||||
bool hasMips() override { return mTex->mMipLevels != 1; }
|
||||
GLenum getBinding() override { return mTex->getBinding(); }
|
||||
GLenum getBinding() override { return mIsCube ? GFXGLFaceType[mFace] : mTex->getBinding(); }
|
||||
GFXFormat getFormat() override { return mTex->getFormat(); }
|
||||
bool isCompatible(const GFXGLTextureObject* tex) override
|
||||
{
|
||||
|
|
@ -82,40 +84,12 @@ public:
|
|||
&& mTex->getWidth() == tex->getWidth()
|
||||
&& mTex->getHeight() == tex->getHeight();
|
||||
}
|
||||
GFXGLTextureObject* getTextureObject() const {return mTex; }
|
||||
|
||||
GFXGLTextureObject* getTextureObject() const { return mTex; }
|
||||
|
||||
private:
|
||||
StrongRefPtr<GFXGLTextureObject> mTex;
|
||||
};
|
||||
|
||||
/// Internal struct used to track Cubemap texture information for FBO attachment
|
||||
class _GFXGLCubemapTargetDesc : public _GFXGLTargetDesc
|
||||
{
|
||||
public:
|
||||
_GFXGLCubemapTargetDesc(GFXGLCubemap* tex, U32 _face, U32 _mipLevel, U32 _zOffset)
|
||||
: _GFXGLTargetDesc(_mipLevel, _zOffset), mTex(tex), mFace(_face)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~_GFXGLCubemapTargetDesc() {}
|
||||
|
||||
U32 getHandle() override { return mTex->getHandle(); }
|
||||
U32 getWidth() override { return mTex->getWidth(); }
|
||||
U32 getHeight() override { return mTex->getHeight(); }
|
||||
U32 getDepth() override { return 0; }
|
||||
bool hasMips() override { return mTex->getMipMapLevels() != 1; }
|
||||
GLenum getBinding() override { return GFXGLCubemap::getEnumForFaceNumber(mFace); }
|
||||
GFXFormat getFormat() override { return mTex->getFormat(); }
|
||||
bool isCompatible(const GFXGLTextureObject* tex) override
|
||||
{
|
||||
return mTex->getFormat() == tex->getFormat()
|
||||
&& mTex->getWidth() == tex->getWidth()
|
||||
&& mTex->getHeight() == tex->getHeight();
|
||||
}
|
||||
|
||||
private:
|
||||
StrongRefPtr<GFXGLCubemap> mTex;
|
||||
U32 mFace;
|
||||
bool mIsCube;
|
||||
};
|
||||
|
||||
// Internal implementations
|
||||
|
|
@ -123,9 +97,9 @@ class _GFXGLTextureTargetImpl // TODO OPENGL remove and implement on GFXGLTextur
|
|||
{
|
||||
public:
|
||||
GFXGLTextureTarget* mTarget;
|
||||
|
||||
|
||||
virtual ~_GFXGLTextureTargetImpl() {}
|
||||
|
||||
|
||||
virtual void applyState() = 0;
|
||||
virtual void makeActive() = 0;
|
||||
virtual void finish() = 0;
|
||||
|
|
@ -137,10 +111,10 @@ class _GFXGLTextureTargetFBOImpl : public _GFXGLTextureTargetImpl
|
|||
public:
|
||||
GLuint mFramebuffer;
|
||||
bool mGenMips;
|
||||
|
||||
|
||||
_GFXGLTextureTargetFBOImpl(GFXGLTextureTarget* target);
|
||||
virtual ~_GFXGLTextureTargetFBOImpl();
|
||||
|
||||
|
||||
void applyState() override;
|
||||
void makeActive() override;
|
||||
void finish() override;
|
||||
|
|
@ -159,42 +133,42 @@ _GFXGLTextureTargetFBOImpl::~_GFXGLTextureTargetFBOImpl()
|
|||
}
|
||||
|
||||
void _GFXGLTextureTargetFBOImpl::applyState()
|
||||
{
|
||||
{
|
||||
// REMINDER: When we implement MRT support, check against GFXGLDevice::getNumRenderTargets()
|
||||
|
||||
|
||||
PRESERVE_FRAMEBUFFER();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
bool drawbufs[16];
|
||||
int bufsize = 0;
|
||||
for (int i = 0; i < 16; i++)
|
||||
drawbufs[i] = false;
|
||||
drawbufs[i] = false;
|
||||
bool hasColor = false;
|
||||
for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ));
|
||||
if(color)
|
||||
for (int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc(static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0 + i));
|
||||
if (color)
|
||||
{
|
||||
hasColor = true;
|
||||
const GLenum binding = color->getBinding();
|
||||
if( binding == GL_TEXTURE_2D || (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) )
|
||||
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ) );
|
||||
else if( binding == GL_TEXTURE_1D )
|
||||
glFramebufferTexture1D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ) );
|
||||
else if( binding == GL_TEXTURE_3D )
|
||||
glFramebufferTexture3D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ), color->getZOffset( ) );
|
||||
if (binding == GL_TEXTURE_2D || (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding(), color->getHandle(), color->getMipLevel());
|
||||
else if (binding == GL_TEXTURE_1D)
|
||||
glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding(), color->getHandle(), color->getMipLevel());
|
||||
else if (binding == GL_TEXTURE_3D)
|
||||
glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding(), color->getHandle(), color->getMipLevel(), color->getZOffset());
|
||||
else
|
||||
Con::errorf("_GFXGLTextureTargetFBOImpl::applyState - Bad binding");
|
||||
Con::errorf("_GFXGLTextureTargetFBOImpl::applyState - Bad binding");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clears the texture (note that the binding is irrelevent)
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, 0, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_GFXGLTargetDesc* depthStecil = mTarget->getTargetDesc(GFXTextureTarget::DepthStencil);
|
||||
if(depthStecil)
|
||||
if (depthStecil)
|
||||
{
|
||||
// Certain drivers have issues with depth only FBOs. That and the next two asserts assume we have a color target.
|
||||
AssertFatal(hasColor, "GFXGLTextureTarget::applyState() - Cannot set DepthStencil target without Color0 target!");
|
||||
|
|
@ -206,40 +180,40 @@ void _GFXGLTextureTargetFBOImpl::applyState()
|
|||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
|
||||
GLenum *buf = new GLenum[bufsize];
|
||||
GLenum* buf = new GLenum[bufsize];
|
||||
int count = 0;
|
||||
for (int i = 0; i < bufsize; i++)
|
||||
{
|
||||
if (drawbufs[i])
|
||||
{
|
||||
buf[count] = GL_COLOR_ATTACHMENT0 + i;
|
||||
count++;
|
||||
}
|
||||
if (drawbufs[i])
|
||||
{
|
||||
buf[count] = GL_COLOR_ATTACHMENT0 + i;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
glDrawBuffers(bufsize, buf);
|
||||
|
||||
|
||||
delete[] buf;
|
||||
CHECK_FRAMEBUFFER_STATUS();
|
||||
}
|
||||
|
||||
void _GFXGLTextureTargetFBOImpl::makeActive()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mFramebuffer);
|
||||
|
||||
int i = 0;
|
||||
GLenum draws[16];
|
||||
for( i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ));
|
||||
if(color)
|
||||
draws[i] = GL_COLOR_ATTACHMENT0 + i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
int i = 0;
|
||||
GLenum draws[16];
|
||||
for (i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc(static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0 + i));
|
||||
if (color)
|
||||
draws[i] = GL_COLOR_ATTACHMENT0 + i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
glDrawBuffers( i, draws );
|
||||
glDrawBuffers(i, draws);
|
||||
}
|
||||
|
||||
void _GFXGLTextureTargetFBOImpl::finish()
|
||||
|
|
@ -250,20 +224,20 @@ void _GFXGLTextureTargetFBOImpl::finish()
|
|||
if (!mGenMips)
|
||||
return;
|
||||
|
||||
for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ) );
|
||||
if(!color || !(color->hasMips()))
|
||||
for (int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
|
||||
{
|
||||
_GFXGLTargetDesc* color = mTarget->getTargetDesc(static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0 + i));
|
||||
if (!color || !(color->hasMips()))
|
||||
continue;
|
||||
|
||||
|
||||
// Generate mips if necessary
|
||||
// Assumes a 2D texture.
|
||||
GLenum binding = color->getBinding();
|
||||
binding = (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ? GL_TEXTURE_CUBE_MAP : binding;
|
||||
|
||||
PRESERVE_TEXTURE( binding );
|
||||
glBindTexture( binding, color->getHandle() );
|
||||
glGenerateMipmap( binding );
|
||||
PRESERVE_TEXTURE(binding);
|
||||
glBindTexture(binding, color->getHandle());
|
||||
glGenerateMipmap(binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,13 +245,13 @@ void _GFXGLTextureTargetFBOImpl::finish()
|
|||
GFXGLTextureTarget::GFXGLTextureTarget(bool genMips) : mCopyFboSrc(0), mCopyFboDst(0)
|
||||
{
|
||||
mGenMips = genMips;
|
||||
for(U32 i=0; i<MaxRenderSlotId; i++)
|
||||
for (U32 i = 0; i < MaxRenderSlotId; i++)
|
||||
mTargets[i] = NULL;
|
||||
|
||||
GFXTextureManager::addEventDelegate( this, &GFXGLTextureTarget::_onTextureEvent );
|
||||
|
||||
GFXTextureManager::addEventDelegate(this, &GFXGLTextureTarget::_onTextureEvent);
|
||||
|
||||
_impl = new _GFXGLTextureTargetFBOImpl(this);
|
||||
|
||||
|
||||
glGenFramebuffers(1, &mCopyFboSrc);
|
||||
glGenFramebuffers(1, &mCopyFboDst);
|
||||
}
|
||||
|
|
@ -292,7 +266,7 @@ GFXGLTextureTarget::~GFXGLTextureTarget()
|
|||
|
||||
const Point2I GFXGLTextureTarget::getSize()
|
||||
{
|
||||
if(mTargets[Color0].isValid())
|
||||
if (mTargets[Color0].isValid())
|
||||
return Point2I(mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight());
|
||||
|
||||
return Point2I(0, 0);
|
||||
|
|
@ -300,61 +274,50 @@ const Point2I GFXGLTextureTarget::getSize()
|
|||
|
||||
GFXFormat GFXGLTextureTarget::getFormat()
|
||||
{
|
||||
if(mTargets[Color0].isValid())
|
||||
if (mTargets[Color0].isValid())
|
||||
return mTargets[Color0]->getFormat();
|
||||
|
||||
return GFXFormatR8G8B8A8;
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/ )
|
||||
void GFXGLTextureTarget::attachTexture(RenderSlot slot, GFXTextureObject* tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/, U32 face /*= 0*/)
|
||||
{
|
||||
if( tex == GFXTextureTarget::sDefaultDepthStencil )
|
||||
if (tex == GFXTextureTarget::sDefaultDepthStencil)
|
||||
tex = GFXGL->getDefaultDepthTex();
|
||||
|
||||
// are we readding the same thing, face and all?
|
||||
_GFXGLTextureTargetDesc* mTex = static_cast<_GFXGLTextureTargetDesc*>(mTargets[slot].ptr());
|
||||
if( (!tex && !mTex) || (mTex && mTex->getTextureObject() == tex) )
|
||||
if ((!tex && !mTex) || (mTex && mTex->getTextureObject() == tex && mTex->getFace() == face))
|
||||
return;
|
||||
|
||||
|
||||
// Triggers an update when we next render
|
||||
invalidateState();
|
||||
|
||||
// We stash the texture and info into an internal struct.
|
||||
GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(tex);
|
||||
if(tex && tex != GFXTextureTarget::sDefaultDepthStencil)
|
||||
mTargets[slot] = new _GFXGLTextureTargetDesc(glTexture, mipLevel, zOffset);
|
||||
if (tex && tex != GFXTextureTarget::sDefaultDepthStencil)
|
||||
{
|
||||
mTargets[slot] = new _GFXGLTextureTargetDesc(glTexture, mipLevel, zOffset, face, glTexture->isCubeMap());
|
||||
}
|
||||
else
|
||||
mTargets[slot] = NULL;
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel/*=0*/ )
|
||||
void GFXGLTextureTarget::attachTexture(RenderSlot slot, GFXCubemap* tex, U32 face, U32 mipLevel/*=0*/)
|
||||
{
|
||||
// No depth cubemaps, sorry
|
||||
AssertFatal(slot != DepthStencil, "GFXGLTextureTarget::attachTexture (cube) - Cube depth textures not supported!");
|
||||
if(slot == DepthStencil)
|
||||
return;
|
||||
|
||||
// Triggers an update when we next render
|
||||
invalidateState();
|
||||
|
||||
// We stash the texture and info into an internal struct.
|
||||
GFXGLCubemap* glTexture = static_cast<GFXGLCubemap*>(tex);
|
||||
if(tex)
|
||||
mTargets[slot] = new _GFXGLCubemapTargetDesc(glTexture, face, mipLevel, 0);
|
||||
else
|
||||
mTargets[slot] = NULL;
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::clearAttachments()
|
||||
{
|
||||
deactivate();
|
||||
for(S32 i=1; i<MaxRenderSlotId; i++)
|
||||
for (S32 i = 1; i < MaxRenderSlotId; i++)
|
||||
attachTexture((RenderSlot)i, NULL);
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::zombify()
|
||||
{
|
||||
invalidateState();
|
||||
|
||||
|
||||
// Will be recreated in applyState
|
||||
_impl = NULL;
|
||||
}
|
||||
|
|
@ -376,15 +339,15 @@ void GFXGLTextureTarget::deactivate()
|
|||
|
||||
void GFXGLTextureTarget::applyState()
|
||||
{
|
||||
if(!isPendingState())
|
||||
if (!isPendingState())
|
||||
return;
|
||||
|
||||
// So we don't do this over and over again
|
||||
stateApplied();
|
||||
|
||||
if(_impl.isNull())
|
||||
|
||||
if (_impl.isNull())
|
||||
_impl = new _GFXGLTextureTargetFBOImpl(this);
|
||||
|
||||
|
||||
_impl->applyState();
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +357,7 @@ _GFXGLTargetDesc* GFXGLTextureTarget::getTargetDesc(RenderSlot slot) const
|
|||
return mTargets[slot].ptr();
|
||||
}
|
||||
|
||||
void GFXGLTextureTarget::_onTextureEvent( GFXTexCallbackCode code )
|
||||
void GFXGLTextureTarget::_onTextureEvent(GFXTexCallbackCode code)
|
||||
{
|
||||
invalidateState();
|
||||
}
|
||||
|
|
@ -403,7 +366,7 @@ const String GFXGLTextureTarget::describeSelf() const
|
|||
{
|
||||
String ret = String::ToString(" Color0 Attachment: %i", mTargets[Color0].isValid() ? mTargets[Color0]->getHandle() : 0);
|
||||
ret += String::ToString(" Depth Attachment: %i", mTargets[DepthStencil].isValid() ? mTargets[DepthStencil]->getHandle() : 0);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -416,27 +379,27 @@ void GFXGLTextureTarget::resolveTo(GFXTextureObject* obj)
|
|||
AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
|
||||
GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);
|
||||
|
||||
if( GFXGL->mCapabilities.copyImage && mTargets[Color0]->isCompatible(glTexture) )
|
||||
if (GFXGL->mCapabilities.copyImage && mTargets[Color0]->isCompatible(glTexture))
|
||||
{
|
||||
GLenum binding = mTargets[Color0]->getBinding();
|
||||
GLenum binding = mTargets[Color0]->getBinding();
|
||||
binding = (binding >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && binding <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ? GL_TEXTURE_CUBE_MAP : binding;
|
||||
U32 srcStartDepth = binding == GL_TEXTURE_CUBE_MAP ? mTargets[Color0]->getBinding() - GL_TEXTURE_CUBE_MAP_POSITIVE_X : 0;
|
||||
glCopyImageSubData(
|
||||
mTargets[Color0]->getHandle(), binding, 0, 0, 0, srcStartDepth,
|
||||
glTexture->getHandle(), glTexture->getBinding(), 0, 0, 0, 0,
|
||||
mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(), 1);
|
||||
mTargets[Color0]->getHandle(), binding, 0, 0, 0, srcStartDepth,
|
||||
glTexture->getHandle(), glTexture->getBinding(), 0, 0, 0, 0,
|
||||
mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(), 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PRESERVE_FRAMEBUFFER();
|
||||
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mCopyFboDst);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glTexture->getBinding(), glTexture->getHandle(), 0);
|
||||
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mCopyFboSrc);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTargets[Color0]->getBinding(), mTargets[Color0]->getHandle(), 0);
|
||||
|
||||
|
||||
glBlitFramebuffer(0, 0, mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(),
|
||||
0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue