mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-29 16:25:42 +00:00
Refactor GFXTextureArray
This commit is contained in:
parent
87dd7ffc4a
commit
e92e945912
7 changed files with 234 additions and 307 deletions
|
|
@ -5,164 +5,47 @@
|
||||||
#include "gfxD3D11Device.h"
|
#include "gfxD3D11Device.h"
|
||||||
#include "gfxD3D11EnumTranslate.h"
|
#include "gfxD3D11EnumTranslate.h"
|
||||||
#include "core/util/tVector.h"
|
#include "core/util/tVector.h"
|
||||||
#include "gfx/gfxDebugEvent.h"
|
|
||||||
#include "gfx/bitmap/imageUtils.h"
|
|
||||||
#include "gfx/util/screenspace.h"
|
#include "gfx/util/screenspace.h"
|
||||||
#include "shaderGen/shaderFeature.h"
|
#include "shaderGen/shaderFeature.h"
|
||||||
|
|
||||||
|
|
||||||
bool GFXD3D11TextureArray::fromTextureArray(const Vector<GFXTexHandle> &textureArray)
|
void GFXD3D11TextureArray::init()
|
||||||
{
|
{
|
||||||
bool success = true;
|
mTextureArrayDesc.Width = mWidth;
|
||||||
Vector<ID3D11Texture2D*> texture2Ds;
|
mTextureArrayDesc.Height = mHeight;
|
||||||
texture2Ds.setSize(textureArray.size());
|
mTextureArrayDesc.MipLevels = mMipLevels;
|
||||||
Vector<GFXTexHandle> tmpHandles;
|
mTextureArrayDesc.ArraySize = mArraySize;
|
||||||
|
mTextureArrayDesc.Format = GFXD3D11TextureFormat[mFormat];
|
||||||
mArraySize = textureArray.size();
|
mTextureArrayDesc.SampleDesc.Count = 1;
|
||||||
|
mTextureArrayDesc.SampleDesc.Quality = 0;
|
||||||
//---------------------------------------------------------------------------------------
|
mTextureArrayDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
// Create the texture array. Each element in the texture
|
mTextureArrayDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||||
// array has the same format/dimensions.
|
mTextureArrayDesc.CPUAccessFlags = 0;
|
||||||
//---------------------------------------------------------------------------------------
|
mTextureArrayDesc.MiscFlags = 0;
|
||||||
D3D11_TEXTURE2D_DESC texElementDesc;
|
|
||||||
GFXFormat format;
|
|
||||||
bool found = false;
|
|
||||||
for (U32 idx = 0; idx < mArraySize; ++idx)
|
|
||||||
{
|
|
||||||
GFXTexHandle texObj = textureArray[idx];
|
|
||||||
if (texObj.isValid())
|
|
||||||
{
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
dynamic_cast<GFXD3D11TextureObject*>(texObj.getPointer())->get2DTex()->GetDesc(&texElementDesc);
|
|
||||||
found = true;
|
|
||||||
format = texObj.getFormat();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format != texObj.getFormat() || texElementDesc.Width != texObj.getWidth() || texElementDesc.Height != texObj.getHeight())
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXGLTextureArray::fromTextureArray there was a mismatch in texture formats, defaulting to uncompressed format");
|
|
||||||
Con::warnf("GFXGLTextureArray::fromTextureArray there was a mismatch in texture formats, defaulting to uncompressed format");
|
|
||||||
success = false;
|
|
||||||
format = GFXFormatR8G8B8A8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// One might think this should return false in this case, but the return value is mostly to highlight internal errors not input errors.
|
|
||||||
if (!found) return true;
|
|
||||||
|
|
||||||
for (U32 idx = 0; idx < mArraySize; ++idx)
|
|
||||||
{
|
|
||||||
texture2Ds[idx] = NULL;
|
|
||||||
|
|
||||||
if(textureArray[idx].isValid())
|
|
||||||
{
|
|
||||||
GFXTexHandle handle = textureArray[idx];
|
|
||||||
if (textureArray[idx]->getPath().isNotEmpty())
|
|
||||||
{
|
|
||||||
D3D11_TEXTURE2D_DESC desc;
|
|
||||||
ID3D11Texture2D* tex = dynamic_cast<GFXD3D11TextureObject*>(textureArray[idx].getPointer())->get2DTex();
|
|
||||||
tex->GetDesc(&desc);
|
|
||||||
if (desc.Height != texElementDesc.Height || desc.Width != texElementDesc.Width || textureArray[idx].getFormat() != format)
|
|
||||||
{
|
|
||||||
if (desc.Height != texElementDesc.Height || desc.Width != texElementDesc.Width)
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXD3D11TextureArray::fromTextureArray all textures should be the same size");
|
|
||||||
Con::warnf("GFXD3D11TextureArray::fromTextureArray all textures should be the same size");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXD3D11TextureArray::fromTextureArray all textures should have the same format");
|
|
||||||
Con::warnf("GFXD3D11TextureArray::fromTextureArray all textures should have the same format");
|
|
||||||
}
|
|
||||||
|
|
||||||
GBitmap* inBitmap = TEXMGR->loadUncompressedTexture(textureArray[idx]->getPath(), &GFXTexturePersistentProfile, texElementDesc.Width, texElementDesc.Height);
|
|
||||||
if (!inBitmap->setFormat(format))
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXD3D11TextureArray::fromTextureArray all textures must be convertible to GFXFormatR8G8B8A8");
|
|
||||||
Con::errorf("GFXD3D11TextureArray::fromTextureArray all textures must be convertible to GFXFormatR8G8B8A8");
|
|
||||||
success = false;
|
|
||||||
handle = NULL;
|
|
||||||
delete inBitmap;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
handle = TEXMGR->createTexture(inBitmap, "", &GFXStaticTextureProfile, true);
|
|
||||||
tmpHandles.push_back(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (handle.isValid())
|
|
||||||
{
|
|
||||||
D3D11_TEXTURE2D_DESC desc;
|
|
||||||
ID3D11Texture2D* tex = dynamic_cast<GFXD3D11TextureObject*>(handle.getPointer())->get2DTex();
|
|
||||||
tex->GetDesc(&desc);
|
|
||||||
if (desc.Height != texElementDesc.Height || desc.Width != texElementDesc.Width || handle.getFormat() != format)
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXD3D11TextureArray::fromTextureArray all textures must have the same size and format");
|
|
||||||
Con::errorf("GFXD3D11TextureArray::fromTextureArray all textures must have the same size and format");
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
texture2Ds[idx] = dynamic_cast<GFXD3D11TextureObject*>(handle.getPointer())->get2DTex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D11_TEXTURE2D_DESC texArrayDesc;
|
|
||||||
texArrayDesc.Width = texElementDesc.Width;
|
|
||||||
texArrayDesc.Height = texElementDesc.Height;
|
|
||||||
texArrayDesc.MipLevels = texElementDesc.MipLevels;
|
|
||||||
texArrayDesc.ArraySize = mArraySize;
|
|
||||||
texArrayDesc.Format = GFXD3D11TextureFormat[format];
|
|
||||||
texArrayDesc.SampleDesc.Count = 1;
|
|
||||||
texArrayDesc.SampleDesc.Quality = 0;
|
|
||||||
texArrayDesc.Usage = D3D11_USAGE_DEFAULT;
|
|
||||||
texArrayDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
||||||
texArrayDesc.CPUAccessFlags = 0;
|
|
||||||
texArrayDesc.MiscFlags = 0;
|
|
||||||
|
|
||||||
HRESULT hr = D3D11DEVICE->CreateTexture2D(&texArrayDesc, NULL, &mTextureArray);
|
|
||||||
AssertFatal(SUCCEEDED(hr), "GFXD3D11TextureArray::_createTextureArray failed to create texture array!");
|
|
||||||
//---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------
|
|
||||||
// Copy individual texture elements into texture array.
|
|
||||||
//---------------------------------------------------------------------------------------
|
|
||||||
// for each texture element...
|
|
||||||
for (UINT i = 0; i < mArraySize; ++i)
|
|
||||||
{
|
|
||||||
if (texture2Ds[i] == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
D3D11_TEXTURE2D_DESC desc;
|
|
||||||
texture2Ds[i]->GetDesc(&desc);
|
|
||||||
// for each mipmap level...
|
|
||||||
for (UINT j = 0; j < desc.MipLevels; ++j)
|
|
||||||
{
|
|
||||||
const U32 srcSubResource = D3D11CalcSubresource(j, 0, desc.MipLevels);
|
|
||||||
const U32 dstSubResource = D3D11CalcSubresource(j, i, texArrayDesc.MipLevels);
|
|
||||||
D3D11DEVICECONTEXT->CopySubresourceRegion(mTextureArray, dstSubResource, 0, 0, 0, texture2Ds[i], srcSubResource, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean temporary textures
|
|
||||||
for (GFXTexHandle handle : tmpHandles)
|
|
||||||
{
|
|
||||||
handle.free();
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
HRESULT hr = D3D11DEVICE->CreateTexture2D(&mTextureArrayDesc, NULL, &mTextureArray);
|
||||||
|
AssertFatal(SUCCEEDED(hr), "GFXD3D11TextureArray::init failed to create texture array!");
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
// Create a resource view to the texture array.
|
// Create a resource view to the texture array.
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
createResourceView(texArrayDesc.Format, texArrayDesc.MipLevels, texArrayDesc.BindFlags);
|
createResourceView(mTextureArrayDesc.Format, mTextureArrayDesc.MipLevels, mTextureArrayDesc.BindFlags);
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
void GFXD3D11TextureArray::_setTexture(const GFXTexHandle& texture, U32 slot)
|
||||||
|
{
|
||||||
|
GFXD3D11TextureObject *texObj = dynamic_cast<GFXD3D11TextureObject*>(texture.getPointer());
|
||||||
|
ID3D11Texture2D* tex2d = texObj->get2DTex();
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
tex2d->GetDesc(&desc);
|
||||||
|
// for each mipmap level...
|
||||||
|
for (UINT j = 0; j < desc.MipLevels; ++j)
|
||||||
|
{
|
||||||
|
const U32 srcSubResource = D3D11CalcSubresource(j, 0, desc.MipLevels);
|
||||||
|
const U32 dstSubResource = D3D11CalcSubresource(j, slot, mTextureArrayDesc.MipLevels);
|
||||||
|
D3D11DEVICECONTEXT->CopySubresourceRegion(mTextureArray, dstSubResource, 0, 0, 0, tex2d, srcSubResource, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXD3D11TextureArray::setToTexUnit(U32 tuNum)
|
void GFXD3D11TextureArray::setToTexUnit(U32 tuNum)
|
||||||
|
|
@ -170,7 +53,6 @@ void GFXD3D11TextureArray::setToTexUnit(U32 tuNum)
|
||||||
D3D11DEVICECONTEXT->PSSetShaderResources(tuNum, 1, &mSRView);
|
D3D11DEVICECONTEXT->PSSetShaderResources(tuNum, 1, &mSRView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GFXD3D11TextureArray::createResourceView(DXGI_FORMAT format, U32 numMipLevels, U32 usageFlags)
|
void GFXD3D11TextureArray::createResourceView(DXGI_FORMAT format, U32 numMipLevels, U32 usageFlags)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
@ -226,6 +108,8 @@ void GFXD3D11TextureArray::Release()
|
||||||
SAFE_RELEASE(mRTView)
|
SAFE_RELEASE(mRTView)
|
||||||
SAFE_RELEASE(mDSView)
|
SAFE_RELEASE(mDSView)
|
||||||
SAFE_RELEASE(mTextureArray)
|
SAFE_RELEASE(mTextureArray)
|
||||||
|
|
||||||
|
GFXTextureArray::Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D11ShaderResourceView* GFXD3D11TextureArray::getSRView()
|
ID3D11ShaderResourceView* GFXD3D11TextureArray::getSRView()
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fromTextureArray(const Vector<GFXTexHandle> &textureArray) override;
|
~GFXD3D11TextureArray() { Release(); };
|
||||||
|
|
||||||
|
void init();
|
||||||
void setToTexUnit(U32 tuNum) override;
|
void setToTexUnit(U32 tuNum) override;
|
||||||
|
|
||||||
void createResourceView(DXGI_FORMAT format, U32 numMipLevels, U32 usageFlags);
|
void createResourceView(DXGI_FORMAT format, U32 numMipLevels, U32 usageFlags);
|
||||||
|
|
@ -39,12 +41,15 @@ public:
|
||||||
ID3D11RenderTargetView** getRTViewPtr();
|
ID3D11RenderTargetView** getRTViewPtr();
|
||||||
ID3D11DepthStencilView** getDSViewPtr();
|
ID3D11DepthStencilView** getDSViewPtr();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _setTexture(const GFXTexHandle& texture, U32 slot) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ID3D11ShaderResourceView* mSRView; // for shader resource input
|
ID3D11ShaderResourceView* mSRView; // for shader resource input
|
||||||
ID3D11RenderTargetView* mRTView; // for render targets
|
ID3D11RenderTargetView* mRTView; // for render targets
|
||||||
ID3D11DepthStencilView* mDSView; //render target view for depth stencil
|
ID3D11DepthStencilView* mDSView; //render target view for depth stencil
|
||||||
|
|
||||||
ID3D11Texture2D* mTextureArray;
|
ID3D11Texture2D* mTextureArray;
|
||||||
|
D3D11_TEXTURE2D_DESC mTextureArrayDesc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -184,8 +184,11 @@ public:
|
||||||
void zombify() override {}
|
void zombify() override {}
|
||||||
void resurrect() override {}
|
void resurrect() override {}
|
||||||
void Release() override {}
|
void Release() override {}
|
||||||
bool fromTextureArray(const Vector<GFXTexHandle> &textureArray) override { return true; }
|
void setToTexUnit(U32 tuNum) override { }
|
||||||
virtual void setToTexUnit(U32 tuNum) { }
|
void init() override { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _setTexture(const GFXTexHandle& texture, U32 slot) override { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class GFXNullVertexBuffer : public GFXVertexBuffer
|
class GFXNullVertexBuffer : public GFXVertexBuffer
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,142 @@
|
||||||
#include "gfxTextureArray.h"
|
#include "gfxTextureArray.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "gfxDevice.h"
|
||||||
|
#include "gfxTextureManager.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
|
||||||
|
void GFXTextureArray::set(U32 width, U32 height, U32 size, GFXFormat format, U32 mipLevels)
|
||||||
|
{
|
||||||
|
mWidth = width;
|
||||||
|
mHeight = height;
|
||||||
|
mArraySize = size;
|
||||||
|
mFormat = format;
|
||||||
|
mMipLevels = mipLevels;
|
||||||
|
|
||||||
|
mTextures.setSize(size);
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GFXTextureArray::fromTextureArray(const Vector<GFXTexHandle>& textureArray)
|
||||||
|
{
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------
|
||||||
|
// Create the texture array. Each element in the texture
|
||||||
|
// array has the same format/dimensions.
|
||||||
|
//---------------------------------------------------------------------------------------
|
||||||
|
bool found = false;
|
||||||
|
for (const GFXTexHandle& texObj : textureArray)
|
||||||
|
{
|
||||||
|
if (texObj.isValid())
|
||||||
|
{
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
mFormat = texObj.getFormat();
|
||||||
|
mWidth = texObj.getWidth();
|
||||||
|
mHeight = texObj.getHeight();
|
||||||
|
mMipLevels = texObj->getMipLevels();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFormat != texObj.getFormat() || mWidth != texObj.getWidth() || mHeight != texObj.getHeight())
|
||||||
|
{
|
||||||
|
AssertWarn(true, "GFXTextureArray::fromTextureArray there was a mismatch in texture formats, defaulting to uncompressed format");
|
||||||
|
Con::warnf("GFXTextureArray::fromTextureArray there was a mismatch in texture formats, defaulting to uncompressed format");
|
||||||
|
success = false;
|
||||||
|
mFormat = GFXFormatR8G8B8A8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// One might think this should return false in this case, but the return value is mostly to highlight internal errors not input errors.
|
||||||
|
if (!found) return true;
|
||||||
|
|
||||||
|
set(mWidth, mHeight, textureArray.size(), mFormat, mMipLevels);
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------
|
||||||
|
// Copy individual texture elements into texture array.
|
||||||
|
//---------------------------------------------------------------------------------------
|
||||||
|
// for each texture element...
|
||||||
|
for (U32 i = 0; i < mArraySize; ++i)
|
||||||
|
{
|
||||||
|
if (textureArray[i].isValid())
|
||||||
|
{
|
||||||
|
setTexture(textureArray[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXTextureArray::setTexture(const GFXTexHandle& texture, U32 slot)
|
||||||
|
{
|
||||||
|
GFXTexHandle handle = texture;
|
||||||
|
if (texture->getPath().isNotEmpty())
|
||||||
|
{
|
||||||
|
if (texture.getHeight() != mHeight || texture.getWidth() != mWidth || texture.getFormat() != mFormat || texture->getMipLevels() < mMipLevels)
|
||||||
|
{
|
||||||
|
if (texture.getHeight() != mHeight || texture.getWidth() != mWidth)
|
||||||
|
{
|
||||||
|
AssertWarn(true, "GFXTextureArray::setTexture all textures should be the same size");
|
||||||
|
Con::warnf("GFXTextureArray::setTexture all textures should be the same size");
|
||||||
|
}
|
||||||
|
else if (texture->getMipLevels() < mMipLevels)
|
||||||
|
{
|
||||||
|
AssertWarn(true, "GFXTextureArray::setTexture all textures should have at least the same number of mips");
|
||||||
|
Con::warnf("GFXTextureArray::setTexture all textures should have at least the same number of mips");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AssertWarn(true, "GFXTextureArray::setTexture all textures should have the same format");
|
||||||
|
Con::warnf("GFXTextureArray::setTexture all textures should have the same format");
|
||||||
|
}
|
||||||
|
|
||||||
|
GBitmap* inBitmap = TEXMGR->loadUncompressedTexture(texture->getPath(), &GFXTexturePersistentProfile, mWidth, mHeight);
|
||||||
|
if (!inBitmap->setFormat(mFormat))
|
||||||
|
{
|
||||||
|
AssertWarn(true, "GFXTextureArray::setTexture all textures must be convertible to GFXFormat " + mFormat);
|
||||||
|
Con::errorf("GFXTextureArray::setTexture all textures must be convertible to GFXFormat" + mFormat);
|
||||||
|
handle = NULL;
|
||||||
|
delete inBitmap;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handle = TEXMGR->createTexture(inBitmap, "", &GFXStaticTextureProfile, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!handle.isValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle.getHeight() != mHeight || handle.getWidth() != mWidth || handle.getFormat() != mFormat || handle->getMipLevels() < mMipLevels)
|
||||||
|
{
|
||||||
|
AssertWarn(true, "GFXTextureArray::setTexture all textures must have the same size and format");
|
||||||
|
Con::errorf("GFXTextureArray::setTexture all textures must have the same size and format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextures[slot] = handle;
|
||||||
|
|
||||||
|
_setTexture(handle, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXTextureArray::Release()
|
||||||
|
{
|
||||||
|
for (GFXTexHandle& mTexture : mTextures)
|
||||||
|
{
|
||||||
|
mTexture = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const String GFXTextureArray::describeSelf() const
|
const String GFXTextureArray::describeSelf() const
|
||||||
{
|
{
|
||||||
// We've got nothing
|
// We've got nothing
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#ifndef _GFXTEXTUREHANDLE_H_
|
#ifndef _GFXTEXTUREHANDLE_H_
|
||||||
#include "gfxTextureHandle.h"
|
#include "gfxTextureHandle.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "core/util/tVector.h"
|
||||||
|
|
||||||
|
|
||||||
class GFXTextureProfile;
|
class GFXTextureProfile;
|
||||||
|
|
@ -43,18 +44,30 @@ class GFXTextureObject;
|
||||||
class GFXTextureArray : public StrongRefBase, public GFXResource
|
class GFXTextureArray : public StrongRefBase, public GFXResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool fromTextureArray(const Vector<GFXTexHandle> &textureArray) = 0;
|
virtual void init() = 0;
|
||||||
|
virtual void set(U32 width, U32 height, U32 size, GFXFormat format, U32 mipLevels);
|
||||||
|
virtual bool fromTextureArray(const Vector<GFXTexHandle> &textureArray);
|
||||||
|
virtual void setTexture(const GFXTexHandle &texture, U32 slot);
|
||||||
virtual void setToTexUnit(U32 tuNum) = 0;
|
virtual void setToTexUnit(U32 tuNum) = 0;
|
||||||
|
|
||||||
|
|
||||||
// GFXResource interface
|
// GFXResource interface
|
||||||
virtual void zombify() = 0;
|
virtual void zombify() = 0;
|
||||||
virtual void resurrect() = 0;
|
virtual void resurrect() = 0;
|
||||||
virtual void Release() = 0;
|
virtual void Release();
|
||||||
|
|
||||||
virtual const String describeSelf() const;
|
virtual const String describeSelf() const;
|
||||||
|
|
||||||
|
GFXFormat mFormat;
|
||||||
|
U32 mWidth;
|
||||||
|
U32 mHeight;
|
||||||
U32 mArraySize;
|
U32 mArraySize;
|
||||||
|
U32 mMipLevels;
|
||||||
|
|
||||||
|
Vector<GFXTexHandle> mTextures;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void _setTexture(const GFXTexHandle& texture, U32 slot) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,175 +3,57 @@
|
||||||
#include "gfxGLTextureObject.h"
|
#include "gfxGLTextureObject.h"
|
||||||
#include "gfxGLUtils.h"
|
#include "gfxGLUtils.h"
|
||||||
#include "core/util/tVector.h"
|
#include "core/util/tVector.h"
|
||||||
#include "gfx/bitmap/imageUtils.h"
|
|
||||||
|
|
||||||
|
|
||||||
GFXGLTextureArray::GFXGLTextureArray()
|
GFXGLTextureArray::GFXGLTextureArray()
|
||||||
{
|
{
|
||||||
mTextureArray = NULL;
|
mTextureArray = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXGLTextureArray::~GFXGLTextureArray()
|
void GFXGLTextureArray::init()
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &mTextureArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GFXGLTextureArray::fromTextureArray(const Vector<GFXTexHandle> &textureArray)
|
|
||||||
{
|
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
if (textureArray.empty())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
U32 baseWidth = 0, baseHeight = 0;
|
|
||||||
bool isCompressed = false;
|
|
||||||
mArraySize = textureArray.size();
|
|
||||||
|
|
||||||
for (GFXTexHandle texObj : textureArray)
|
|
||||||
{
|
|
||||||
if (texObj.isValid())
|
|
||||||
{
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
baseWidth = texObj.getWidth();
|
|
||||||
baseHeight = texObj.getHeight();
|
|
||||||
mMipMapLevels = getMax((U32)1, texObj->mMipLevels);
|
|
||||||
found = true;
|
|
||||||
mFormat = texObj.getFormat();
|
|
||||||
isCompressed = ImageUtil::isCompressedFormat(mFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mFormat != texObj.getFormat() || baseWidth != texObj.getWidth() || baseHeight != texObj.getHeight())
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXGLTextureArray::fromTextureArray there was a mismatch in texture format, defaulting to uncompressed format");
|
|
||||||
Con::warnf("GFXGLTextureArray::fromTextureArray there was a mismatch in texture format, defaulting to uncompressed format");
|
|
||||||
success = false;
|
|
||||||
mFormat = GFXFormatR8G8B8A8;
|
|
||||||
isCompressed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// One might think this should return false in this case, but the return value is mostly to highlight internal errors not input errors.
|
|
||||||
if (!found) return true;
|
|
||||||
|
|
||||||
Vector <GFXGLTextureObject*> texture2Ds;
|
|
||||||
texture2Ds.setSize(textureArray.size());
|
|
||||||
Vector<GFXTexHandle> tmpHandles;
|
|
||||||
|
|
||||||
for (U32 idx = 0; idx < mArraySize; ++idx)
|
|
||||||
{
|
|
||||||
texture2Ds[idx] = NULL;
|
|
||||||
GFXTexHandle texObj = textureArray[idx];
|
|
||||||
|
|
||||||
if (texObj.isValid())
|
|
||||||
{
|
|
||||||
GFXTexHandle handle = textureArray[idx];
|
|
||||||
if (texObj->getPath().isNotEmpty())
|
|
||||||
{
|
|
||||||
if (texObj.getHeight() != baseHeight|| texObj.getWidth() != baseWidth || texObj.getFormat() != mFormat)
|
|
||||||
{
|
|
||||||
if (texObj.getHeight() != baseHeight || texObj.getWidth() != baseWidth)
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXGLTextureArray::fromTextureArray all textures should be the same size");
|
|
||||||
Con::warnf("GFXGLTextureArray::fromTextureArray all textures should be the same size");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXGLTextureArray::fromTextureArray all textures should have the same format");
|
|
||||||
Con::warnf("GFXGLTextureArray::fromTextureArray all textures should have the same format");
|
|
||||||
}
|
|
||||||
|
|
||||||
GBitmap* inBitmap = TEXMGR->loadUncompressedTexture(textureArray[idx]->getPath(), &GFXTexturePersistentProfile, baseWidth, baseHeight);
|
|
||||||
if (!inBitmap->setFormat(mFormat))
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXGLTextureArray::fromTextureArray all textures must be convertible to GFXFormatR8G8B8A8");
|
|
||||||
Con::errorf("GFXGLTextureArray::fromTextureArray all textures must be convertible to GFXFormatR8G8B8A8");
|
|
||||||
success = false;
|
|
||||||
handle = NULL;
|
|
||||||
delete inBitmap;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
handle = TEXMGR->createTexture(inBitmap, "", &GFXStaticTextureProfile, true);
|
|
||||||
tmpHandles.push_back(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (handle.isValid())
|
|
||||||
{
|
|
||||||
if (handle.getHeight() != baseHeight || handle.getWidth()!= baseWidth || handle.getFormat() != mFormat)
|
|
||||||
{
|
|
||||||
AssertWarn(true, "GFXGLTextureArray::fromTextureArray all textures must have the same size and format");
|
|
||||||
Con::errorf("GFXGLTextureArray::fromTextureArray all textures must have the same size and format");
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
texture2Ds[idx] = dynamic_cast<GFXGLTextureObject*>(handle.getPointer());
|
|
||||||
tmpHandles.push_back(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenTextures(1, &mTextureArray);
|
glGenTextures(1, &mTextureArray);
|
||||||
PRESERVE_2D_TEXTURE_ARRAY();
|
PRESERVE_2D_TEXTURE_ARRAY();
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, mMin(mMipMapLevels - 1, 1));
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, mMin(mMipLevels - 1, 1));
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, mMipMapLevels, GL_RGBA8, baseWidth, baseHeight, textureArray.size());
|
glTexStorage3D(GL_TEXTURE_2D_ARRAY, mMipLevels, GL_RGBA8, mWidth, mHeight, mArraySize);
|
||||||
|
}
|
||||||
|
|
||||||
for (U32 idx = 0; idx < texture2Ds.size(); ++idx)
|
void GFXGLTextureArray::_setTexture(const GFXTexHandle& texture, U32 slot)
|
||||||
|
{
|
||||||
|
PRESERVE_2D_TEXTURE_ARRAY();
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
|
||||||
|
|
||||||
|
GFXGLTextureObject* texObj = dynamic_cast<GFXGLTextureObject*>(texture.getPointer());
|
||||||
|
for (U32 mip = 0; mip < mMipLevels; ++mip)
|
||||||
{
|
{
|
||||||
if (texture2Ds[idx] == NULL)
|
U8* buf = texObj->getTextureData(mip);
|
||||||
|
const U32 mipWidth = getMax(U32(1), mWidth >> mip);
|
||||||
|
const U32 mipHeight = getMax(U32(1), mHeight >> mip);
|
||||||
|
if (mIsCompressed)
|
||||||
{
|
{
|
||||||
continue;
|
glCompressedTexSubImage3D(
|
||||||
|
GL_TEXTURE_2D_ARRAY,
|
||||||
|
mip, 0, 0,
|
||||||
|
slot, mipWidth, mipHeight, 1,
|
||||||
|
GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], buf
|
||||||
|
);
|
||||||
}
|
}
|
||||||
GFXGLTextureObject* texObj = texture2Ds[idx];
|
else
|
||||||
for (U32 mip = 0; mip < mMipMapLevels; ++mip)
|
|
||||||
{
|
{
|
||||||
U8* buf = texObj->getTextureData(mip);
|
glTexSubImage3D(
|
||||||
const U32 mipWidth = getMax(U32(1), baseWidth >> mip);
|
GL_TEXTURE_2D_ARRAY,
|
||||||
const U32 mipHeight = getMax(U32(1), baseHeight >> mip);
|
mip, 0, 0,
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
|
slot, mipWidth, mipHeight, 1,
|
||||||
if (isCompressed)
|
GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], buf
|
||||||
{
|
);
|
||||||
glCompressedTexSubImage3D(
|
|
||||||
GL_TEXTURE_2D_ARRAY,
|
|
||||||
mip, 0, 0,
|
|
||||||
idx, mipWidth, mipHeight, 1,
|
|
||||||
GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], buf
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glTexSubImage3D(
|
|
||||||
GL_TEXTURE_2D_ARRAY,
|
|
||||||
mip, 0, 0,
|
|
||||||
idx, mipWidth, mipHeight, 1,
|
|
||||||
GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], buf
|
|
||||||
);
|
|
||||||
}
|
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
|
||||||
delete[] buf;
|
|
||||||
}
|
}
|
||||||
|
delete[] buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isCompressed)
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
|
||||||
|
|
||||||
// Clean temporary textures
|
|
||||||
for (GFXTexHandle handle : tmpHandles)
|
|
||||||
{
|
|
||||||
handle.free();
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXGLTextureArray::setToTexUnit(U32 tuNum)
|
void GFXGLTextureArray::setToTexUnit(U32 tuNum)
|
||||||
|
|
@ -179,13 +61,13 @@ void GFXGLTextureArray::setToTexUnit(U32 tuNum)
|
||||||
dynamic_cast<GFXGLDevice*>(getOwningDevice())->setTextureArrayInternal(tuNum, this);
|
dynamic_cast<GFXGLDevice*>(getOwningDevice())->setTextureArrayInternal(tuNum, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GFXGLTextureArray::Release()
|
void GFXGLTextureArray::Release()
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &mTextureArray);
|
glDeleteTextures(1, &mTextureArray);
|
||||||
mTextureArray = 0;
|
mTextureArray = 0;
|
||||||
}
|
|
||||||
|
|
||||||
|
GFXTextureArray::Release();
|
||||||
|
}
|
||||||
|
|
||||||
void GFXGLTextureArray::bind(U32 textureUnit) const
|
void GFXGLTextureArray::bind(U32 textureUnit) const
|
||||||
{
|
{
|
||||||
|
|
@ -201,7 +83,7 @@ void GFXGLTextureArray::bind(U32 textureUnit) const
|
||||||
const GFXSamplerStateDesc& ssd = sb->getDesc().samplers[textureUnit];
|
const GFXSamplerStateDesc& ssd = sb->getDesc().samplers[textureUnit];
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, 0));
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, 0));
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, mMin(mMipMapLevels - 1, 1));
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, mMin(mMipLevels - 1, 1));
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,10 @@ class GFXGLTextureArray : public GFXTextureArray
|
||||||
public:
|
public:
|
||||||
GFXGLTextureArray();
|
GFXGLTextureArray();
|
||||||
|
|
||||||
~GFXGLTextureArray();
|
~GFXGLTextureArray() { Release(); };
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
bool fromTextureArray(const Vector<GFXTexHandle>& textureArray) override;
|
|
||||||
void setToTexUnit(U32 tuNum) override;
|
void setToTexUnit(U32 tuNum) override;
|
||||||
|
|
||||||
void bind(U32 textureUnit) const;
|
void bind(U32 textureUnit) const;
|
||||||
|
|
@ -23,11 +24,13 @@ public:
|
||||||
void resurrect() override;
|
void resurrect() override;
|
||||||
void Release() override;
|
void Release() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _setTexture(const GFXTexHandle& texture, U32 slot) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint mTextureArray;
|
GLuint mTextureArray;
|
||||||
|
|
||||||
U32 mMipMapLevels;
|
bool mIsCompressed;
|
||||||
GFXFormat mFormat;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue