Implement Singlepass Terrain Render

This commit is contained in:
Lukas Aldershaab 2021-01-01 21:05:21 +01:00
parent 49a8c0ad36
commit 87dd7ffc4a
35 changed files with 1658 additions and 951 deletions

View file

@ -22,6 +22,8 @@
#include "platform/platform.h"
#include "gfx/gl/gfxGLDevice.h"
#include "gfxGLTextureArray.h"
#include "platform/platformGL.h"
#include "gfx/gfxCubemap.h"
@ -457,6 +459,13 @@ GFXCubemapArray *GFXGLDevice::createCubemapArray()
return cubeArray;
}
GFXTextureArray* GFXGLDevice::createTextureArray()
{
GFXGLTextureArray* textureArray = new GFXGLTextureArray();
textureArray->registerResourceWithDevice(this);
return textureArray;
}
void GFXGLDevice::endSceneInternal()
{
// nothing to do for opengl
@ -766,6 +775,22 @@ void GFXGLDevice::setCubemapArrayInternal(U32 textureUnit, const GFXGLCubemapArr
}
}
void GFXGLDevice::setTextureArrayInternal(U32 textureUnit, const GFXGLTextureArray* texture)
{
if (texture)
{
mActiveTextureType[textureUnit] = GL_TEXTURE_2D_ARRAY;
texture->bind(textureUnit);
}
else if (mActiveTextureType[textureUnit] != GL_ZERO)
{
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(mActiveTextureType[textureUnit], 0);
getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
mActiveTextureType[textureUnit] = GL_ZERO;
}
}
void GFXGLDevice::setMatrix( GFXMatrixType mtype, const MatrixF &mat )
{
// ONLY NEEDED ON FFP

View file

@ -35,6 +35,7 @@
#include "gfx/gfxResource.h"
#include "gfx/gl/gfxGLStateBlock.h"
class GFXGLTextureArray;
class GFXGLVertexBuffer;
class GFXGLPrimitiveBuffer;
class GFXGLTextureTarget;
@ -83,6 +84,7 @@ public:
virtual GFXCubemap * createCubemap();
virtual GFXCubemapArray *createCubemapArray();
virtual GFXTextureArray *createTextureArray();
virtual F32 getFillConventionOffset() const { return 0.0f; }
@ -173,6 +175,7 @@ protected:
virtual void setTextureInternal(U32 textureUnit, const GFXTextureObject*texture);
virtual void setCubemapInternal(U32 textureUnit, const GFXGLCubemap* texture);
virtual void setCubemapArrayInternal(U32 textureUnit, const GFXGLCubemapArray* texture);
virtual void setTextureArrayInternal(U32 textureUnit, const GFXGLTextureArray* texture);
virtual void setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable);
virtual void setLightMaterialInternal(const GFXLightMaterial mat);
@ -210,6 +213,7 @@ private:
friend class GFXGLTextureObject;
friend class GFXGLCubemap;
friend class GFXGLCubemapArray;
friend class GFXGLTextureArray;
friend class GFXGLWindowTarget;
friend class GFXGLPrimitiveBuffer;
friend class GFXGLVertexBuffer;

View file

@ -82,6 +82,7 @@ static U32 shaderConstTypeSize(GFXShaderConstType type)
case GFXSCT_Sampler:
case GFXSCT_SamplerCube:
case GFXSCT_SamplerCubeArray:
case GFXSCT_SamplerTextureArray:
return 4;
case GFXSCT_Float2:
case GFXSCT_Int2:
@ -630,6 +631,9 @@ void GFXGLShader::initConstantDescs()
case GL_SAMPLER_CUBE_MAP_ARRAY_ARB:
desc.constType = GFXSCT_SamplerCubeArray;
break;
case GL_SAMPLER_2D_ARRAY:
desc.constType = GFXSCT_SamplerTextureArray;
break;
default:
AssertFatal(false, "GFXGLShader::initConstantDescs - unrecognized uniform type");
// If we don't recognize the constant don't add its description.
@ -661,7 +665,10 @@ void GFXGLShader::initHandles()
HandleMap::Iterator handle = mHandles.find(desc.name);
S32 sampler = -1;
if(desc.constType == GFXSCT_Sampler || desc.constType == GFXSCT_SamplerCube || desc.constType == GFXSCT_SamplerCubeArray)
if(desc.constType == GFXSCT_Sampler ||
desc.constType == GFXSCT_SamplerCube ||
desc.constType == GFXSCT_SamplerCubeArray ||
desc.constType == GFXSCT_SamplerTextureArray)
{
S32 idx = mSamplerNamesOrdered.find_next(desc.name);
AssertFatal(idx != -1, "");
@ -704,7 +711,11 @@ void GFXGLShader::initHandles()
for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter)
{
GFXGLShaderConstHandle* handle = iter->value;
if(handle->isValid() && (handle->getType() == GFXSCT_Sampler || handle->getType() == GFXSCT_SamplerCube || handle->getType() == GFXSCT_SamplerCubeArray))
if(handle->isValid() &&
(handle->getType() == GFXSCT_Sampler ||
handle->getType() == GFXSCT_SamplerCube ||
handle->getType() == GFXSCT_SamplerCubeArray ||
handle->getType() == GFXSCT_SamplerTextureArray))
{
// Set sampler number on our program.
glUniform1i(handle->mLocation, handle->mSamplerNum);
@ -837,6 +848,7 @@ void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer)
case GFXSCT_Sampler:
case GFXSCT_SamplerCube:
case GFXSCT_SamplerCubeArray:
case GFXSCT_SamplerTextureArray:
glUniform1iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset));
break;
case GFXSCT_Int2:

View file

@ -20,11 +20,11 @@ public:
class TextureUnit
{
public:
TextureUnit() : mTexture1D(0), mTexture2D(0), mTexture3D(0), mTextureCube(0), mTextureCubeArray(0)
TextureUnit() : mTexture1D(0), mTexture2D(0), mTexture3D(0), mTextureCube(0), mTextureCubeArray(0), mTextureArray(0)
{
}
GLuint mTexture1D, mTexture2D, mTexture3D, mTextureCube, mTextureCubeArray;
GLuint mTexture1D, mTexture2D, mTexture3D, mTextureCube, mTextureCubeArray, mTextureArray;
};
/// after glBindTexture
@ -48,6 +48,9 @@ public:
case GL_TEXTURE_CUBE_MAP_ARRAY:
mTextureUnits[mActiveTexture].mTextureCubeArray = handle;
break;
case GL_TEXTURE_2D_ARRAY:
mTextureUnits[mActiveTexture].mTextureArray = handle;
break;
default:
AssertFatal(0, avar("GFXGLStateCache::setCacheBindedTex - binding (%x) not supported.", biding) );
return;
@ -74,6 +77,9 @@ public:
case GL_TEXTURE_CUBE_MAP_ARRAY:
mTextureUnits[mActiveTexture].mTextureCubeArray = handle;
break;
case GL_TEXTURE_2D_ARRAY:
mTextureUnits[mActiveTexture].mTextureArray = handle;
break;
case GL_FRAMEBUFFER:
mBindedFBO_W = mBindedFBO_R = handle;
break;
@ -109,6 +115,8 @@ public:
return mTextureUnits[mActiveTexture].mTextureCube;
case GL_TEXTURE_CUBE_MAP_ARRAY:
return mTextureUnits[mActiveTexture].mTextureCubeArray;
case GL_TEXTURE_2D_ARRAY:
return mTextureUnits[mActiveTexture].mTextureArray;
case GL_DRAW_FRAMEBUFFER:
return mBindedFBO_W;
case GL_READ_FRAMEBUFFER:
@ -138,4 +146,4 @@ protected:
};
#endif
#endif

View file

@ -0,0 +1,215 @@
#include "gfxGLTextureArray.h"
#include "gfxGLTextureObject.h"
#include "gfxGLUtils.h"
#include "core/util/tVector.h"
#include "gfx/bitmap/imageUtils.h"
GFXGLTextureArray::GFXGLTextureArray()
{
mTextureArray = NULL;
}
GFXGLTextureArray::~GFXGLTextureArray()
{
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);
PRESERVE_2D_TEXTURE_ARRAY();
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_MIN_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_T, GL_CLAMP_TO_EDGE);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, mMipMapLevels, GL_RGBA8, baseWidth, baseHeight, textureArray.size());
for (U32 idx = 0; idx < texture2Ds.size(); ++idx)
{
if (texture2Ds[idx] == NULL)
{
continue;
}
GFXGLTextureObject* texObj = texture2Ds[idx];
for (U32 mip = 0; mip < mMipMapLevels; ++mip)
{
U8* buf = texObj->getTextureData(mip);
const U32 mipWidth = getMax(U32(1), baseWidth >> mip);
const U32 mipHeight = getMax(U32(1), baseHeight >> mip);
glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
if (isCompressed)
{
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;
}
}
if (!isCompressed)
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
// Clean temporary textures
for (GFXTexHandle handle : tmpHandles)
{
handle.free();
}
return success;
}
void GFXGLTextureArray::setToTexUnit(U32 tuNum)
{
dynamic_cast<GFXGLDevice*>(getOwningDevice())->setTextureArrayInternal(tuNum, this);
}
void GFXGLTextureArray::Release()
{
glDeleteTextures(1, &mTextureArray);
mTextureArray = 0;
}
void GFXGLTextureArray::bind(U32 textureUnit) const
{
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
dynamic_cast<GFXGLDevice*>(getOwningDevice())->getOpenglCache()->setCacheBindedTex(textureUnit, GL_TEXTURE_2D_ARRAY, mTextureArray);
GFXGLStateBlockRef sb = static_cast<GFXGLDevice*>(GFX)->getCurrentStateBlock();
AssertFatal(sb, "GFXGLTextureArray::bind - No active stateblock!");
if (!sb)
return;
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_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_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
}
void GFXGLTextureArray::zombify()
{
}
void GFXGLTextureArray::resurrect()
{
}

View file

@ -0,0 +1,34 @@
#ifndef _GFXGLTEXTUREARRAY_H_
#define _GFXGLTEXTUREARRAY_H_
#include <glad/glad.h>
#include "gfx/gfxTextureArray.h"
#include "gfx/gfxTextureManager.h"
class GFXGLTextureArray : public GFXTextureArray
{
public:
GFXGLTextureArray();
~GFXGLTextureArray();
bool fromTextureArray(const Vector<GFXTexHandle>& textureArray) override;
void setToTexUnit(U32 tuNum) override;
void bind(U32 textureUnit) const;
// GFXResource interface
void zombify() override;
void resurrect() override;
void Release() override;
private:
GLuint mTextureArray;
U32 mMipMapLevels;
GFXFormat mFormat;
};
#endif

View file

@ -194,6 +194,9 @@ GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_CUBE_MAP, GL
#define PRESERVE_CUBEMAP_ARRAY_TEXTURE() \
GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, (GFXGLPreserveInteger::BindFn)glBindTexture)
#define PRESERVE_2D_TEXTURE_ARRAY() \
GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BINDING_2D_ARRAY, (GFXGLPreserveInteger::BindFn)glBindTexture)
#define _GET_TEXTURE_BINDING(binding) \
binding == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : (binding == GL_TEXTURE_3D ? GL_TEXTURE_BINDING_3D : GL_TEXTURE_BINDING_1D )