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

@ -40,6 +40,8 @@
#include "shaderGen/shaderGen.h" #include "shaderGen/shaderGen.h"
#include <d3d9.h> //d3dperf #include <d3d9.h> //d3dperf
#include "gfxD3D11TextureArray.h"
#ifdef TORQUE_DEBUG #ifdef TORQUE_DEBUG
#include "d3d11sdklayers.h" #include "d3d11sdklayers.h"
#endif #endif
@ -48,6 +50,8 @@
#pragma comment(lib, "d3d9.lib") //d3dperf #pragma comment(lib, "d3d9.lib") //d3dperf
#pragma comment(lib, "d3d11.lib") #pragma comment(lib, "d3d11.lib")
class GFXD3D11TextureArray;
class GFXPCD3D11RegisterDevice class GFXPCD3D11RegisterDevice
{ {
public: public:
@ -1736,6 +1740,13 @@ GFXCubemapArray * GFXD3D11Device::createCubemapArray()
return cubeArray; return cubeArray;
} }
GFXTextureArray * GFXD3D11Device::createTextureArray()
{
GFXD3D11TextureArray* textureArray = new GFXD3D11TextureArray();
textureArray->registerResourceWithDevice(this);
return textureArray;
}
// Debug events // Debug events
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void GFXD3D11Device::enterDebugEvent(ColorI color, const char *name) void GFXD3D11Device::enterDebugEvent(ColorI color, const char *name)

View file

@ -231,6 +231,7 @@ public:
virtual GFXCubemap *createCubemap(); virtual GFXCubemap *createCubemap();
virtual GFXCubemapArray *createCubemapArray(); virtual GFXCubemapArray *createCubemapArray();
virtual GFXTextureArray* createTextureArray();
virtual F32 getPixelShaderVersion() const { return mPixVersion; } virtual F32 getPixelShaderVersion() const { return mPixVersion; }
virtual void setPixelShaderVersion( F32 version ){ mPixVersion = version;} virtual void setPixelShaderVersion( F32 version ){ mPixVersion = version;}

View file

@ -1385,7 +1385,8 @@ void GFXD3D11Shader::_buildSamplerShaderConstantHandles( Vector<GFXShaderConstDe
AssertFatal( desc.constType == GFXSCT_Sampler || AssertFatal( desc.constType == GFXSCT_Sampler ||
desc.constType == GFXSCT_SamplerCube || desc.constType == GFXSCT_SamplerCube ||
desc.constType == GFXSCT_SamplerCubeArray, desc.constType == GFXSCT_SamplerCubeArray ||
desc.constType == GFXSCT_SamplerTextureArray,
"GFXD3D11Shader::_buildSamplerShaderConstantHandles - Invalid samplerDescription type!" ); "GFXD3D11Shader::_buildSamplerShaderConstantHandles - Invalid samplerDescription type!" );
GFXD3D11ShaderConstHandle *handle; GFXD3D11ShaderConstHandle *handle;

View file

@ -0,0 +1,266 @@
#include "gfxD3D11TextureArray.h"
#include <d3d11.h>
#include "gfxD3D11Device.h"
#include "gfxD3D11EnumTranslate.h"
#include "core/util/tVector.h"
#include "gfx/gfxDebugEvent.h"
#include "gfx/bitmap/imageUtils.h"
#include "gfx/util/screenspace.h"
#include "shaderGen/shaderFeature.h"
bool GFXD3D11TextureArray::fromTextureArray(const Vector<GFXTexHandle> &textureArray)
{
bool success = true;
Vector<ID3D11Texture2D*> texture2Ds;
texture2Ds.setSize(textureArray.size());
Vector<GFXTexHandle> tmpHandles;
mArraySize = textureArray.size();
//---------------------------------------------------------------------------------------
// Create the texture array. Each element in the texture
// array has the same format/dimensions.
//---------------------------------------------------------------------------------------
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();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// Create a resource view to the texture array.
//---------------------------------------------------------------------------------------
createResourceView(texArrayDesc.Format, texArrayDesc.MipLevels, texArrayDesc.BindFlags);
//---------------------------------------------------------------------------------------
return success;
}
void GFXD3D11TextureArray::setToTexUnit(U32 tuNum)
{
D3D11DEVICECONTEXT->PSSetShaderResources(tuNum, 1, &mSRView);
}
void GFXD3D11TextureArray::createResourceView(DXGI_FORMAT format, U32 numMipLevels, U32 usageFlags)
{
HRESULT hr;
if (usageFlags & D3D11_BIND_SHADER_RESOURCE)
{
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
if (usageFlags & D3D11_BIND_DEPTH_STENCIL)
desc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; // reads the depth
else
desc.Format = format;
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.MostDetailedMip = 0;
desc.Texture2DArray.MipLevels = numMipLevels;
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = mArraySize;
hr = D3D11DEVICE->CreateShaderResourceView(mTextureArray, &desc, &mSRView);
AssertFatal(SUCCEEDED(hr), "GFXD3D11TextureArray::CreateShaderResourceView failed to create view!");
}
if (usageFlags & D3D11_BIND_RENDER_TARGET)
{
D3D11_RENDER_TARGET_VIEW_DESC desc;
desc.Format = format;
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.MipSlice = 0;
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = mArraySize;
hr = D3D11DEVICE->CreateRenderTargetView(mTextureArray, &desc, &mRTView);
AssertFatal(SUCCEEDED(hr), "GFXD3D11TextureArray::CreateRenderTargetView failed to create view!");
}
if (usageFlags & D3D11_BIND_DEPTH_STENCIL)
{
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
desc.Format = format;
desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.MipSlice = 0;
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = mArraySize;
desc.Flags = 0;
hr = D3D11DEVICE->CreateDepthStencilView(mTextureArray, &desc, &mDSView);
AssertFatal(SUCCEEDED(hr), "GFXD3D11TextureArray::CreateDepthStencilView failed to create view!");
}
}
void GFXD3D11TextureArray::Release()
{
SAFE_RELEASE(mSRView)
SAFE_RELEASE(mRTView)
SAFE_RELEASE(mDSView)
SAFE_RELEASE(mTextureArray)
}
ID3D11ShaderResourceView* GFXD3D11TextureArray::getSRView()
{
return mSRView;
}
ID3D11RenderTargetView* GFXD3D11TextureArray::getRTView()
{
return mRTView;
}
ID3D11DepthStencilView* GFXD3D11TextureArray::getDSView()
{
return mDSView;
}
ID3D11ShaderResourceView** GFXD3D11TextureArray::getSRViewPtr()
{
return &mSRView;
}
ID3D11RenderTargetView** GFXD3D11TextureArray::getRTViewPtr()
{
return &mRTView;
}
ID3D11DepthStencilView** GFXD3D11TextureArray::getDSViewPtr()
{
return &mDSView;
}
void GFXD3D11TextureArray::zombify()
{
// Unsupported
}
void GFXD3D11TextureArray::resurrect()
{
// Unsupported
}

View file

@ -0,0 +1,51 @@
#ifndef _GFXD3D11TEXTUREARRAY_H_
#define _GFXD3D11TEXTUREARRAY_H_
#include <dxgiformat.h>
#include "gfx/gfxTextureArray.h"
#include "gfx/gfxTextureManager.h"
#include "core/util/safeRelease.h"
#include "gfxD3D11TextureManager.h"
class GFXD3D11TextureArray : public GFXTextureArray
{
public:
GFXD3D11TextureArray()
: mSRView( NULL ),
mRTView( NULL ),
mDSView( NULL ),
mTextureArray( NULL )
{
}
bool fromTextureArray(const Vector<GFXTexHandle> &textureArray) override;
void setToTexUnit(U32 tuNum) override;
void createResourceView(DXGI_FORMAT format, U32 numMipLevels, U32 usageFlags);
// GFXResource interface
void zombify() override;
void resurrect() override;
void Release() override;
ID3D11ShaderResourceView* getSRView();
ID3D11RenderTargetView* getRTView();
ID3D11DepthStencilView* getDSView();
ID3D11ShaderResourceView** getSRViewPtr();
ID3D11RenderTargetView** getRTViewPtr();
ID3D11DepthStencilView** getDSViewPtr();
private:
ID3D11ShaderResourceView* mSRView; // for shader resource input
ID3D11RenderTargetView* mRTView; // for render targets
ID3D11DepthStencilView* mDSView; //render target view for depth stencil
ID3D11Texture2D* mTextureArray;
};
#endif

View file

@ -210,8 +210,8 @@ bool GFXD3D11TextureObject::copyToBmp(GBitmap* bmp)
// check format limitations // check format limitations
// at the moment we only support RGBA for the source (other 4 byte formats should // at the moment we only support RGBA for the source (other 4 byte formats should
// be easy to add though) // be easy to add though)
AssertFatal(mFormat == GFXFormatR16G16B16A16F || mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8A8_LINEAR_FORCE || mFormat == GFXFormatR8G8B8A8_SRGB, "copyToBmp: invalid format"); AssertFatal(mFormat == GFXFormatR16G16B16A16F || mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8A8_LINEAR_FORCE || mFormat == GFXFormatR8G8B8A8_SRGB || mFormat == GFXFormatR8G8B8, "copyToBmp: invalid format");
if (mFormat != GFXFormatR16G16B16A16F && mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8A8_LINEAR_FORCE && mFormat != GFXFormatR8G8B8A8_SRGB) if (mFormat != GFXFormatR16G16B16A16F && mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8A8_LINEAR_FORCE && mFormat != GFXFormatR8G8B8A8_SRGB && mFormat != GFXFormatR8G8B8)
return false; return false;
PROFILE_START(GFXD3D11TextureObject_copyToBmp); PROFILE_START(GFXD3D11TextureObject_copyToBmp);
@ -248,6 +248,7 @@ bool GFXD3D11TextureObject::copyToBmp(GBitmap* bmp)
desc.BindFlags = 0; desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.Usage = D3D11_USAGE_STAGING; desc.Usage = D3D11_USAGE_STAGING;
desc.MiscFlags = 0;
ID3D11Texture2D* pStagingTexture = NULL; ID3D11Texture2D* pStagingTexture = NULL;
HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &pStagingTexture); HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &pStagingTexture);

View file

@ -178,6 +178,16 @@ public:
virtual void resurrect() {} virtual void resurrect() {}
}; };
class GFXNullTextureArray : public GFXTextureArray
{
public:
void zombify() override {}
void resurrect() override {}
void Release() override {}
bool fromTextureArray(const Vector<GFXTexHandle> &textureArray) override { return true; }
virtual void setToTexUnit(U32 tuNum) { }
};
class GFXNullVertexBuffer : public GFXVertexBuffer class GFXNullVertexBuffer : public GFXVertexBuffer
{ {
unsigned char* tempBuf; unsigned char* tempBuf;
@ -317,6 +327,11 @@ GFXCubemapArray* GFXNullDevice::createCubemapArray()
return new GFXNullCubemapArray(); return new GFXNullCubemapArray();
}; };
GFXTextureArray* GFXNullDevice::createTextureArray()
{
return new GFXNullTextureArray();
};
void GFXNullDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList ) void GFXNullDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
{ {
// Add the NULL renderer // Add the NULL renderer

View file

@ -130,6 +130,7 @@ protected:
public: public:
virtual GFXCubemap * createCubemap(); virtual GFXCubemap * createCubemap();
virtual GFXCubemapArray *createCubemapArray(); virtual GFXCubemapArray *createCubemapArray();
virtual GFXTextureArray *createTextureArray();
virtual F32 getFillConventionOffset() const { return 0.0f; }; virtual F32 getFillConventionOffset() const { return 0.0f; };

View file

@ -727,7 +727,7 @@ bool GBitmap::checkForTransparency()
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
LinearColorF GBitmap::sampleTexel(F32 u, F32 v) const LinearColorF GBitmap::sampleTexel(F32 u, F32 v, bool retAlpha) const
{ {
LinearColorF col(0.5f, 0.5f, 0.5f); LinearColorF col(0.5f, 0.5f, 0.5f);
// normally sampling wraps all the way around at 1.0, // normally sampling wraps all the way around at 1.0,
@ -751,6 +751,13 @@ LinearColorF GBitmap::sampleTexel(F32 u, F32 v) const
col.red = F32(buffer[lexelindex + 0]) / 255.0f; col.red = F32(buffer[lexelindex + 0]) / 255.0f;
col.green = F32(buffer[lexelindex + 1]) / 255.0f; col.green = F32(buffer[lexelindex + 1]) / 255.0f;
col.blue = F32(buffer[lexelindex + 2]) / 255.0f; col.blue = F32(buffer[lexelindex + 2]) / 255.0f;
if (retAlpha)
{
if (getHasTransparency())
col.alpha = F32(buffer[lexelindex + 3]) / 255.0f;
else
col.alpha = 1.0f;
}
} }
return col; return col;
@ -1352,7 +1359,7 @@ U32 GBitmap::getSurfaceSize(const U32 mipLevel) const
} }
DefineEngineFunction( getBitmapInfo, String, ( const char *filename ),, DefineEngineFunction( getBitmapInfo, String, ( const char *filename ),,
"Returns image info in the following format: width TAB height TAB bytesPerPixel. " "Returns image info in the following format: width TAB height TAB bytesPerPixel TAB format. "
"It will return an empty string if the file is not found.\n" "It will return an empty string if the file is not found.\n"
"@ingroup Rendering\n" ) "@ingroup Rendering\n" )
{ {
@ -1360,7 +1367,8 @@ DefineEngineFunction( getBitmapInfo, String, ( const char *filename ),,
if ( !image ) if ( !image )
return String::EmptyString; return String::EmptyString;
return String::ToString( "%d\t%d\t%d", image->getWidth(), return String::ToString( "%d\t%d\t%d\t%d", image->getWidth(),
image->getHeight(), image->getHeight(),
image->getBytesPerPixel() ); image->getBytesPerPixel(),
image->getFormat());
} }

View file

@ -205,7 +205,7 @@ public:
/// the bitmap bits and to check for alpha values less than 255 /// the bitmap bits and to check for alpha values less than 255
bool checkForTransparency(); bool checkForTransparency();
LinearColorF sampleTexel(F32 u, F32 v) const; LinearColorF sampleTexel(F32 u, F32 v, bool retAlpha = false) const;
bool getColor(const U32 x, const U32 y, ColorI& rColor) const; bool getColor(const U32 x, const U32 y, ColorI& rColor) const;
bool setColor(const U32 x, const U32 y, const ColorI& rColor); bool setColor(const U32 x, const U32 y, const ColorI& rColor);
U8 getChanelValueAt(U32 x, U32 y, U32 chan); U8 getChanelValueAt(U32 x, U32 y, U32 chan);

View file

@ -132,6 +132,8 @@ GFXDevice::GFXDevice()
mCurrentCubemap[i] = NULL; mCurrentCubemap[i] = NULL;
mNewCubemap[i] = NULL; mNewCubemap[i] = NULL;
mCurrentCubemapArray[i] = NULL; mCurrentCubemapArray[i] = NULL;
mNewTextureArray[i] = NULL;
mCurrentTextureArray[i] = NULL;
mNewCubemapArray[i] = NULL; mNewCubemapArray[i] = NULL;
mTexType[i] = GFXTDT_Normal; mTexType[i] = GFXTDT_Normal;
@ -266,6 +268,8 @@ GFXDevice::~GFXDevice()
mNewCubemap[i] = NULL; mNewCubemap[i] = NULL;
mCurrentCubemapArray[i] = NULL; mCurrentCubemapArray[i] = NULL;
mNewCubemapArray[i] = NULL; mNewCubemapArray[i] = NULL;
mCurrentTextureArray[i] = NULL;
mNewTextureArray[i] = NULL;
} }
mCurrentRT = NULL; mCurrentRT = NULL;
@ -411,6 +415,15 @@ void GFXDevice::updateStates(bool forceSetAll /*=false*/)
setTextureInternal(i, NULL); setTextureInternal(i, NULL);
} }
break; break;
case GFXTDT_TextureArray:
{
mCurrentTextureArray[i] = mNewTextureArray[i];
if (mCurrentTextureArray[i])
mCurrentTextureArray[i]->setToTexUnit(i);
else
setTextureInternal(i, NULL);
}
break;
default: default:
AssertFatal(false, "Unknown texture type!"); AssertFatal(false, "Unknown texture type!");
break; break;
@ -559,6 +572,15 @@ void GFXDevice::updateStates(bool forceSetAll /*=false*/)
setTextureInternal(i, NULL); setTextureInternal(i, NULL);
} }
break; break;
case GFXTDT_TextureArray:
{
mCurrentTextureArray[i] = mNewTextureArray[i];
if (mCurrentTextureArray[i])
mCurrentTextureArray[i]->setToTexUnit(i);
else
setTextureInternal(i, NULL);
}
break;
default: default:
AssertFatal(false, "Unknown texture type!"); AssertFatal(false, "Unknown texture type!");
break; break;
@ -801,6 +823,8 @@ void GFXDevice::setTexture( U32 stage, GFXTextureObject *texture )
mCurrentCubemap[stage] = NULL; mCurrentCubemap[stage] = NULL;
mNewCubemapArray[stage] = NULL; mNewCubemapArray[stage] = NULL;
mCurrentCubemapArray[stage] = NULL; mCurrentCubemapArray[stage] = NULL;
mNewTextureArray[stage] = NULL;
mCurrentTextureArray[stage] = NULL;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -827,6 +851,8 @@ void GFXDevice::setCubeTexture( U32 stage, GFXCubemap *cubemap )
mCurrentTexture[stage] = NULL; mCurrentTexture[stage] = NULL;
mNewCubemapArray[stage] = NULL; mNewCubemapArray[stage] = NULL;
mCurrentCubemapArray[stage] = NULL; mCurrentCubemapArray[stage] = NULL;
mNewTextureArray[stage] = NULL;
mCurrentTextureArray[stage] = NULL;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -853,6 +879,36 @@ void GFXDevice::setCubeArrayTexture(U32 stage, GFXCubemapArray *cubemapArray)
mCurrentTexture[stage] = NULL; mCurrentTexture[stage] = NULL;
mNewCubemap[stage] = NULL; mNewCubemap[stage] = NULL;
mCurrentCubemap[stage] = NULL; mCurrentCubemap[stage] = NULL;
mNewTextureArray[stage] = NULL;
mCurrentTextureArray[stage] = NULL;
}
//-----------------------------------------------------------------------------
// Set texture array
//-----------------------------------------------------------------------------
void GFXDevice::setTextureArray(U32 stage, GFXTextureArray *textureArray)
{
AssertFatal(stage < getNumSamplers(), avar("GFXDevice::setTextureArray - out of range stage! %i>%i", stage, getNumSamplers()));
if (mTexType[stage] == GFXTDT_TextureArray &&
((mTextureDirty[stage] && mNewTextureArray[stage].getPointer() == textureArray) ||
(!mTextureDirty[stage] && mCurrentTextureArray[stage].getPointer() == textureArray)))
return;
mStateDirty = true;
mTexturesDirty = true;
mTextureDirty[stage] = true;
mNewTextureArray[stage] = textureArray;
mTexType[stage] = GFXTDT_TextureArray;
// Clear out textures
mNewTexture[stage] = NULL;
mCurrentTexture[stage] = NULL;
mNewCubemap[stage] = NULL;
mCurrentCubemap[stage] = NULL;
mNewCubemapArray[stage] = NULL;
mCurrentCubemapArray[stage] = NULL;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View file

@ -57,6 +57,7 @@
#ifndef _PLATFORM_PLATFORMTIMER_H_ #ifndef _PLATFORM_PLATFORMTIMER_H_
#include "platform/platformTimer.h" #include "platform/platformTimer.h"
#endif #endif
#include "gfxTextureArray.h"
class FontRenderBatcher; class FontRenderBatcher;
class GFont; class GFont;
@ -498,7 +499,8 @@ protected:
{ {
GFXTDT_Normal, GFXTDT_Normal,
GFXTDT_Cube, GFXTDT_Cube,
GFXTDT_CubeArray GFXTDT_CubeArray,
GFXTDT_TextureArray
}; };
GFXTexHandle mCurrentTexture[TEXTURE_STAGE_COUNT]; GFXTexHandle mCurrentTexture[TEXTURE_STAGE_COUNT];
@ -507,6 +509,8 @@ protected:
GFXCubemapHandle mNewCubemap[TEXTURE_STAGE_COUNT]; GFXCubemapHandle mNewCubemap[TEXTURE_STAGE_COUNT];
GFXCubemapArrayHandle mCurrentCubemapArray[TEXTURE_STAGE_COUNT]; GFXCubemapArrayHandle mCurrentCubemapArray[TEXTURE_STAGE_COUNT];
GFXCubemapArrayHandle mNewCubemapArray[TEXTURE_STAGE_COUNT]; GFXCubemapArrayHandle mNewCubemapArray[TEXTURE_STAGE_COUNT];
GFXTextureArrayHandle mCurrentTextureArray[TEXTURE_STAGE_COUNT];
GFXTextureArrayHandle mNewTextureArray[TEXTURE_STAGE_COUNT];
TexDirtyType mTexType[TEXTURE_STAGE_COUNT]; TexDirtyType mTexType[TEXTURE_STAGE_COUNT];
bool mTextureDirty[TEXTURE_STAGE_COUNT]; bool mTextureDirty[TEXTURE_STAGE_COUNT];
@ -757,6 +761,7 @@ protected:
public: public:
virtual GFXCubemap * createCubemap() = 0; virtual GFXCubemap * createCubemap() = 0;
virtual GFXCubemapArray *createCubemapArray() = 0; virtual GFXCubemapArray *createCubemapArray() = 0;
virtual GFXTextureArray *createTextureArray() = 0;
inline GFXTextureManager *getTextureManager() inline GFXTextureManager *getTextureManager()
{ {
@ -952,6 +957,7 @@ public:
void setTexture(U32 stage, GFXTextureObject *texture); void setTexture(U32 stage, GFXTextureObject *texture);
void setCubeTexture( U32 stage, GFXCubemap *cubemap ); void setCubeTexture( U32 stage, GFXCubemap *cubemap );
void setCubeArrayTexture( U32 stage, GFXCubemapArray *cubemapArray); void setCubeArrayTexture( U32 stage, GFXCubemapArray *cubemapArray);
void setTextureArray( U32 stage, GFXTextureArray *textureArray);
inline GFXTextureObject* getCurrentTexture( U32 stage ) { return mCurrentTexture[stage]; } inline GFXTextureObject* getCurrentTexture( U32 stage ) { return mCurrentTexture[stage]; }
/// @} /// @}

View file

@ -599,7 +599,8 @@ enum GFXShaderConstType
// Samplers // Samplers
GFXSCT_Sampler, GFXSCT_Sampler,
GFXSCT_SamplerCube, GFXSCT_SamplerCube,
GFXSCT_SamplerCubeArray GFXSCT_SamplerCubeArray,
GFXSCT_SamplerTextureArray
}; };

View file

@ -0,0 +1,7 @@
#include "gfxTextureArray.h"
const String GFXTextureArray::describeSelf() const
{
// We've got nothing
return String();
}

View file

@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _GFXTEXTUREARRAY_H_
#define _GFXTEXTUREARRAY_H_
#ifndef _REFBASE_H_
#include "core/util/refBase.h"
#endif
#ifndef _GFXRESOURCE_H_
#include "gfx/gfxResource.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfxEnums.h"
#endif
#ifndef _GFXTEXTUREHANDLE_H_
#include "gfxTextureHandle.h"
#endif
class GFXTextureProfile;
class GFXTextureObject;
class GFXTextureArray : public StrongRefBase, public GFXResource
{
public:
virtual bool fromTextureArray(const Vector<GFXTexHandle> &textureArray) = 0;
virtual void setToTexUnit(U32 tuNum) = 0;
// GFXResource interface
virtual void zombify() = 0;
virtual void resurrect() = 0;
virtual void Release() = 0;
virtual const String describeSelf() const;
U32 mArraySize;
};
/// A reference counted handle to a texture array resource.
class GFXTextureArrayHandle : public StrongRefPtr<GFXTextureArray>
{
public:
GFXTextureArrayHandle() {}
GFXTextureArrayHandle(GFXTextureArray* textureArray) { StrongRefPtr<GFXTextureArray>::set(textureArray); }
/// Releases the texture handle.
void free() { StrongObjectRef::set(NULL); }
};
#endif // _GFXTEXTUREARRAY_H_

View file

@ -894,6 +894,42 @@ Torque::Path GFXTextureManager::validatePath(const Torque::Path &path)
return correctPath; return correctPath;
} }
GBitmap *GFXTextureManager::loadUncompressedTexture(const Torque::Path &path, GFXTextureProfile *profile, U32 width, U32 height)
{
GBitmap* inBitmap = loadUncompressedTexture(path, &GFXTexturePersistentProfile);
if (inBitmap == NULL)
{
Con::warnf("GFXTextureManager::loadUncompressedTexture unable to load texture: %s", path.getFullPath());
return NULL;
}
// Set the format so we don't have to handle which channels are where.
if (!inBitmap->setFormat(GFXFormatR8G8B8A8))
{
Con::warnf("GFXTextureManager::loadUncompressedTexture unable to handle texture format: %s", path.getFullPath());
return NULL;
}
GBitmap* outBmp = new GBitmap(width, height, true, GFXFormatR8G8B8A8);
U8* oBits = (U8*)outBmp->getWritableBits();
for (S32 y = 0; y < width; y++)
{
for (S32 x = 0; x < height; x++)
{
ColorI texelColor = inBitmap->sampleTexel(x / F32(width), y / F32(height), true).toColorI(true);
oBits[(y * width + x) * 4] = texelColor.red;
oBits[(y * width + x) * 4 + 1] = texelColor.green;
oBits[(y * width + x) * 4 + 2] = texelColor.blue;
oBits[(y * width + x) * 4 + 3] = texelColor.alpha;
}
}
return outBmp;
}
GBitmap *GFXTextureManager::loadUncompressedTexture(const Torque::Path &path, GFXTextureProfile *profile) GBitmap *GFXTextureManager::loadUncompressedTexture(const Torque::Path &path, GFXTextureProfile *profile)
{ {
PROFILE_SCOPE(GFXTextureManager_loadUncompressedTexture); PROFILE_SCOPE(GFXTextureManager_loadUncompressedTexture);

View file

@ -41,6 +41,7 @@
#ifndef _TSIGNAL_H_ #ifndef _TSIGNAL_H_
#include "core/util/tSignal.h" #include "core/util/tSignal.h"
#endif #endif
#include "gfxTextureHandle.h"
namespace Torque namespace Torque
@ -131,6 +132,7 @@ public:
S32 antialiasLevel); S32 antialiasLevel);
Torque::Path validatePath(const Torque::Path &path); Torque::Path validatePath(const Torque::Path &path);
GBitmap *loadUncompressedTexture(const Torque::Path& path, GFXTextureProfile* profile, U32 width, U32 height);
GBitmap *loadUncompressedTexture(const Torque::Path &path, GFXTextureProfile *profile); GBitmap *loadUncompressedTexture(const Torque::Path &path, GFXTextureProfile *profile);
virtual GFXTextureObject *createCompositeTexture(const Torque::Path &pathR, const Torque::Path &pathG, const Torque::Path &pathB, const Torque::Path &pathA, U32 inputKey[4], virtual GFXTextureObject *createCompositeTexture(const Torque::Path &pathR, const Torque::Path &pathG, const Torque::Path &pathB, const Torque::Path &pathA, U32 inputKey[4],
GFXTextureProfile *profile); GFXTextureProfile *profile);

View file

@ -22,6 +22,8 @@
#include "platform/platform.h" #include "platform/platform.h"
#include "gfx/gl/gfxGLDevice.h" #include "gfx/gl/gfxGLDevice.h"
#include "gfxGLTextureArray.h"
#include "platform/platformGL.h" #include "platform/platformGL.h"
#include "gfx/gfxCubemap.h" #include "gfx/gfxCubemap.h"
@ -457,6 +459,13 @@ GFXCubemapArray *GFXGLDevice::createCubemapArray()
return cubeArray; return cubeArray;
} }
GFXTextureArray* GFXGLDevice::createTextureArray()
{
GFXGLTextureArray* textureArray = new GFXGLTextureArray();
textureArray->registerResourceWithDevice(this);
return textureArray;
}
void GFXGLDevice::endSceneInternal() void GFXGLDevice::endSceneInternal()
{ {
// nothing to do for opengl // 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 ) void GFXGLDevice::setMatrix( GFXMatrixType mtype, const MatrixF &mat )
{ {
// ONLY NEEDED ON FFP // ONLY NEEDED ON FFP

View file

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

View file

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

View file

@ -20,11 +20,11 @@ public:
class TextureUnit class TextureUnit
{ {
public: 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 /// after glBindTexture
@ -48,6 +48,9 @@ public:
case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY:
mTextureUnits[mActiveTexture].mTextureCubeArray = handle; mTextureUnits[mActiveTexture].mTextureCubeArray = handle;
break; break;
case GL_TEXTURE_2D_ARRAY:
mTextureUnits[mActiveTexture].mTextureArray = handle;
break;
default: default:
AssertFatal(0, avar("GFXGLStateCache::setCacheBindedTex - binding (%x) not supported.", biding) ); AssertFatal(0, avar("GFXGLStateCache::setCacheBindedTex - binding (%x) not supported.", biding) );
return; return;
@ -74,6 +77,9 @@ public:
case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY:
mTextureUnits[mActiveTexture].mTextureCubeArray = handle; mTextureUnits[mActiveTexture].mTextureCubeArray = handle;
break; break;
case GL_TEXTURE_2D_ARRAY:
mTextureUnits[mActiveTexture].mTextureArray = handle;
break;
case GL_FRAMEBUFFER: case GL_FRAMEBUFFER:
mBindedFBO_W = mBindedFBO_R = handle; mBindedFBO_W = mBindedFBO_R = handle;
break; break;
@ -109,6 +115,8 @@ public:
return mTextureUnits[mActiveTexture].mTextureCube; return mTextureUnits[mActiveTexture].mTextureCube;
case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY:
return mTextureUnits[mActiveTexture].mTextureCubeArray; return mTextureUnits[mActiveTexture].mTextureCubeArray;
case GL_TEXTURE_2D_ARRAY:
return mTextureUnits[mActiveTexture].mTextureArray;
case GL_DRAW_FRAMEBUFFER: case GL_DRAW_FRAMEBUFFER:
return mBindedFBO_W; return mBindedFBO_W;
case GL_READ_FRAMEBUFFER: case GL_READ_FRAMEBUFFER:

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() \ #define PRESERVE_CUBEMAP_ARRAY_TEXTURE() \
GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, (GFXGLPreserveInteger::BindFn)glBindTexture) 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) \ #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 ) binding == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : (binding == GL_TEXTURE_3D ? GL_TEXTURE_BINDING_3D : GL_TEXTURE_BINDING_1D )

View file

@ -80,6 +80,29 @@ void EchoOp::print( Stream &stream )
WRITESTR( mStatement ); WRITESTR( mStatement );
} }
//**************************************************************************
// Index operation
//**************************************************************************
IndexOp::IndexOp( Var* var, U32 index ) : Parent( NULL, NULL )
{
mInput[0] = var;
mIndex = index;
}
//--------------------------------------------------------------------------
// Print
//--------------------------------------------------------------------------
void IndexOp::print( Stream &stream )
{
Var* var = dynamic_cast<Var*>(mInput[0]);
mInput[0]->print(stream);
if (var->arraySize > 1)
{
WRITESTR(String::ToString("[%d]", mIndex));
}
}
//************************************************************************** //**************************************************************************
// General operation // General operation

View file

@ -110,6 +110,21 @@ public:
virtual void print( Stream &stream ); virtual void print( Stream &stream );
}; };
//----------------------------------------------------------------------------
/*!
Accesses the given index on the variable
*/
//----------------------------------------------------------------------------
class IndexOp : public ShaderOp
{
typedef ShaderOp Parent;
U32 mIndex;
public:
IndexOp( Var* var, U32 index );
virtual void print( Stream &stream );
};
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/*! /*!

View file

@ -48,7 +48,6 @@ namespace
FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new NamedFeatureGLSL("TerrainMacroMap Deprecated")); // new TerrainMacroMapFeatGLSL); FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new NamedFeatureGLSL("TerrainMacroMap Deprecated")); // new TerrainMacroMapFeatGLSL);
FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL ); FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL );
FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) ); FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) );
FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL );
FEATUREMGR->registerFeature( MFT_TerrainORMMap, new TerrainORMMapFeatGLSL ); FEATUREMGR->registerFeature( MFT_TerrainORMMap, new TerrainORMMapFeatGLSL );
FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatGLSL ); FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatGLSL );
} }
@ -124,69 +123,90 @@ Var* TerrainFeatGLSL::_getInMacroCoord( Vector<ShaderComponent*> &componentList
return inDet; return inDet;
} }
Var* TerrainFeatGLSL::_getNormalMapTex() Var* TerrainFeatGLSL::_getDetailMapSampler()
{ {
String name( String::ToString( "normalMap%d", getProcessIndex() ) ); String name("detailMapSampler");
Var *normalMap = (Var*)LangElement::find( name ); Var* detailMapSampler = (Var*)LangElement::find(name);
if ( !normalMap ) if (!detailMapSampler)
{ {
normalMap = new Var; detailMapSampler = new Var;
normalMap->setType( "sampler2D" ); detailMapSampler->setName(name);
normalMap->setName( name ); detailMapSampler->setType("sampler2DArray");
normalMap->uniform = true; detailMapSampler->uniform = true;
normalMap->sampler = true; detailMapSampler->sampler = true;
normalMap->constNum = Var::getTexUnitNum(); detailMapSampler->constNum = Var::getTexUnitNum();
} }
return normalMap; return detailMapSampler;
} }
Var* TerrainFeatGLSL::_getORMConfigMapTex() Var* TerrainFeatGLSL::_getNormalMapSampler()
{ {
String name(String::ToString("ormConfigMap%d", getProcessIndex())); String name("normalMapSampler");
Var *ormConfigMap = (Var*)LangElement::find(name); Var* normalMapSampler = (Var*)LangElement::find(name);
if (!ormConfigMap) if (!normalMapSampler)
{ {
ormConfigMap = new Var; normalMapSampler = new Var;
ormConfigMap->setType("sampler2D"); normalMapSampler->setName(name);
ormConfigMap->setName(name); normalMapSampler->setType("sampler2DArray");
ormConfigMap->uniform = true; normalMapSampler->uniform = true;
ormConfigMap->sampler = true; normalMapSampler->sampler = true;
ormConfigMap->constNum = Var::getTexUnitNum(); normalMapSampler->constNum = Var::getTexUnitNum();
} }
return ormConfigMap; return normalMapSampler;
}
Var* TerrainFeatGLSL::_getOrmMapSampler()
{
String name("ormMapSampler");
Var* ormMapSampler = (Var*)LangElement::find(name);
if (!ormMapSampler)
{
ormMapSampler = new Var;
ormMapSampler->setName(name);
ormMapSampler->setType("sampler2DArray");
ormMapSampler->uniform = true;
ormMapSampler->sampler = true;
ormMapSampler->constNum = Var::getTexUnitNum();
}
return ormMapSampler;
} }
Var* TerrainFeatGLSL::_getDetailIdStrengthParallax() Var* TerrainFeatGLSL::_getDetailIdStrengthParallax()
{ {
String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) ); String name(String::ToString("detailIdStrengthParallax", getProcessIndex()));
Var *detailInfo = (Var*)LangElement::find( name ); Var* detailInfo = (Var*)LangElement::find(name);
if ( !detailInfo ) if (!detailInfo)
{ {
detailInfo = new Var; detailInfo = new Var;
detailInfo->setType( "vec3" ); detailInfo->setType("vec4");
detailInfo->setName( name ); detailInfo->setName(name);
detailInfo->uniform = true; detailInfo->uniform = true;
detailInfo->constSortPos = cspPotentialPrimitive; detailInfo->constSortPos = cspPotentialPrimitive;
detailInfo->arraySize = getProcessIndex();
} }
detailInfo->arraySize = mMax(detailInfo->arraySize, getProcessIndex() + 1);
return detailInfo; return detailInfo;
} }
Var* TerrainFeatGLSL::_getMacroIdStrengthParallax() Var* TerrainFeatGLSL::_getMacroIdStrengthParallax()
{ {
String name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) ); String name(String::ToString("macroIdStrengthParallax%d", getProcessIndex()));
Var *detailInfo = (Var*)LangElement::find( name ); Var* detailInfo = (Var*)LangElement::find(name);
if ( !detailInfo ) if (!detailInfo)
{ {
detailInfo = new Var; detailInfo = new Var;
detailInfo->setType( "vec3" ); detailInfo->setType("vec3");
detailInfo->setName( name ); detailInfo->setName(name);
detailInfo->uniform = true; detailInfo->uniform = true;
detailInfo->constSortPos = cspPotentialPrimitive; detailInfo->constSortPos = cspPotentialPrimitive;
} }
@ -377,11 +397,17 @@ void TerrainDetailMapFeatGLSL::processVert( Vector<ShaderComponent*> &component
outTex->setType( "vec4" ); outTex->setType( "vec4" );
// Get the detail scale and fade info. // Get the detail scale and fade info.
Var *detScaleAndFade = new Var; Var *detScaleAndFade = (Var*)LangElement::find("detailScaleAndFade");
detScaleAndFade->setType( "vec4" ); if (!detScaleAndFade)
detScaleAndFade->setName( String::ToString( "detailScaleAndFade%d", detailIndex ) ); {
detScaleAndFade = new Var;
detScaleAndFade->setType("vec4");
detScaleAndFade->setName("detailScaleAndFade");
detScaleAndFade->uniform = true; detScaleAndFade->uniform = true;
detScaleAndFade->constSortPos = cspPotentialPrimitive; detScaleAndFade->constSortPos = cspPotentialPrimitive;
}
detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1);
// Setup the detail coord. // Setup the detail coord.
// //
@ -392,11 +418,11 @@ void TerrainDetailMapFeatGLSL::processVert( Vector<ShaderComponent*> &component
// //
// See TerrainBaseMapFeatGLSL::processVert(). // See TerrainBaseMapFeatGLSL::processVert().
// //
meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) ); meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex) ) );
// And sneak the detail fade thru the w detailCoord. // And sneak the detail fade thru the w detailCoord.
meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, detScaleAndFade, dist, detScaleAndFade ) ); outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)) );
output = meta; output = meta;
} }
@ -473,7 +499,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
// Calculate the blend for this detail texture. // Calculate the blend for this detail texture.
meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) ); new DecOp( detailBlend ), new IndexOp(detailInfo, detailIndex), inTex, layerSize, layerSample ) );
// New terrain // New terrain
@ -525,15 +551,10 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
} }
// Get the detail texture. // Get the detail texture.
Var *detailMap = new Var; Var *detailMap = _getDetailMapSampler();
detailMap->setType("sampler2D");
detailMap->setName(String::ToString("detailMap%d", detailIndex));
detailMap->uniform = true;
detailMap->sampler = true;
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
// Get the normal map texture. // Get the normal map texture.
Var *normalMap = _getNormalMapTex(); Var *normalMap = _getNormalMapSampler();
// Issue happens somewhere here ----- // Issue happens somewhere here -----
@ -541,8 +562,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
// //
// We take two normal samples and lerp between them for // We take two normal samples and lerp between them for
// side projection layers... else a single sample. // side projection layers... else a single sample.
LangElement *texOp; //
// Note that we're doing the standard greyscale detail // Note that we're doing the standard greyscale detail
// map technique here which can darken and lighten the // map technique here which can darken and lighten the
// diffuse texture. // diffuse texture.
@ -552,35 +572,17 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
// //
if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
{ {
meta->addStatement(new GenOp(" @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet, detailMap, inDet, inTex)); detailColor, detailMap, inDet, new IndexOp(detailInfo, detailIndex), detailMap, inDet, new IndexOp(detailInfo, detailIndex), inTex));
texOp = new GenOp("lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
normalMap, inDet, normalMap, inDet, inTex);
} }
else else
{ {
meta->addStatement(new GenOp(" @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( tex2D( @, vec3(@.xy, @.x) ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet)); detailColor, detailMap, inDet, new IndexOp(detailInfo, detailIndex)));
texOp = new GenOp("tex2D(@, @.xy)", normalMap, inDet);
} }
// New terrain // New terrain
// Get a var and accumulate the blend amount.
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
if ( !blendTotal )
{
blendTotal = new Var;
blendTotal->setName( "blendTotal" );
blendTotal->setType( "float" );
meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
}
// Add to the blend total.
meta->addStatement(new GenOp(" @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend));
// If we had a parallax feature... then factor in the parallax // If we had a parallax feature... then factor in the parallax
// amount so that it fades out with the layer blending. // amount so that it fades out with the layer blending.
if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) ) if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) )
@ -588,13 +590,13 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
// Call the library function to do the rest. // Call the library function to do the rest.
if (fd.features.hasFeature(MFT_IsBC3nm, detailIndex)) if (fd.features.hasFeature(MFT_IsBC3nm, detailIndex))
{ {
meta->addStatement(new GenOp(" @.xy += parallaxOffsetDxtnm( @, @.xy, @, @.z * @ );\r\n", meta->addStatement(new GenOp(" @.xy += parallaxOffsetDxtnm( @, vec3(@.xy, @.x), @, @.z * @ );\r\n",
inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend)); inDet, normalMap, inDet, new IndexOp(detailInfo, detailIndex), negViewTS, new IndexOp(detailInfo, detailIndex), detailBlend));
} }
else else
{ {
meta->addStatement(new GenOp(" @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n", meta->addStatement(new GenOp(" @.xy += parallaxOffset( @, vec3(@.xy, @.x), @, @.z * @ );\r\n",
inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend)); inDet, normalMap, inDet, new IndexOp(detailInfo, detailIndex), negViewTS, new IndexOp(detailInfo, detailIndex), detailBlend));
} }
} }
@ -632,17 +634,17 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
// //
if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) ) if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
{ {
meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet, detailMap, inDet, inTex ) ); detailColor, detailMap, inDet, new IndexOp(detailInfo, detailIndex), detailMap, inDet, new IndexOp(detailInfo, detailIndex), inTex ) );
} }
else else
{ {
meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", meta->addStatement( new GenOp( " @ = ( tex2D( @, vec3(@.xy, @.x) ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet ) ); detailColor, detailMap, inDet, new IndexOp(detailInfo, detailIndex)) );
} }
meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
detailColor, detailInfo, inDet ) ); detailColor, new IndexOp(detailInfo, detailIndex), inDet ) );
meta->addStatement(new GenOp(" @.rgb = toGamma(@.rgb);\r\n", outColor, outColor)); meta->addStatement(new GenOp(" @.rgb = toGamma(@.rgb);\r\n", outColor, outColor));
@ -666,26 +668,13 @@ ShaderFeature::Resources TerrainDetailMapFeatGLSL::getResources( const MaterialF
// If this is the first detail pass then we // If this is the first detail pass then we
// samples from the layer tex. // samples from the layer tex.
res.numTex += 1; res.numTex += 1;
// If this material also does parallax then it
// will generate the negative view vector and the
// worldToTanget transform.
if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) )
res.numTexReg += 4;
}
// sample from the detail texture for diffuse coloring.
res.numTex += 1;
// If we have parallax for this layer then we'll also
// be sampling the normal map for the parallax heightmap.
if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) )
res.numTex += 1;
// Finally we always send the detail texture
// coord to the pixel shader.
res.numTexReg += 1; res.numTexReg += 1;
// Texture Array
res.numTex += 1;
res.numTexReg += 1;
}
return res; return res;
} }
@ -836,20 +825,6 @@ void TerrainMacroMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentL
meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) ); new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
// Get a var and accumulate the blend amount.
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
if ( !blendTotal )
{
blendTotal = new Var;
//blendTotal->setName( "blendTotal" );
blendTotal->setName( "blendTotal" );
blendTotal->setType( "float" );
meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
}
// Add to the blend total.
meta->addStatement(new GenOp(" @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend));
Var *detailColor = (Var*)LangElement::find( "macroColor" ); Var *detailColor = (Var*)LangElement::find( "macroColor" );
if ( !detailColor ) if ( !detailColor )
{ {
@ -992,11 +967,12 @@ void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
meta->addStatement( new GenOp( " {\r\n" ) ); meta->addStatement( new GenOp( " {\r\n" ) );
// Get the normal map texture. // Get the normal map texture.
Var *normalMap = _getNormalMapTex(); Var *normalMap = _getNormalMapSampler();
/// Get the texture coord. /// Get the texture coord.
Var *inDet = _getInDetailCoord( componentList ); Var *inDet = _getInDetailCoord( componentList );
Var *inTex = getVertTexCoord( "texCoord" ); Var *inTex = getVertTexCoord( "texCoord" );
Var* detailInfo = _getDetailIdStrengthParallax();
// Sample the normal map. // Sample the normal map.
// //
@ -1005,11 +981,11 @@ void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
LangElement *texOp; LangElement *texOp;
if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) ) if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) )
{ {
texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )", texOp = new GenOp( "lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z )",
normalMap, inDet, normalMap, inDet, inTex ); normalMap, inDet, new IndexOp(detailInfo, normalIndex), normalMap, inDet, inTex, new IndexOp(detailInfo, normalIndex));
} }
else else
texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet ); texOp = new GenOp( String::ToString("tex2D(@, vec3(@.xy, @.x))", normalIndex), normalMap, inDet, new IndexOp(detailInfo, normalIndex));
// create bump normal // create bump normal
Var *bumpNorm = new Var; Var *bumpNorm = new Var;
@ -1019,26 +995,11 @@ void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
LangElement *bumpNormDecl = new DecOp( bumpNorm ); LangElement *bumpNormDecl = new DecOp( bumpNorm );
meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) ); meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
// If this is the last normal map then we
// can test to see the total blend value
// to see if we should clip the result.
Var* blendTotal = (Var*)LangElement::find("blendTotal");
if (blendTotal)
{
if (fd.features.getNextFeatureIndex(MFT_TerrainNormalMap, normalIndex) == -1)
meta->addStatement(new GenOp(" if ( @ > 0.0001f ){\r\n\r\n", blendTotal));
}
// Normalize is done later... // Normalize is done later...
// Note: The reverse mul order is intentional. Affine matrix. // Note: The reverse mul order is intentional. Affine matrix.
meta->addStatement(new GenOp(" @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n", meta->addStatement(new GenOp(" @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n",
gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet)); gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet));
if (blendTotal)
{
if (fd.features.getNextFeatureIndex(MFT_TerrainNormalMap, normalIndex) == -1)
meta->addStatement(new GenOp(" }\r\n"));
}
// End the conditional block. // End the conditional block.
meta->addStatement( new GenOp( " }\r\n" ) ); meta->addStatement( new GenOp( " }\r\n" ) );
@ -1049,6 +1010,13 @@ ShaderFeature::Resources TerrainNormalMapFeatGLSL::getResources( const MaterialF
{ {
Resources res; Resources res;
if (getProcessIndex() == 0)
{
// Texture Array
res.numTex += 1;
res.numTexReg += 1;
}
// We only need to process normals during the deferred. // We only need to process normals during the deferred.
if ( fd.features.hasFeature( MFT_DeferredConditioner ) ) if ( fd.features.hasFeature( MFT_DeferredConditioner ) )
{ {
@ -1107,35 +1075,6 @@ ShaderFeature::Resources TerrainLightMapFeatGLSL::getResources( const MaterialFe
return res; return res;
} }
void TerrainAdditiveFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
Var *color = NULL;
Var* norm = NULL;
if (fd.features[MFT_isDeferred])
{
color = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1));
norm = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
}
color = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
if ( !color || !blendTotal )
return;
MultiLine *meta = new MultiLine;
meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) );
meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) );
if (fd.features[MFT_isDeferred])
{
meta->addStatement(new GenOp(" @.a = @;\r\n", norm, blendTotal));
}
output = meta;
}
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO), //standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
//.b = specular strength, a= spec power. //.b = specular strength, a= spec power.
@ -1197,21 +1136,25 @@ void TerrainORMMapFeatGLSL::processVert(Vector<ShaderComponent*> &componentList,
Var *outTex = (Var*)LangElement::find(String::ToString("detCoord%d", detailIndex)); Var *outTex = (Var*)LangElement::find(String::ToString("detCoord%d", detailIndex));
if (outTex == NULL) if (outTex == NULL)
{ {
outTex = new Var;
outTex = connectComp->getElement(RT_TEXCOORD); outTex = connectComp->getElement(RT_TEXCOORD);
outTex->setName(String::ToString("detCoord%d", detailIndex)); outTex->setName(String::ToString("detCoord%d", detailIndex));
outTex->setStructName("OUT"); outTex->setStructName("OUT");
outTex->setType("vec4"); outTex->setType("vec4");
} }
// Get the detail scale and fade info. // Get the detail scale and fade info.
Var *detScaleAndFade = (Var*)LangElement::find(String::ToString("detailScaleAndFade%d", detailIndex)); Var *detScaleAndFade = (Var*)LangElement::find("detailScaleAndFade");
if (detScaleAndFade == NULL) if (detScaleAndFade == NULL)
{ {
detScaleAndFade = new Var;
detScaleAndFade->setType("vec4"); detScaleAndFade->setType("vec4");
detScaleAndFade->setName(String::ToString("detailScaleAndFade%d", detailIndex)); detScaleAndFade->setName("detailScaleAndFade");
detScaleAndFade->uniform = true; detScaleAndFade->uniform = true;
detScaleAndFade->constSortPos = cspPotentialPrimitive; detScaleAndFade->constSortPos = cspPotentialPrimitive;
} }
detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1);
// Setup the detail coord. // Setup the detail coord.
// //
// NOTE: You see here we scale the texture coord by 'xyx' // NOTE: You see here we scale the texture coord by 'xyx'
@ -1221,11 +1164,11 @@ void TerrainORMMapFeatGLSL::processVert(Vector<ShaderComponent*> &componentList,
// //
// See TerrainBaseMapFeatGLSL::processVert(). // See TerrainBaseMapFeatGLSL::processVert().
// //
meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade)); meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex)));
// And sneak the detail fade thru the w detailCoord. // And sneak the detail fade thru the w detailCoord.
meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, detScaleAndFade, dist, detScaleAndFade)); outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)));
output = meta; output = meta;
} }
@ -1241,9 +1184,10 @@ void TerrainORMMapFeatGLSL::processPix(Vector<ShaderComponent*> &componentList,
/// Get the texture coord. /// Get the texture coord.
Var *inDet = _getInDetailCoord(componentList); Var *inDet = _getInDetailCoord(componentList);
Var *inTex = getVertTexCoord("texCoord"); Var *inTex = getVertTexCoord("texCoord");
Var* detailInfo = _getDetailIdStrengthParallax();
const S32 compositeIndex = getProcessIndex(); const S32 compositeIndex = getProcessIndex();
Var *ormConfigMap = _getORMConfigMapTex(); Var *ormConfigMap = _getOrmMapSampler();
// Sample the normal map. // Sample the normal map.
// //
// We take two normal samples and lerp between them for // We take two normal samples and lerp between them for
@ -1252,11 +1196,11 @@ void TerrainORMMapFeatGLSL::processPix(Vector<ShaderComponent*> &componentList,
if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex))
{ {
texOp = new GenOp("lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )", texOp = new GenOp("lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z )",
ormConfigMap, inDet, ormConfigMap, inDet, inTex); ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex), ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex), inTex);
} }
else else
texOp = new GenOp("tex2D(@, @.xy)", ormConfigMap, inDet); texOp = new GenOp("tex2D(@, vec3(@.xy, @.x))", ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex));
// search for material var // search for material var
Var * ormConfig; Var * ormConfig;

View file

@ -44,9 +44,9 @@ public:
Var* _getInMacroCoord(Vector<ShaderComponent*> &componentList ); Var* _getInMacroCoord(Vector<ShaderComponent*> &componentList );
Var* _getNormalMapTex(); Var* _getDetailMapSampler();
Var* _getNormalMapSampler();
Var* _getORMConfigMapTex(); Var* _getOrmMapSampler();
static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp ); static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp );
@ -151,17 +151,6 @@ public:
virtual String getName() { return "Terrain Lightmap Texture"; } virtual String getName() { return "Terrain Lightmap Texture"; }
}; };
class TerrainAdditiveFeatGLSL : public TerrainFeatGLSL
{
public:
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual String getName() { return "Terrain Additive"; }
};
class TerrainORMMapFeatGLSL : public TerrainFeatGLSL class TerrainORMMapFeatGLSL : public TerrainFeatGLSL
{ {
public: public:

View file

@ -48,7 +48,6 @@ namespace
FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new NamedFeatureHLSL("TerrainMacroMap Deprecated")); // new TerrainMacroMapFeatHLSL); FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new NamedFeatureHLSL("TerrainMacroMap Deprecated")); // new TerrainMacroMapFeatHLSL);
FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL );
FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) ); FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) );
FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL );
FEATUREMGR->registerFeature( MFT_TerrainORMMap, new TerrainORMMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainORMMap, new TerrainORMMapFeatHLSL );
FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatHLSL );
} }
@ -123,56 +122,131 @@ Var* TerrainFeatHLSL::_getInMacroCoord( Vector<ShaderComponent*> &componentList
return inDet; return inDet;
} }
Var* TerrainFeatHLSL::_getNormalMapTex() Var* TerrainFeatHLSL::_getDetailMapSampler()
{ {
String name(String::ToString("normalMap%d", getProcessIndex())); String name("detailMapSampler");
Var *normalMap = (Var*)LangElement::find(name); Var* detailMapSampler = (Var*)LangElement::find(name);
if (!normalMap) if(!detailMapSampler)
{ {
normalMap = new Var; detailMapSampler = new Var;
normalMap->setType("SamplerState"); detailMapSampler->setName(name);
normalMap->setName(name); detailMapSampler->setType("SamplerState");
normalMap->uniform = true; detailMapSampler->uniform = true;
normalMap->sampler = true; detailMapSampler->sampler = true;
normalMap->constNum = Var::getTexUnitNum(); detailMapSampler->constNum = Var::getTexUnitNum();
} }
return normalMap; return detailMapSampler;
} }
Var* TerrainFeatHLSL::_getORMConfigMapTex() Var* TerrainFeatHLSL::_getDetailMapArray()
{ {
String name(String::ToString("ormConfigMap%d", getProcessIndex())); String name("detailMapArray");
Var *ormConfigMap = (Var*)LangElement::find(name); Var* detailMapArray = (Var*)LangElement::find(name);
if (!ormConfigMap) if(!detailMapArray)
{ {
ormConfigMap = new Var; detailMapArray = new Var;
ormConfigMap->setType("SamplerState"); detailMapArray->setName(name);
ormConfigMap->setName(name); detailMapArray->setType("Texture2DArray");
ormConfigMap->uniform = true; detailMapArray->uniform = true;
ormConfigMap->sampler = true; detailMapArray->texture = true;
ormConfigMap->constNum = Var::getTexUnitNum(); detailMapArray->constNum = _getDetailMapSampler()->constNum;
} }
return ormConfigMap; return detailMapArray;
}
Var* TerrainFeatHLSL::_getNormalMapSampler()
{
String name("normalMapSampler");
Var* normalMapSampler = (Var*)LangElement::find(name);
if (!normalMapSampler)
{
normalMapSampler = new Var;
normalMapSampler->setName(name);
normalMapSampler->setType("SamplerState");
normalMapSampler->uniform = true;
normalMapSampler->sampler = true;
normalMapSampler->constNum = Var::getTexUnitNum();
}
return normalMapSampler;
}
Var* TerrainFeatHLSL::_getNormalMapArray()
{
String name("normalMapArray");
Var* normalMapArray = (Var*)LangElement::find(name);
if (!normalMapArray)
{
normalMapArray = new Var;
normalMapArray->setName(name);
normalMapArray->setType("Texture2DArray");
normalMapArray->uniform = true;
normalMapArray->texture = true;
normalMapArray->constNum = _getNormalMapSampler()->constNum;
}
return normalMapArray;
}
Var* TerrainFeatHLSL::_getOrmMapSampler()
{
String name("ormMapSampler");
Var* ormMapSampler = (Var*)LangElement::find(name);
if (!ormMapSampler)
{
ormMapSampler = new Var;
ormMapSampler->setName(name);
ormMapSampler->setType("SamplerState");
ormMapSampler->uniform = true;
ormMapSampler->sampler = true;
ormMapSampler->constNum = Var::getTexUnitNum();
}
return ormMapSampler;
}
Var* TerrainFeatHLSL::_getOrmMapArray()
{
String name("ormMapArray");
Var* ormMapArray = (Var*)LangElement::find(name);
if (!ormMapArray)
{
ormMapArray = new Var;
ormMapArray->setName(name);
ormMapArray->setType("Texture2DArray");
ormMapArray->uniform = true;
ormMapArray->texture = true;
ormMapArray->constNum = _getOrmMapSampler()->constNum;
}
return ormMapArray;
} }
Var* TerrainFeatHLSL::_getDetailIdStrengthParallax() Var* TerrainFeatHLSL::_getDetailIdStrengthParallax()
{ {
String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) ); String name( String::ToString( "detailIdStrengthParallax", getProcessIndex() ) );
Var *detailInfo = (Var*)LangElement::find( name ); Var *detailInfo = (Var*)LangElement::find( name );
if ( !detailInfo ) if ( !detailInfo )
{ {
detailInfo = new Var; detailInfo = new Var;
detailInfo->setType( "float3" ); detailInfo->setType( "float4" );
detailInfo->setName( name ); detailInfo->setName( name );
detailInfo->uniform = true; detailInfo->uniform = true;
detailInfo->constSortPos = cspPotentialPrimitive; detailInfo->constSortPos = cspPotentialPrimitive;
detailInfo->arraySize = getProcessIndex();
} }
detailInfo->arraySize = mMax(detailInfo->arraySize, getProcessIndex() + 1);
return detailInfo; return detailInfo;
} }
@ -383,11 +457,17 @@ void TerrainDetailMapFeatHLSL::processVert( Vector<ShaderComponent*> &component
outTex->setType( "float4" ); outTex->setType( "float4" );
// Get the detail scale and fade info. // Get the detail scale and fade info.
Var *detScaleAndFade = new Var; Var* detScaleAndFade = (Var*)LangElement::find("detailScaleAndFade");
detScaleAndFade->setType( "float4" ); if (detScaleAndFade == NULL)
detScaleAndFade->setName( String::ToString( "detailScaleAndFade%d", detailIndex ) ); {
detScaleAndFade = new Var;
detScaleAndFade->setType("float4");
detScaleAndFade->setName("detailScaleAndFade");
detScaleAndFade->uniform = true; detScaleAndFade->uniform = true;
detScaleAndFade->constSortPos = cspPotentialPrimitive; detScaleAndFade->constSortPos = cspPotentialPrimitive;
}
detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1);
// Setup the detail coord. // Setup the detail coord.
// //
@ -398,11 +478,11 @@ void TerrainDetailMapFeatHLSL::processVert( Vector<ShaderComponent*> &component
// //
// See TerrainBaseMapFeatHLSL::processVert(). // See TerrainBaseMapFeatHLSL::processVert().
// //
meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) ); meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex) ) );
// And sneak the detail fade thru the w detailCoord. // And sneak the detail fade thru the w detailCoord.
meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, detScaleAndFade, dist, detScaleAndFade ) ); outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)) );
output = meta; output = meta;
} }
@ -485,52 +565,25 @@ void TerrainDetailMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
// Calculate the blend for this detail texture. // Calculate the blend for this detail texture.
meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) ); new DecOp( detailBlend ), new IndexOp(detailInfo, detailIndex), inTex, layerSize, layerSample ) );
// Get a var and accumulate the blend amount.
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
if ( !blendTotal )
{
blendTotal = new Var;
blendTotal->setName( "blendTotal" );
blendTotal->setType( "float" );
meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
}
// Add to the blend total.
meta->addStatement(new GenOp(" @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend));
// If we had a parallax feature... then factor in the parallax // If we had a parallax feature... then factor in the parallax
// amount so that it fades out with the layer blending. // amount so that it fades out with the layer blending.
if (fd.features.hasFeature(MFT_TerrainParallaxMap, detailIndex)) if (fd.features.hasFeature(MFT_TerrainParallaxMap, detailIndex))
{ {
// Get the rest of our inputs. Var* normalMapArray = _getNormalMapArray();
Var *normalMap = _getNormalMapTex(); Var* normalMapSampler = _getNormalMapSampler();
String name(String::ToString("normalMapTex%d", getProcessIndex()));
Var *normalMapTex = (Var*)LangElement::find(name);
if (!normalMapTex)
{
normalMapTex = new Var;
normalMapTex->setName(String::ToString("normalMapTex%d", getProcessIndex()));
normalMapTex->setType("Texture2D");
normalMapTex->uniform = true;
normalMapTex->texture = true;
normalMapTex->constNum = normalMap->constNum;
}
// Call the library function to do the rest. // Call the library function to do the rest.
if (fd.features.hasFeature(MFT_IsBC3nm, detailIndex)) if (fd.features.hasFeature(MFT_IsBC3nm, detailIndex))
{ {
meta->addStatement(new GenOp(" @.xy += parallaxOffsetDxtnm( @, @, @.xy, @, @.z * @ );\r\n", meta->addStatement(new GenOp(" @.xy += parallaxOffsetDxtnmTexArray( @, @, float3(@.xy, @.x), @, @.z * @ );\r\n",
inDet, normalMapTex, normalMap, inDet, negViewTS, detailInfo, detailBlend)); inDet, normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, detailIndex), negViewTS, new IndexOp(detailInfo, detailIndex), detailBlend));
} }
else else
{ {
meta->addStatement(new GenOp(" @.xy += parallaxOffset( @, @, @.xy, @, @.z * @ );\r\n", meta->addStatement(new GenOp(" @.xy += parallaxOffsetTexArray( @, @, float3(@.xy, @.x), @, @.z * @ );\r\n",
inDet, normalMapTex, normalMap, inDet, negViewTS, detailInfo, detailBlend)); inDet, normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, detailIndex), negViewTS, new IndexOp(detailInfo, detailIndex), detailBlend));
} }
} }
@ -559,14 +612,6 @@ void TerrainDetailMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
} }
// Get the detail texture.
Var *detailMap = new Var;
detailMap->setType( "SamplerState" );
detailMap->setName( String::ToString( "detailMap%d", detailIndex ) );
detailMap->uniform = true;
detailMap->sampler = true;
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
// If we're using SM 3.0 then take advantage of // If we're using SM 3.0 then take advantage of
// dynamic branching to skip layers per-pixel. // dynamic branching to skip layers per-pixel.
@ -585,27 +630,23 @@ void TerrainDetailMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
// //
//Sampled detail texture that is not expanded //Sampled detail texture that is not expanded
Var* detailTex = new Var; Var* detailMapArray = _getDetailMapArray();
detailTex->setName(String::ToString("detailTex%d", detailIndex)); Var* detailMapSampler = _getDetailMapSampler();
detailTex->setType("Texture2D");
detailTex->uniform = true;
detailTex->texture = true;
detailTex->constNum = detailMap->constNum;
if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
{ {
meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, @.yz ), @.Sample( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n",
detailColor, detailTex, detailMap, inDet, detailTex, detailMap, inDet, inTex)); detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), inTex));
} }
else else
{ {
meta->addStatement(new GenOp(" @ = ( @.Sample( @, @.xy ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( @.Sample( @, float3(@.xy, @.x) ) * 2.0 ) - 1.0;\r\n",
detailColor, detailTex, detailMap, inDet)); detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex)));
} }
meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
detailColor, detailInfo, inDet ) ); detailColor, new IndexOp(detailInfo, detailIndex), inDet ) );
ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget;
@ -635,25 +676,24 @@ ShaderFeature::Resources TerrainDetailMapFeatHLSL::getResources( const MaterialF
// If this is the first detail pass then we // If this is the first detail pass then we
// samples from the layer tex. // samples from the layer tex.
res.numTex += 1; res.numTex += 1;
res.numTexReg += 1;
// If this material also does parallax then it // Add Detail TextureArray
// will generate the negative view vector and the res.numTex += 1;
// worldToTanget transform. res.numTexReg += 1;
if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) )
res.numTexReg += 4;
} }
// sample from the detail texture for diffuse coloring. // sample from the detail texture for diffuse coloring.
res.numTex += 1; // res.numTex += 1;
// If we have parallax for this layer then we'll also // If we have parallax for this layer then we'll also
// be sampling the normal map for the parallax heightmap. // be sampling the normal map for the parallax heightmap.
if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) ) //if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) )
res.numTex += 1; //res.numTex += 1;
// Finally we always send the detail texture // Finally we always send the detail texture
// coord to the pixel shader. // coord to the pixel shader.
res.numTexReg += 1; // res.numTexReg += 1;
return res; return res;
} }
@ -714,18 +754,24 @@ void TerrainMacroMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentL
outTex->setType( "float4" ); outTex->setType( "float4" );
// Get the detail scale and fade info. // Get the detail scale and fade info.
Var *detScaleAndFade = new Var; Var* macroScaleAndFade = (Var*)LangElement::find("macroScaleAndFade");
detScaleAndFade->setType( "float4" ); if (macroScaleAndFade == NULL)
detScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) ); {
detScaleAndFade->uniform = true; macroScaleAndFade = new Var;
detScaleAndFade->constSortPos = cspPotentialPrimitive; macroScaleAndFade->setType("float4");
macroScaleAndFade->setName("macroScaleAndFade");
macroScaleAndFade->uniform = true;
macroScaleAndFade->constSortPos = cspPotentialPrimitive;
}
macroScaleAndFade->arraySize = mMax(macroScaleAndFade->arraySize, detailIndex + 1);
// Setup the detail coord. // Setup the detail coord.
meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) ); meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(macroScaleAndFade, detailIndex)) );
// And sneak the detail fade thru the w detailCoord. // And sneak the detail fade thru the w detailCoord.
meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, detScaleAndFade, dist, detScaleAndFade ) ); outTex, new IndexOp(macroScaleAndFade, detailIndex), dist, new IndexOp(macroScaleAndFade, detailIndex)) );
output = meta; output = meta;
} }
@ -809,20 +855,7 @@ void TerrainMacroMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentL
// Calculate the blend for this detail texture. // Calculate the blend for this detail texture.
meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) ); new DecOp( detailBlend ), new IndexOp(detailInfo, detailIndex), inTex, layerSize, layerSample ) );
// Get a var and accumulate the blend amount.
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
if ( !blendTotal )
{
blendTotal = new Var;
blendTotal->setName( "blendTotal" );
blendTotal->setType( "float" );
meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
}
// Add to the blend total.
meta->addStatement(new GenOp(" @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend));
// Check to see if we have a gbuffer normal. // Check to see if we have a gbuffer normal.
Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
@ -849,22 +882,6 @@ void TerrainMacroMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentL
meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
} }
// Get the detail texture.
Var *detailMap = new Var;
detailMap->setType( "SamplerState" );
detailMap->setName( String::ToString( "macroMap%d", detailIndex ) );
detailMap->uniform = true;
detailMap->sampler = true;
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
//Create texture object for directx 11
Var *detailTex = new Var;
detailTex->setName(String::ToString("macroMapTex%d", detailIndex));
detailTex->setType("Texture2D");
detailTex->uniform = true;
detailTex->texture = true;
detailTex->constNum = detailMap->constNum;
// If we're using SM 3.0 then take advantage of // If we're using SM 3.0 then take advantage of
// dynamic branching to skip layers per-pixel. // dynamic branching to skip layers per-pixel.
if ( GFX->getPixelShaderVersion() >= 3.0f ) if ( GFX->getPixelShaderVersion() >= 3.0f )
@ -872,6 +889,9 @@ void TerrainMacroMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentL
meta->addStatement( new GenOp( " {\r\n" ) ); meta->addStatement( new GenOp( " {\r\n" ) );
Var* detailMapArray = _getDetailMapArray();
Var* detailMapSampler = _getDetailMapSampler();
// Note that we're doing the standard greyscale detail // Note that we're doing the standard greyscale detail
// map technique here which can darken and lighten the // map technique here which can darken and lighten the
// diffuse texture. // diffuse texture.
@ -881,17 +901,17 @@ void TerrainMacroMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentL
// //
if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
{ {
meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, @.yz ), @.Sample( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n",
detailColor, detailTex, detailMap, inDet, detailTex, detailMap, inDet, inTex)); detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), inTex));
} }
else else
{ {
meta->addStatement(new GenOp(" @ = ( @.Sample( @, @.xy ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( @.Sample( @, float3(@.xy, @.x) ) * 2.0 ) - 1.0;\r\n",
detailColor, detailTex, detailMap, inDet)); detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex)));
} }
meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
detailColor, detailInfo, inDet ) ); detailColor, new IndexOp(detailInfo, detailIndex), inDet ) );
ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget;
@ -987,38 +1007,28 @@ void TerrainNormalMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
meta->addStatement( new GenOp( " {\r\n" ) ); meta->addStatement( new GenOp( " {\r\n" ) );
// Get the normal map texture.
Var *normalMap = _getNormalMapTex();
/// Get the texture coord. /// Get the texture coord.
Var *inDet = _getInDetailCoord( componentList ); Var *inDet = _getInDetailCoord( componentList );
Var *inTex = getVertTexCoord( "texCoord" ); Var *inTex = getVertTexCoord( "texCoord" );
Var* detailInfo = _getDetailIdStrengthParallax();
// Sample the normal map. // Sample the normal map.
// //
// We take two normal samples and lerp between them for // We take two normal samples and lerp between them for
// side projection layers... else a single sample. // side projection layers... else a single sample.
LangElement *texOp; LangElement *texOp;
String name(String::ToString("normalMapTex%d", getProcessIndex())); Var* normalMapSampler = _getNormalMapSampler();
Var *normalMapTex = (Var*)LangElement::find(name); Var* normalMapArray = _getNormalMapArray();
if (!normalMapTex)
{
normalMapTex = new Var;
normalMapTex->setName(String::ToString("normalMapTex%d", getProcessIndex()));
normalMapTex->setType("Texture2D");
normalMapTex->uniform = true;
normalMapTex->texture = true;
normalMapTex->constNum = normalMap->constNum;
}
if (fd.features.hasFeature(MFT_TerrainSideProject, normalIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, normalIndex))
{ {
texOp = new GenOp("lerp( @.Sample( @, @.yz ), @.Sample( @, @.xz ), @.z )", texOp = new GenOp("lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z )",
normalMapTex, normalMap, inDet, normalMapTex, normalMap, inDet, inTex); normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex), normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex), inTex);
} }
else else
texOp = new GenOp("@.Sample(@, @.xy)", normalMapTex, normalMap, inDet); texOp = new GenOp("@.Sample(@, float3(@.xy, @.x))", normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex));
// create bump normal // create bump normal
Var *bumpNorm = new Var; Var *bumpNorm = new Var;
@ -1028,25 +1038,11 @@ void TerrainNormalMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
LangElement *bumpNormDecl = new DecOp( bumpNorm ); LangElement *bumpNormDecl = new DecOp( bumpNorm );
meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) ); meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
// If this is the last normal map then we
// can test to see the total blend value
// to see if we should clip the result.
Var* blendTotal = (Var*)LangElement::find("blendTotal");
if (blendTotal)
{
if (fd.features.getNextFeatureIndex(MFT_TerrainNormalMap, normalIndex) == -1)
meta->addStatement(new GenOp(" if ( @ > 0.0001f ){\r\n\r\n", blendTotal));
}
// Normalize is done later... // Normalize is done later...
// Note: The reverse mul order is intentional. Affine matrix. // Note: The reverse mul order is intentional. Affine matrix.
meta->addStatement( new GenOp( " @ = lerp( @, mul( @.xyz, @ ), min( @, @.w ) );\r\n", meta->addStatement( new GenOp( " @ = lerp( @, mul( @.xyz, @ ), min( @, @.w ) );\r\n",
gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) ); gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );
if (blendTotal)
{
if (fd.features.getNextFeatureIndex(MFT_TerrainNormalMap, normalIndex) == -1)
meta->addStatement(new GenOp(" }\r\n"));
}
// End the conditional block. // End the conditional block.
meta->addStatement( new GenOp( " }\r\n" ) ); meta->addStatement( new GenOp( " }\r\n" ) );
@ -1057,13 +1053,20 @@ ShaderFeature::Resources TerrainNormalMapFeatHLSL::getResources( const MaterialF
{ {
Resources res; Resources res;
if (getProcessIndex() == 0)
{
res.numTexReg += 1;
res.numTex += 1;
}
// If this is the first normal map and there // If this is the first normal map and there
// are no parallax features then we will // are no parallax features then we will
// generate the worldToTanget transform. // generate the worldToTanget transform.
if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) && //if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) ) // ( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) )
res.numTexReg = 3; // res.numTexReg = 3;
res.numTex = 1; //res.numTex = 1;
return res; return res;
} }
@ -1116,35 +1119,6 @@ ShaderFeature::Resources TerrainLightMapFeatHLSL::getResources( const MaterialFe
return res; return res;
} }
void TerrainAdditiveFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
Var *color = NULL;
Var* norm = NULL;
if (fd.features[MFT_isDeferred])
{
color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) );
norm = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget) );
}
else
color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget) );
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
if ( !color || !blendTotal )
return;
MultiLine *meta = new MultiLine;
meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) );
meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) );
if (fd.features[MFT_isDeferred])
{
meta->addStatement(new GenOp(" @.a = @;\r\n", norm, blendTotal));
}
output = meta;
}
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO), //standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
//.b = specular strength, a= spec power. //.b = specular strength, a= spec power.
@ -1211,15 +1185,18 @@ void TerrainORMMapFeatHLSL::processVert(Vector<ShaderComponent*> &componentList,
outTex->setType("float4"); outTex->setType("float4");
} }
// Get the detail scale and fade info. // Get the detail scale and fade info.
Var *detScaleAndFade = (Var*)LangElement::find(String::ToString("detailScaleAndFade%d", detailIndex)); Var *detScaleAndFade = (Var*)LangElement::find("detailScaleAndFade");
if (detScaleAndFade == NULL) if (detScaleAndFade == NULL)
{ {
detScaleAndFade = new Var;
detScaleAndFade->setType("float4"); detScaleAndFade->setType("float4");
detScaleAndFade->setName(String::ToString("detailScaleAndFade%d", detailIndex)); detScaleAndFade->setName("detailScaleAndFade");
detScaleAndFade->uniform = true; detScaleAndFade->uniform = true;
detScaleAndFade->constSortPos = cspPotentialPrimitive; detScaleAndFade->constSortPos = cspPotentialPrimitive;
} }
detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1);
// Setup the detail coord. // Setup the detail coord.
// //
// NOTE: You see here we scale the texture coord by 'xyx' // NOTE: You see here we scale the texture coord by 'xyx'
@ -1229,11 +1206,11 @@ void TerrainORMMapFeatHLSL::processVert(Vector<ShaderComponent*> &componentList,
// //
// See TerrainBaseMapFeatHLSL::processVert(). // See TerrainBaseMapFeatHLSL::processVert().
// //
meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade)); meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex)));
// And sneak the detail fade thru the w detailCoord. // And sneak the detail fade thru the w detailCoord.
meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, detScaleAndFade, dist, detScaleAndFade)); outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)));
output = meta; output = meta;
} }
@ -1249,32 +1226,24 @@ void TerrainORMMapFeatHLSL::processPix(Vector<ShaderComponent*> &componentList,
/// Get the texture coord. /// Get the texture coord.
Var *inDet = _getInDetailCoord(componentList); Var *inDet = _getInDetailCoord(componentList);
Var *inTex = getVertTexCoord("texCoord"); Var *inTex = getVertTexCoord("texCoord");
Var* detailInfo = _getDetailIdStrengthParallax();
const S32 compositeIndex = getProcessIndex(); const S32 compositeIndex = getProcessIndex();
Var *ormConfigMap = _getORMConfigMapTex();
// Sample the normal map. // Sample the normal map.
// //
// We take two normal samples and lerp between them for // We take two normal samples and lerp between them for
// side projection layers... else a single sample. // side projection layers... else a single sample.
LangElement *texOp; LangElement *texOp;
String name(String::ToString("ormConfigMapTex%d", getProcessIndex()));
Var *ormConfigMapTex = (Var*)LangElement::find(name); Var* ormMapArray = _getOrmMapArray();
if (!ormConfigMapTex) Var* ormMapSampler = _getOrmMapSampler();
{
ormConfigMapTex = new Var;
ormConfigMapTex->setName(String::ToString("ormConfigMapTex%d", getProcessIndex()));
ormConfigMapTex->setType("Texture2D");
ormConfigMapTex->uniform = true;
ormConfigMapTex->texture = true;
ormConfigMapTex->constNum = ormConfigMap->constNum;
}
if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex))
{ {
texOp = new GenOp("lerp( @.Sample( @, @.yz ), @.Sample( @, @.xz ), @.z )", texOp = new GenOp("lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z )",
ormConfigMapTex, ormConfigMap, inDet, ormConfigMapTex, ormConfigMap, inDet, inTex); ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex), ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex), inTex);
} }
else else
texOp = new GenOp("@.Sample(@, @.xy)", ormConfigMapTex, ormConfigMap, inDet); texOp = new GenOp("@.Sample(@, float3(@.xy, @.x))", ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex));
// search for material var // search for material var
Var * ormConfig; Var * ormConfig;

View file

@ -45,6 +45,12 @@ public:
Var* _getInMacroCoord(Vector<ShaderComponent*> &componentList ); Var* _getInMacroCoord(Vector<ShaderComponent*> &componentList );
Var* _getDetailMapSampler();
Var* _getDetailMapArray();
Var* _getNormalMapSampler();
Var* _getNormalMapArray();
Var* _getOrmMapSampler();
Var* _getOrmMapArray();
Var* _getNormalMapTex(); Var* _getNormalMapTex();
Var* _getORMConfigMapTex(); Var* _getORMConfigMapTex();
@ -151,17 +157,6 @@ public:
virtual String getName() { return "Terrain Lightmap Texture"; } virtual String getName() { return "Terrain Lightmap Texture"; }
}; };
class TerrainAdditiveFeatHLSL : public TerrainFeatHLSL
{
public:
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual String getName() { return "Terrain Additive"; }
};
class TerrainORMMapFeatHLSL : public TerrainFeatHLSL class TerrainORMMapFeatHLSL : public TerrainFeatHLSL
{ {
public: public:

View file

@ -23,6 +23,8 @@
#include "platform/platform.h" #include "platform/platform.h"
#include "terrain/terrCellMaterial.h" #include "terrain/terrCellMaterial.h"
#include "core/util/safeRelease.h"
#include "terrain/terrData.h" #include "terrain/terrData.h"
#include "terrain/terrCell.h" #include "terrain/terrCell.h"
#include "materials/materialFeatureTypes.h" #include "materials/materialFeatureTypes.h"
@ -37,7 +39,7 @@
#include "gfx/util/screenspace.h" #include "gfx/util/screenspace.h"
#include "lighting/advanced/advancedLightBinManager.h" #include "lighting/advanced/advancedLightBinManager.h"
S32 sgMaxTerrainMaterialsPerPass = 3; S32 sgMaxTerrainMaterialsPerPass = 32;
AFTER_MODULE_INIT( MaterialManager ) AFTER_MODULE_INIT( MaterialManager )
{ {
@ -55,12 +57,18 @@ Vector<String> _initSamplerNames()
//samplerNames.push_back("$macrolayerTex"); //samplerNames.push_back("$macrolayerTex");
samplerNames.push_back("$lightMapTex"); samplerNames.push_back("$lightMapTex");
samplerNames.push_back("$lightInfoBuffer"); samplerNames.push_back("$lightInfoBuffer");
samplerNames.push_back("$normalMapSampler");
samplerNames.push_back("$detailMapSampler");
samplerNames.push_back("$macroMapSampler");
samplerNames.push_back("$ormMapSampler");
// samplerNames.push_back("$ormConfigMapArray");
for(int i = 0; i < sgMaxTerrainMaterialsPerPass; ++i) for(int i = 0; i < sgMaxTerrainMaterialsPerPass; ++i)
{ {
samplerNames.push_back(avar("$normalMap%d",i)); //samplerNames.push_back(avar("$normalMap%d",i));
samplerNames.push_back(avar("$detailMap%d",i)); //samplerNames.push_back(avar("$detailMap%d",i));
//samplerNames.push_back(avar("$macroMap%d", i)); //samplerNames.push_back(avar("$macroMap%d", i));
samplerNames.push_back(avar("$ormConfigMap%d", i)); // samplerNames.push_back(avar("$ormConfigMap%d", i));
} }
return samplerNames; return samplerNames;
@ -71,10 +79,11 @@ const Vector<String> TerrainCellMaterial::mSamplerNames = _initSamplerNames();
TerrainCellMaterial::TerrainCellMaterial() TerrainCellMaterial::TerrainCellMaterial()
: mTerrain( NULL ), : mTerrain( NULL ),
mCurrPass( 0 ),
mDeferredMat( NULL ), mDeferredMat( NULL ),
mReflectMat( NULL ), mReflectMat( NULL ),
mMaterials(0) mShader( NULL ),
mCurrPass( 0 ),
mMaterials( 0 )
{ {
smAllMaterials.push_back( this ); smAllMaterials.push_back( this );
} }
@ -84,6 +93,9 @@ TerrainCellMaterial::~TerrainCellMaterial()
SAFE_DELETE( mDeferredMat ); SAFE_DELETE( mDeferredMat );
SAFE_DELETE( mReflectMat ); SAFE_DELETE( mReflectMat );
smAllMaterials.remove( this ); smAllMaterials.remove( this );
T3D::for_each(mMaterialInfos.begin(), mMaterialInfos.end(), T3D::delete_pointer());
mMaterialInfos.clear();
} }
void TerrainCellMaterial::_updateDefaultAnisotropy() void TerrainCellMaterial::_updateDefaultAnisotropy()
@ -101,59 +113,12 @@ void TerrainCellMaterial::_updateDefaultAnisotropy()
Vector<TerrainCellMaterial*>::iterator iter = smAllMaterials.begin(); Vector<TerrainCellMaterial*>::iterator iter = smAllMaterials.begin();
for ( ; iter != smAllMaterials.end(); iter++ ) for ( ; iter != smAllMaterials.end(); iter++ )
{ {
for ( U32 p=0; p < (*iter)->mPasses.size(); p++ )
{
Pass &pass = (*iter)->mPasses[p];
// Start from the existing state block. // Start from the existing state block.
GFXStateBlockDesc desc = pass.stateBlock->getDesc(); GFXStateBlockDesc desc = (*iter)->mStateBlock->getDesc();
for ( U32 m=0; m < pass.materials.size(); m++ ) if ((*iter)->mDetailTexArrayConst->isValid())
{ {
const MaterialInfo *matInfo = pass.materials[m]; const S32 sampler = (*iter)->mDetailTexArrayConst->getSamplerRegister();
if ( matInfo->detailTexConst->isValid() )
{
const S32 sampler = matInfo->detailTexConst->getSamplerRegister();
if ( maxAnisotropy > 1 )
{
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
}
else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
}
if ( matInfo->macroTexConst->isValid() )
{
const S32 sampler = matInfo->macroTexConst->getSamplerRegister();
if ( maxAnisotropy > 1 )
{
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
}
else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
}
if ( matInfo->normalTexConst->isValid() )
{
const S32 sampler = matInfo->normalTexConst->getSamplerRegister();
if ( maxAnisotropy > 1 )
{
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
}
else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
}
if (matInfo->ormTexConst->isValid())
{
const S32 sampler = matInfo->ormTexConst->getSamplerRegister();
if (maxAnisotropy > 1) if (maxAnisotropy > 1)
{ {
@ -164,23 +129,58 @@ void TerrainCellMaterial::_updateDefaultAnisotropy()
desc.samplers[sampler].minFilter = GFXTextureFilterLinear; desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
} }
} // for ( U32 m=0; m < pass.materials.size(); m++ ) if ((*iter)->mMacroTexArrayConst->isValid())
{
const S32 sampler = (*iter)->mMacroTexArrayConst->getSamplerRegister();
if (maxAnisotropy > 1)
{
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
}
else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
}
if ((*iter)->mNormalTexArrayConst->isValid())
{
const S32 sampler = (*iter)->mNormalTexArrayConst->getSamplerRegister();
if (maxAnisotropy > 1)
{
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
}
else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
}
if ((*iter)->mOrmTexArrayConst->isValid())
{
const S32 sampler = (*iter)->mOrmTexArrayConst->getSamplerRegister();
if (maxAnisotropy > 1)
{
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
}
else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
}
// Set the updated stateblock. // Set the updated stateblock.
desc.setCullMode( GFXCullCCW ); desc.setCullMode(GFXCullCCW);
pass.stateBlock = GFX->createStateBlock( desc ); (*iter)->mStateBlock = GFX->createStateBlock(desc);
//reflection //reflection
desc.setCullMode( GFXCullCW ); desc.setCullMode(GFXCullCW);
pass.reflectionStateBlock = GFX->createStateBlock(desc); (*iter)->mReflectionStateBlock = GFX->createStateBlock(desc);
// Create the wireframe state blocks. // Create the wireframe state blocks.
GFXStateBlockDesc wireframe( desc ); GFXStateBlockDesc wireframe(desc);
wireframe.fillMode = GFXFillWireframe; wireframe.fillMode = GFXFillWireframe;
wireframe.setCullMode( GFXCullCCW ); wireframe.setCullMode(GFXCullCCW);
pass.wireframeStateBlock = GFX->createStateBlock( wireframe ); (*iter)->mWireframeStateBlock = GFX->createStateBlock(wireframe);
} // for ( U32 p=0; i < (*iter)->mPasses.size(); p++ )
} }
} }
@ -207,31 +207,26 @@ void TerrainCellMaterial::setTransformAndEye( const MatrixF &modelXfm,
VectorF vEye = invViewXfm.getForwardVector(); VectorF vEye = invViewXfm.getForwardVector();
vEye.normalize( 1.0f / farPlane ); vEye.normalize( 1.0f / farPlane );
for ( U32 i=0; i < mPasses.size(); i++ ) mConsts->setSafe(mModelViewProjConst, modelViewProj);
{
Pass &pass = mPasses[i];
pass.consts->setSafe( pass.modelViewProjConst, modelViewProj ); if (mViewToObjConst->isValid() || mWorldViewOnlyConst->isValid())
if( pass.viewToObj->isValid() || pass.worldViewOnly->isValid() )
{ {
MatrixF worldViewOnly = viewXfm * modelXfm; MatrixF worldViewOnly = viewXfm * modelXfm;
pass.consts->setSafe( pass.worldViewOnly, worldViewOnly ); mConsts->setSafe(mWorldViewOnlyConst, worldViewOnly);
if( pass.viewToObj->isValid() ) if (mViewToObjConst->isValid())
{ {
worldViewOnly.affineInverse(); worldViewOnly.affineInverse();
pass.consts->set( pass.viewToObj, worldViewOnly); mConsts->set(mViewToObjConst, worldViewOnly);
} }
} }
pass.consts->setSafe( pass.eyePosWorldConst, eyePos ); mConsts->setSafe(mEyePosWorldConst, eyePos);
pass.consts->setSafe( pass.eyePosConst, objEyePos ); mConsts->setSafe(mEyePosConst, objEyePos);
pass.consts->setSafe( pass.objTransConst, modelXfm ); mConsts->setSafe(mObjTransConst, modelXfm);
pass.consts->setSafe( pass.worldToObjConst, invModelXfm ); mConsts->setSafe(mWorldToObjConst, invModelXfm);
pass.consts->setSafe( pass.vEyeConst, vEye ); mConsts->setSafe(mVEyeConst, vEye);
}
} }
TerrainCellMaterial* TerrainCellMaterial::getDeferredMat() TerrainCellMaterial* TerrainCellMaterial::getDeferredMat()
@ -268,8 +263,7 @@ void TerrainCellMaterial::init( TerrainBlock *block,
mTerrain = block; mTerrain = block;
mMaterials = activeMaterials; mMaterials = activeMaterials;
Vector<MaterialInfo*> materials; mMaterialInfos.clear();
for ( U32 i = 0; i < 64; i++ ) for ( U32 i = 0; i < 64; i++ )
{ {
if ( !( mMaterials & ((U64)1 << i ) ) ) if ( !( mMaterials & ((U64)1 << i ) ) )
@ -280,41 +274,20 @@ void TerrainCellMaterial::init( TerrainBlock *block,
MaterialInfo *info = new MaterialInfo(); MaterialInfo *info = new MaterialInfo();
info->layerId = i; info->layerId = i;
info->mat = mat; info->mat = mat;
materials.push_back( info ); mMaterialInfos.push_back(info);
} }
mCurrPass = 0; if (!_initShader(deferredMat,
mPasses.clear();
// Ok... loop till we successfully generate all
// the shader passes for the materials.
while ( materials.size() > 0 || baseOnly )
{
mPasses.increment();
if ( !_createPass( &materials,
&mPasses.last(),
mPasses.size() == 1,
deferredMat,
reflectMat, reflectMat,
baseOnly ) ) baseOnly))
{ {
Con::errorf( "TerrainCellMaterial::init - Failed to create pass!" ); Con::errorf("TerrainCellMaterial::init - Failed to init shader!");
// The pass failed to be generated... give up. T3D::for_each(mMaterialInfos.begin(), mMaterialInfos.end(), T3D::delete_pointer());
mPasses.last().materials.clear(); mMaterialInfos.clear();
mPasses.clear();
T3D::for_each( materials.begin(), materials.end(), T3D::delete_pointer() );
return; return;
} }
if ( baseOnly )
break;
}
// Cleanup any remaining matinfo.
T3D::for_each( materials.begin(), materials.end(), T3D::delete_pointer() );
// If we have attached mats then update them too. // If we have attached mats then update them too.
if ( mDeferredMat ) if ( mDeferredMat )
mDeferredMat->init( mTerrain, mMaterials, true, false, baseOnly ); mDeferredMat->init( mTerrain, mMaterials, true, false, baseOnly );
@ -322,14 +295,11 @@ void TerrainCellMaterial::init( TerrainBlock *block,
mReflectMat->init( mTerrain, mMaterials, false, true, baseOnly ); mReflectMat->init( mTerrain, mMaterials, false, true, baseOnly );
} }
bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials, bool TerrainCellMaterial::_initShader(bool deferredMat,
Pass *pass,
bool firstPass,
bool deferredMat,
bool reflectMat, bool reflectMat,
bool baseOnly ) bool baseOnly)
{ {
if ( GFX->getPixelShaderVersion() < 3.0f ) if (GFX->getPixelShaderVersion() < 3.0f)
baseOnly = true; baseOnly = true;
// NOTE: At maximum we only try to combine sgMaxTerrainMaterialsPerPass materials // NOTE: At maximum we only try to combine sgMaxTerrainMaterialsPerPass materials
@ -337,7 +307,7 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
// cases, but the most common case results in much fewer // cases, but the most common case results in much fewer
// shader generation failures and permutations leading to // shader generation failures and permutations leading to
// faster load time and less hiccups during gameplay. // faster load time and less hiccups during gameplay.
U32 matCount = getMin( sgMaxTerrainMaterialsPerPass, materials->size() ); U32 matCount = getMin(sgMaxTerrainMaterialsPerPass, mMaterialInfos.size());
Vector<GFXTexHandle> normalMaps; Vector<GFXTexHandle> normalMaps;
@ -347,96 +317,89 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
// TODO: This seems ugly... we should trigger // TODO: This seems ugly... we should trigger
// features like this differently in the future. // features like this differently in the future.
// //
bool useBLM = String::compare( LIGHTMGR->getId(), "BLM" ) == 0; bool useBLM = String::compare(LIGHTMGR->getId(), "BLM") == 0;
// Do we need to disable normal mapping? // Do we need to disable normal mapping?
const bool disableNormalMaps = MATMGR->getExclusionFeatures().hasFeature( MFT_NormalMap ) || useBLM; const bool disableNormalMaps = MATMGR->getExclusionFeatures().hasFeature(MFT_NormalMap) || useBLM;
// How about parallax? // How about parallax?
const bool disableParallaxMaps = GFX->getPixelShaderVersion() < 3.0f || const bool disableParallaxMaps = GFX->getPixelShaderVersion() < 3.0f ||
MATMGR->getExclusionFeatures().hasFeature( MFT_Parallax ); MATMGR->getExclusionFeatures().hasFeature(MFT_Parallax);
// Has advanced lightmap support been enabled for deferred. // Has advanced lightmap support been enabled for deferred.
bool advancedLightmapSupport = false; bool advancedLightmapSupport = false;
if ( deferredMat ) if (deferredMat)
{ {
// This sucks... but it works. // This sucks... but it works.
AdvancedLightBinManager *lightBin; AdvancedLightBinManager* lightBin;
if ( Sim::findObject( "AL_LightBinMgr", lightBin ) ) if (Sim::findObject("AL_LightBinMgr", lightBin))
advancedLightmapSupport = lightBin->MRTLightmapsDuringDeferred(); advancedLightmapSupport = lightBin->MRTLightmapsDuringDeferred();
} }
// Loop till we create a valid shader! // Loop till we create a valid shader!
while( true ) while (true)
{ {
FeatureSet features; FeatureSet features;
features.addFeature( MFT_VertTransform ); features.addFeature(MFT_VertTransform);
features.addFeature( MFT_TerrainBaseMap ); features.addFeature(MFT_TerrainBaseMap);
if ( deferredMat ) if (deferredMat)
{ {
features.addFeature( MFT_EyeSpaceDepthOut ); features.addFeature(MFT_EyeSpaceDepthOut);
features.addFeature( MFT_DeferredConditioner ); features.addFeature(MFT_DeferredConditioner);
features.addFeature(MFT_isDeferred); features.addFeature(MFT_isDeferred);
if ( advancedLightmapSupport ) if (advancedLightmapSupport)
features.addFeature( MFT_RenderTarget3_Zero ); features.addFeature(MFT_RenderTarget3_Zero);
} }
else else
{ {
features.addFeature( MFT_RTLighting ); features.addFeature(MFT_RTLighting);
// The HDR feature is always added... it will compile out // The HDR feature is always added... it will compile out
// if HDR is not enabled in the engine. // if HDR is not enabled in the engine.
features.addFeature( MFT_HDROut ); features.addFeature(MFT_HDROut);
} }
// Enable lightmaps and fogging if we're in BL. // Enable lightmaps and fogging if we're in BL.
if ( reflectMat || useBLM ) if (reflectMat || useBLM)
{ {
features.addFeature( MFT_Fog ); features.addFeature(MFT_Fog);
features.addFeature( MFT_ForwardShading ); features.addFeature(MFT_ForwardShading);
} }
if ( useBLM ) if (useBLM)
features.addFeature( MFT_TerrainLightMap ); features.addFeature(MFT_TerrainLightMap);
// The additional passes need to be lerp blended into the
// target to maintain the results of the previous passes.
if (!firstPass && deferredMat)
features.addFeature( MFT_TerrainAdditive );
normalMaps.clear(); normalMaps.clear();
pass->materials.clear();
S32 featureIndex = 0;
// Now add all the material layer features. // Now add all the material layer features.
for (U32 i = 0; i < matCount && !baseOnly; i++)
for ( U32 i=0; i < matCount && !baseOnly; i++ )
{ {
TerrainMaterial *mat = (*materials)[i]->mat; TerrainMaterial* mat = mMaterialInfos[i]->mat;
if ( mat == NULL ) if (mat == NULL)
continue; continue;
// We only include materials that // We only include materials that
// have more than a base texture. // have more than a base texture.
if ( mat->getDetailSize() <= 0 || if (mat->getDetailSize() <= 0 ||
mat->getDetailDistance() <= 0 || mat->getDetailDistance() <= 0 ||
mat->getDetailMap().isEmpty() ) mat->getDetailMap().isEmpty())
continue; continue;
S32 featureIndex = pass->materials.size();
// check for macro detail texture // check for macro detail texture
if ( !(mat->getMacroSize() <= 0 || mat->getMacroDistance() <= 0 || mat->getMacroMap().isEmpty() ) ) if (!(mat->getMacroSize() <= 0 || mat->getMacroDistance() <= 0 || mat->getMacroMap().isEmpty()))
{ {
if(deferredMat) if (deferredMat)
features.addFeature(MFT_isDeferred, featureIndex); features.addFeature(MFT_isDeferred, featureIndex);
features.addFeature( MFT_TerrainMacroMap, featureIndex ); features.addFeature(MFT_TerrainMacroMap, featureIndex);
} }
if(deferredMat) if (deferredMat)
features.addFeature(MFT_isDeferred, featureIndex); features.addFeature(MFT_isDeferred, featureIndex);
features.addFeature( MFT_TerrainDetailMap, featureIndex ); features.addFeature(MFT_TerrainDetailMap, featureIndex);
if (!(mat->getORMConfigMap().isEmpty())) if (!(mat->getORMConfigMap().isEmpty()))
{ {
@ -451,33 +414,34 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
if (mat->getInvertRoughness()) if (mat->getInvertRoughness())
features.addFeature(MFT_InvertRoughness, featureIndex); features.addFeature(MFT_InvertRoughness, featureIndex);
pass->materials.push_back( (*materials)[i] );
normalMaps.increment(); normalMaps.increment();
// Skip normal maps if we need to. // Skip normal maps if we need to.
if ( !disableNormalMaps && mat->getNormalMap().isNotEmpty() ) if (!disableNormalMaps && mat->getNormalMap().isNotEmpty())
{ {
features.addFeature( MFT_TerrainNormalMap, featureIndex ); features.addFeature(MFT_TerrainNormalMap, featureIndex);
normalMaps.last().set( mat->getNormalMap(), normalMaps.last().set(mat->getNormalMap(),
&GFXNormalMapProfile, "TerrainCellMaterial::_createPass() - NormalMap" ); &GFXNormalMapProfile, "TerrainCellMaterial::_initShader() - NormalMap");
GFXFormat normalFmt = normalMaps.last().getFormat(); GFXFormat normalFmt = normalMaps.last().getFormat();
if ( normalFmt == GFXFormatBC3 ) if (normalFmt == GFXFormatBC3)
features.addFeature( MFT_IsBC3nm, featureIndex ); features.addFeature(MFT_IsBC3nm, featureIndex);
else if ( normalFmt == GFXFormatBC5) else if (normalFmt == GFXFormatBC5)
features.addFeature( MFT_IsBC5nm, featureIndex); features.addFeature(MFT_IsBC5nm, featureIndex);
// Do we need and can we do parallax mapping? // Do we need and can we do parallax mapping?
if ( !disableParallaxMaps && if (!disableParallaxMaps &&
mat->getParallaxScale() > 0.0f && mat->getParallaxScale() > 0.0f &&
!mat->useSideProjection() ) !mat->useSideProjection())
features.addFeature( MFT_TerrainParallaxMap, featureIndex ); features.addFeature(MFT_TerrainParallaxMap, featureIndex);
} }
// Is this layer got side projection? // Is this layer got side projection?
if ( mat->useSideProjection() ) if (mat->useSideProjection())
features.addFeature( MFT_TerrainSideProject, featureIndex ); features.addFeature(MFT_TerrainSideProject, featureIndex);
featureIndex++;
} }
MaterialFeatureData featureData; MaterialFeatureData featureData;
@ -488,16 +452,16 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
// registers we're gonna need. // registers we're gonna need.
U32 numTex = 0; U32 numTex = 0;
U32 numTexReg = 0; U32 numTexReg = 0;
for ( U32 i=0; i < features.getCount(); i++ ) for (U32 i = 0; i < features.getCount(); i++)
{ {
S32 index; S32 index;
const FeatureType &type = features.getAt( i, &index ); const FeatureType& type = features.getAt(i, &index);
ShaderFeature* sf = FEATUREMGR->getByType( type ); ShaderFeature* sf = FEATUREMGR->getByType(type);
if ( !sf ) if (!sf)
continue; continue;
sf->setProcessIndex( index ); sf->setProcessIndex(index);
ShaderFeature::Resources res = sf->getResources( featureData ); ShaderFeature::Resources res = sf->getResources(featureData);
numTex += res.numTex; numTex += res.numTex;
numTexReg += res.numTexReg; numTexReg += res.numTexReg;
@ -509,8 +473,8 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
// limit. Its really supposed to be 11, but that // limit. Its really supposed to be 11, but that
// always fails to compile so far. // always fails to compile so far.
// //
if ( numTex < GFX->getNumSamplers() && if (numTex < GFX->getNumSamplers() &&
numTexReg <= 10 ) numTexReg <= 10)
{ {
// NOTE: We really shouldn't be getting errors building the shaders, // NOTE: We really shouldn't be getting errors building the shaders,
// but we can generate more instructions than the ps_2_x will allow. // but we can generate more instructions than the ps_2_x will allow.
@ -524,18 +488,18 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
// we get down to a single material. If a single material case // we get down to a single material. If a single material case
// fails it means it cannot generate any passes at all! // fails it means it cannot generate any passes at all!
const bool logErrors = true;// matCount == 1; const bool logErrors = true;// matCount == 1;
GFXShader::setLogging( logErrors, true ); GFXShader::setLogging(logErrors, true);
pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames ); mShader = SHADERGEN->getShader(featureData, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames);
} }
// If we got a shader then we can continue. // If we got a shader then we can continue.
if ( pass->shader ) if (mShader)
break; break;
// If the material count is already 1 then this // If the material count is already 1 then this
// is a real shader error... give up! // is a real shader error... give up!
if ( matCount <= 1 ) if (matCount <= 1)
return false; return false;
// If we failed we next try half the input materials // If we failed we next try half the input materials
@ -544,112 +508,62 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
} }
// Setup the constant buffer. // Setup the constant buffer.
pass->consts = pass->shader->allocConstBuffer(); mConsts = mShader->allocConstBuffer();
// Prepare the basic constants. // Prepare the basic constants.
pass->modelViewProjConst = pass->shader->getShaderConstHandle( "$modelview" ); mModelViewProjConst = mShader->getShaderConstHandle("$modelview");
pass->worldViewOnly = pass->shader->getShaderConstHandle( "$worldViewOnly" ); mWorldViewOnlyConst = mShader->getShaderConstHandle("$worldViewOnly");
pass->viewToObj = pass->shader->getShaderConstHandle( "$viewToObj" ); mViewToObjConst = mShader->getShaderConstHandle("$viewToObj");
pass->eyePosWorldConst = pass->shader->getShaderConstHandle( "$eyePosWorld" ); mEyePosWorldConst = mShader->getShaderConstHandle("$eyePosWorld");
pass->eyePosConst = pass->shader->getShaderConstHandle( "$eyePos" ); mEyePosConst = mShader->getShaderConstHandle("$eyePos");
pass->vEyeConst = pass->shader->getShaderConstHandle( "$vEye" ); mVEyeConst = mShader->getShaderConstHandle("$vEye");
pass->layerSizeConst = pass->shader->getShaderConstHandle( "$layerSize" ); mLayerSizeConst = mShader->getShaderConstHandle("$layerSize");
pass->objTransConst = pass->shader->getShaderConstHandle( "$objTrans" ); mObjTransConst = mShader->getShaderConstHandle("$objTrans");
pass->worldToObjConst = pass->shader->getShaderConstHandle( "$worldToObj" ); mWorldToObjConst = mShader->getShaderConstHandle("$worldToObj");
pass->lightInfoBufferConst = pass->shader->getShaderConstHandle( "$lightInfoBuffer" ); mLightInfoBufferConst = mShader->getShaderConstHandle("$lightInfoBuffer");
pass->baseTexMapConst = pass->shader->getShaderConstHandle( "$baseTexMap" ); mBaseTexMapConst = mShader->getShaderConstHandle("$baseTexMap");
pass->layerTexConst = pass->shader->getShaderConstHandle( "$layerTex" ); mLayerTexConst = mShader->getShaderConstHandle("$layerTex");
pass->fogDataConst = pass->shader->getShaderConstHandle( "$fogData" ); mFogDataConst = mShader->getShaderConstHandle("$fogData");
pass->fogColorConst = pass->shader->getShaderConstHandle( "$fogColor" ); mFogColorConst = mShader->getShaderConstHandle("$fogColor");
pass->lightMapTexConst = pass->shader->getShaderConstHandle( "$lightMapTex" ); mLightMapTexConst = mShader->getShaderConstHandle("$lightMapTex");
pass->oneOverTerrainSize = pass->shader->getShaderConstHandle( "$oneOverTerrainSize" ); mOneOverTerrainSizeConst = mShader->getShaderConstHandle("$oneOverTerrainSize");
pass->squareSize = pass->shader->getShaderConstHandle( "$squareSize" ); mSquareSizeConst = mShader->getShaderConstHandle("$squareSize");
pass->lightParamsConst = pass->shader->getShaderConstHandle( "$rtParamslightInfoBuffer" ); mLightParamsConst = mShader->getShaderConstHandle("$rtParamslightInfoBuffer");
// Now prepare the basic stateblock. // Now prepare the basic stateblock.
GFXStateBlockDesc desc; GFXStateBlockDesc desc;
if ( !firstPass )
{
desc.setBlend( true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha );
// If this is the deferred then we don't want to
// write to the last two color channels (where
// depth is usually encoded).
//
// This trick works in combination with the
// MFT_TerrainAdditive feature to lerp the
// output normal with the previous pass.
//
if ( deferredMat )
desc.setColorWrites( true, true, true, false );
}
// We write to the zbuffer if this is a deferred // We write to the zbuffer if this is a deferred
// material or if the deferred is disabled. // material or if the deferred is disabled.
desc.setZReadWrite( true, !MATMGR->getDeferredEnabled() || desc.setZReadWrite(true, !MATMGR->getDeferredEnabled() ||
deferredMat || deferredMat ||
reflectMat ); reflectMat);
desc.samplersDefined = true; desc.samplersDefined = true;
if ( pass->baseTexMapConst->isValid() ) if (mBaseTexMapConst->isValid())
desc.samplers[pass->baseTexMapConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear(); desc.samplers[mBaseTexMapConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear();
if ( pass->layerTexConst->isValid() ) if (mLayerTexConst->isValid())
desc.samplers[pass->layerTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint(); desc.samplers[mLayerTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint();
if ( pass->lightInfoBufferConst->isValid() ) if (mLightInfoBufferConst->isValid())
desc.samplers[pass->lightInfoBufferConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint(); desc.samplers[mLightInfoBufferConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint();
if ( pass->lightMapTexConst->isValid() ) if (mLightMapTexConst->isValid())
desc.samplers[pass->lightMapTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear(); desc.samplers[mLightMapTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear();
const U32 maxAnisotropy = MATMGR->getDefaultAnisotropy(); const U32 maxAnisotropy = MATMGR->getDefaultAnisotropy();
// Finally setup the material specific shader mDetailInfoVArrayConst = mShader->getShaderConstHandle("$detailScaleAndFade");
// constants and stateblock state. mDetailInfoPArrayConst = mShader->getShaderConstHandle("$detailIdStrengthParallax");
// mMacroInfoVArrayConst = mShader->getShaderConstHandle("$macroIdStrengthParallax");
// NOTE: If this changes be sure to check TerrainCellMaterial::_updateDefaultAnisotropy mMacroInfoPArrayConst = mShader->getShaderConstHandle("$macroIdStrengthParallax");
// to see if it needs the same changes.
// mDetailTexArrayConst = mShader->getShaderConstHandle("$detailMapSampler");
for ( U32 i=0; i < pass->materials.size(); i++ ) if (mDetailTexArrayConst->isValid())
{ {
MaterialInfo *matInfo = pass->materials[i]; const S32 sampler = mDetailTexArrayConst->getSamplerRegister();
matInfo->detailInfoVConst = pass->shader->getShaderConstHandle( avar( "$detailScaleAndFade%d", i ) );
matInfo->detailInfoPConst = pass->shader->getShaderConstHandle( avar( "$detailIdStrengthParallax%d", i ) );
matInfo->detailTexConst = pass->shader->getShaderConstHandle( avar( "$detailMap%d", i ) );
if ( matInfo->detailTexConst->isValid() )
{
const S32 sampler = matInfo->detailTexConst->getSamplerRegister();
desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
if ( maxAnisotropy > 1 )
{
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
}
else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
matInfo->detailTex.set( matInfo->mat->getDetailMap(),
&GFXStaticTextureProfile, "TerrainCellMaterial::_createPass() - DetailMap" );
}
matInfo->ormTexConst = pass->shader->getShaderConstHandle(avar("$ormConfigMap%d", i));
if (matInfo->ormTexConst->isValid())
{
GFXTextureProfile* profile = &GFXStaticTextureProfile;
if (matInfo->mat->getIsSRGB())
profile = &GFXStaticTextureSRGBProfile;
matInfo->ormTex.set(matInfo->mat->getORMConfigMap(),
profile, "TerrainCellMaterial::_createPass() - CompositeMap");
const S32 sampler = matInfo->ormTexConst->getSamplerRegister();
desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear(); desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
desc.samplers[sampler].magFilter = GFXTextureFilterLinear; desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
@ -664,60 +578,60 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
desc.samplers[sampler].minFilter = GFXTextureFilterLinear; desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
} }
matInfo->macroInfoVConst = pass->shader->getShaderConstHandle( avar( "$macroScaleAndFade%d", i ) ); mMacroTexArrayConst = mShader->getShaderConstHandle("$macroMapSampler");
matInfo->macroInfoPConst = pass->shader->getShaderConstHandle( avar( "$macroIdStrengthParallax%d", i ) ); if (mMacroTexArrayConst->isValid())
matInfo->macroTexConst = pass->shader->getShaderConstHandle( avar( "$macroMap%d", i ) );
if ( matInfo->macroTexConst->isValid() )
{ {
const S32 sampler = matInfo->macroTexConst->getSamplerRegister(); const S32 sampler = mMacroTexArrayConst->getSamplerRegister();
desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear(); desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
desc.samplers[sampler].magFilter = GFXTextureFilterLinear; desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
desc.samplers[sampler].mipFilter = GFXTextureFilterLinear; desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
if ( maxAnisotropy > 1 ) if (maxAnisotropy > 1)
{ {
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic; desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy; desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
} }
else else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear; desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
matInfo->macroTex.set( matInfo->mat->getMacroMap(),
&GFXStaticTextureProfile, "TerrainCellMaterial::_createPass() - MacroMap" );
} }
//end macro texture
matInfo->normalTexConst = pass->shader->getShaderConstHandle( avar( "$normalMap%d", i ) ); mNormalTexArrayConst = mShader->getShaderConstHandle("$normalMapSampler");
if ( matInfo->normalTexConst->isValid() ) if (mNormalTexArrayConst->isValid())
{ {
const S32 sampler = matInfo->normalTexConst->getSamplerRegister(); const S32 sampler = mNormalTexArrayConst->getSamplerRegister();
desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear(); desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
desc.samplers[sampler].magFilter = GFXTextureFilterLinear; desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
desc.samplers[sampler].mipFilter = GFXTextureFilterLinear; desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
if ( maxAnisotropy > 1 ) if (maxAnisotropy > 1)
{ {
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic; desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy; desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
} }
else else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear; desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
matInfo->normalTex = normalMaps[i];
}
} }
// Remove the materials we processed and leave the mOrmTexArrayConst = mShader->getShaderConstHandle("$ormMapSampler");
// ones that remain for the next pass. if (mOrmTexArrayConst->isValid())
for ( U32 i=0; i < matCount; i++ )
{ {
MaterialInfo *matInfo = materials->first(); GFXTextureProfile* profile = &GFXStaticTextureProfile;
if ( baseOnly || pass->materials.find_next( matInfo ) == -1 )
delete matInfo; const S32 sampler = mOrmTexArrayConst->getSamplerRegister();
materials->pop_front();
desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
if (maxAnisotropy > 1)
{
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
}
else
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
} }
// If we're doing deferred it requires some // If we're doing deferred it requires some
@ -726,28 +640,34 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
desc.addDesc( RenderDeferredMgr::getOpaqueStenciWriteDesc( false ) ); desc.addDesc( RenderDeferredMgr::getOpaqueStenciWriteDesc( false ) );
desc.setCullMode( GFXCullCCW ); desc.setCullMode( GFXCullCCW );
pass->stateBlock = GFX->createStateBlock(desc); mStateBlock = GFX->createStateBlock(desc);
//reflection stateblock //reflection stateblock
desc.setCullMode( GFXCullCW ); desc.setCullMode( GFXCullCW );
pass->reflectionStateBlock = GFX->createStateBlock(desc); mReflectionStateBlock = GFX->createStateBlock(desc);
// Create the wireframe state blocks. // Create the wireframe state blocks.
GFXStateBlockDesc wireframe( desc ); GFXStateBlockDesc wireframe( desc );
wireframe.fillMode = GFXFillWireframe; wireframe.fillMode = GFXFillWireframe;
wireframe.setCullMode( GFXCullCCW ); wireframe.setCullMode( GFXCullCCW );
pass->wireframeStateBlock = GFX->createStateBlock( wireframe ); mWireframeStateBlock = GFX->createStateBlock( wireframe );
return true; return true;
} }
void TerrainCellMaterial::_updateMaterialConsts( Pass *pass ) void TerrainCellMaterial::_updateMaterialConsts( )
{ {
PROFILE_SCOPE( TerrainCellMaterial_UpdateMaterialConsts ); PROFILE_SCOPE( TerrainCellMaterial_UpdateMaterialConsts );
if (mMaterialInfos.empty())
for ( U32 j=0; j < pass->materials.size(); j++ )
{ {
MaterialInfo *matInfo = pass->materials[j]; return;
}
AlignedArray<Point4F> detailInfoArray(mMaterialInfos.size(), sizeof(Point4F));
AlignedArray<Point4F> detailScaleAndFadeArray(mMaterialInfos.size(), sizeof(Point4F));
for ( U32 j=0; j < mMaterialInfos.size(); j++ )
{
MaterialInfo *matInfo = mMaterialInfos[j];
F32 detailSize = matInfo->mat->getDetailSize(); F32 detailSize = matInfo->mat->getDetailSize();
F32 detailScale = 1.0f; F32 detailScale = 1.0f;
@ -775,38 +695,16 @@ void TerrainCellMaterial::_updateMaterialConsts( Pass *pass )
if ( !mIsZero( distance ) ) if ( !mIsZero( distance ) )
detailScaleAndFade.w = 1.0f / distance; detailScaleAndFade.w = 1.0f / distance;
Point3F detailIdStrengthParallax( matInfo->layerId, Point4F detailIdStrengthParallax( matInfo->layerId,
matInfo->mat->getDetailStrength(), matInfo->mat->getDetailStrength(),
matInfo->mat->getParallaxScale() ); matInfo->mat->getParallaxScale(), 0 );
pass->consts->setSafe( matInfo->detailInfoVConst, detailScaleAndFade ); detailScaleAndFadeArray[j] = detailScaleAndFade;
pass->consts->setSafe( matInfo->detailInfoPConst, detailIdStrengthParallax ); detailInfoArray[j] = detailIdStrengthParallax;
// macro texture info
F32 macroSize = matInfo->mat->getMacroSize();
F32 macroScale = 1.0f;
if ( !mIsZero( macroSize ) )
macroScale = mTerrain->getWorldBlockSize() / macroSize;
// Scale the distance by the global scalar.
const F32 macroDistance = mTerrain->smDetailScale * matInfo->mat->getMacroDistance();
Point4F macroScaleAndFade( macroScale,
-macroScale,
macroDistance,
0 );
if ( !mIsZero( macroDistance ) )
macroScaleAndFade.w = 1.0f / macroDistance;
Point3F macroIdStrengthParallax( matInfo->layerId,
matInfo->mat->getMacroStrength(),
0 );
pass->consts->setSafe( matInfo->macroInfoVConst, macroScaleAndFade );
pass->consts->setSafe( matInfo->macroInfoPConst, macroIdStrengthParallax );
} }
mConsts->setSafe(mDetailInfoVArrayConst, detailScaleAndFadeArray);
mConsts->setSafe(mDetailInfoPArrayConst, detailInfoArray);
} }
bool TerrainCellMaterial::setupPass( const SceneRenderState *state, bool TerrainCellMaterial::setupPass( const SceneRenderState *state,
@ -814,80 +712,80 @@ bool TerrainCellMaterial::setupPass( const SceneRenderState *state,
{ {
PROFILE_SCOPE( TerrainCellMaterial_SetupPass ); PROFILE_SCOPE( TerrainCellMaterial_SetupPass );
if ( mCurrPass >= mPasses.size() ) if (mCurrPass > 0)
{ {
mCurrPass = 0; mCurrPass = 0;
return false; return false;
} }
Pass &pass = mPasses[mCurrPass]; if (mMaterialInfos.size() > 4)
{
int a = 2 + 2;
}
_updateMaterialConsts( &pass ); mCurrPass++;
if ( pass.baseTexMapConst->isValid() ) _updateMaterialConsts();
GFX->setTexture( pass.baseTexMapConst->getSamplerRegister(), mTerrain->mBaseTex.getPointer() );
if ( pass.layerTexConst->isValid() ) if ( mBaseTexMapConst->isValid() )
GFX->setTexture( pass.layerTexConst->getSamplerRegister(), mTerrain->mLayerTex.getPointer() ); GFX->setTexture( mBaseTexMapConst->getSamplerRegister(), mTerrain->mBaseTex.getPointer() );
if ( pass.lightMapTexConst->isValid() ) if ( mLayerTexConst->isValid() )
GFX->setTexture( pass.lightMapTexConst->getSamplerRegister(), mTerrain->getLightMapTex() ); GFX->setTexture( mLayerTexConst->getSamplerRegister(), mTerrain->mLayerTex.getPointer() );
if ( mLightMapTexConst->isValid() )
GFX->setTexture( mLightMapTexConst->getSamplerRegister(), mTerrain->getLightMapTex() );
if ( sceneData.wireframe ) if ( sceneData.wireframe )
GFX->setStateBlock( pass.wireframeStateBlock ); GFX->setStateBlock( mWireframeStateBlock );
else if ( state->isReflectPass( )) else if ( state->isReflectPass( ))
GFX->setStateBlock( pass.reflectionStateBlock ); GFX->setStateBlock( mReflectionStateBlock );
else else
GFX->setStateBlock( pass.stateBlock ); GFX->setStateBlock( mStateBlock );
GFX->setShader( pass.shader ); GFX->setShader( mShader );
GFX->setShaderConstBuffer( pass.consts ); GFX->setShaderConstBuffer( mConsts );
// Let the light manager prepare any light stuff it needs. // Let the light manager prepare any light stuff it needs.
LIGHTMGR->setLightInfo( NULL, LIGHTMGR->setLightInfo( NULL,
NULL, NULL,
sceneData, sceneData,
state, state,
mCurrPass, 0,
pass.consts ); mConsts );
for ( U32 i=0; i < pass.materials.size(); i++ ) if (mDetailTexArrayConst->isValid())
{ GFX->setTextureArray(mDetailTexArrayConst->getSamplerRegister(), mTerrain->getDetailTextureArray());
MaterialInfo *matInfo = pass.materials[i]; if (mMacroTexArrayConst->isValid())
GFX->setTextureArray(mMacroTexArrayConst->getSamplerRegister(), mTerrain->getMacroTextureArray());
if (mNormalTexArrayConst->isValid())
GFX->setTextureArray(mNormalTexArrayConst->getSamplerRegister(), mTerrain->getNormalTextureArray());
if (mOrmTexArrayConst->isValid())
GFX->setTextureArray(mOrmTexArrayConst->getSamplerRegister(), mTerrain->getOrmTextureArray());
if ( matInfo->detailTexConst->isValid() ) mConsts->setSafe( mLayerSizeConst, (F32)mTerrain->mLayerTex.getWidth() );
GFX->setTexture( matInfo->detailTexConst->getSamplerRegister(), matInfo->detailTex );
if ( matInfo->macroTexConst->isValid() )
GFX->setTexture( matInfo->macroTexConst->getSamplerRegister(), matInfo->macroTex );
if ( matInfo->normalTexConst->isValid() )
GFX->setTexture( matInfo->normalTexConst->getSamplerRegister(), matInfo->normalTex );
if ( matInfo->ormTexConst->isValid() )
GFX->setTexture( matInfo->ormTexConst->getSamplerRegister(), matInfo->ormTex );
}
pass.consts->setSafe( pass.layerSizeConst, (F32)mTerrain->mLayerTex.getWidth() ); if ( mOneOverTerrainSizeConst->isValid() )
if ( pass.oneOverTerrainSize->isValid() )
{ {
F32 oneOverTerrainSize = 1.0f / mTerrain->getWorldBlockSize(); F32 oneOverTerrainSize = 1.0f / mTerrain->getWorldBlockSize();
pass.consts->set( pass.oneOverTerrainSize, oneOverTerrainSize ); mConsts->set( mOneOverTerrainSizeConst, oneOverTerrainSize );
} }
pass.consts->setSafe( pass.squareSize, mTerrain->getSquareSize() ); mConsts->setSafe( mSquareSizeConst, mTerrain->getSquareSize() );
if ( pass.fogDataConst->isValid() ) if ( mFogDataConst->isValid() )
{ {
Point3F fogData; Point3F fogData;
fogData.x = sceneData.fogDensity; fogData.x = sceneData.fogDensity;
fogData.y = sceneData.fogDensityOffset; fogData.y = sceneData.fogDensityOffset;
fogData.z = sceneData.fogHeightFalloff; fogData.z = sceneData.fogHeightFalloff;
pass.consts->set( pass.fogDataConst, fogData ); mConsts->set( mFogDataConst, fogData );
} }
pass.consts->setSafe( pass.fogColorConst, sceneData.fogColor ); mConsts->setSafe( mFogColorConst, sceneData.fogColor );
if ( pass.lightInfoBufferConst->isValid() && if ( mLightInfoBufferConst->isValid() &&
pass.lightParamsConst->isValid() ) mLightParamsConst->isValid() )
{ {
if ( !mLightInfoTarget ) if ( !mLightInfoTarget )
mLightInfoTarget = NamedTexTarget::find( "diffuseLighting" ); mLightInfoTarget = NamedTexTarget::find( "diffuseLighting" );
@ -900,17 +798,16 @@ bool TerrainCellMaterial::setupPass( const SceneRenderState *state,
if ( texObject ) if ( texObject )
{ {
GFX->setTexture( pass.lightInfoBufferConst->getSamplerRegister(), texObject ); GFX->setTexture( mLightInfoBufferConst->getSamplerRegister(), texObject );
const Point3I &targetSz = texObject->getSize(); const Point3I &targetSz = texObject->getSize();
const RectI &targetVp = mLightInfoTarget->getViewport(); const RectI &targetVp = mLightInfoTarget->getViewport();
Point4F rtParams; Point4F rtParams;
ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams); ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams);
pass.consts->setSafe( pass.lightParamsConst, rtParams ); mConsts->setSafe( mLightParamsConst, rtParams );
} }
} }
++mCurrPass;
return true; return true;
} }

View file

@ -40,6 +40,7 @@
#endif #endif
class GFXTextureArray;
class SceneRenderState; class SceneRenderState;
struct SceneData; struct SceneData;
class TerrainMaterial; class TerrainMaterial;
@ -58,8 +59,7 @@ protected:
public: public:
MaterialInfo() MaterialInfo()
:mat(NULL), layerId(0), detailTexConst(NULL), macroTexConst(NULL), normalTexConst(NULL), :mat(NULL), layerId(0)
ormTexConst(NULL), detailInfoVConst(NULL), detailInfoPConst(NULL), macroInfoVConst(NULL), macroInfoPConst(NULL)
{ {
} }
@ -69,95 +69,60 @@ protected:
TerrainMaterial *mat; TerrainMaterial *mat;
U32 layerId; U32 layerId;
GFXShaderConstHandle *detailTexConst;
GFXTexHandle detailTex;
GFXShaderConstHandle *macroTexConst;
GFXTexHandle macroTex;
GFXShaderConstHandle *normalTexConst;
GFXTexHandle normalTex;
GFXShaderConstHandle *ormTexConst;
GFXTexHandle ormTex;
GFXShaderConstHandle *detailInfoVConst;
GFXShaderConstHandle *detailInfoPConst;
GFXShaderConstHandle *macroInfoVConst;
GFXShaderConstHandle *macroInfoPConst;
}; };
class Pass
{
public:
Pass()
: shader( NULL ),
modelViewProjConst(NULL), worldViewOnly(NULL), viewToObj(NULL),
eyePosWorldConst(NULL), eyePosConst(NULL),
objTransConst(NULL), worldToObjConst(NULL), vEyeConst(NULL),
layerSizeConst(NULL), lightParamsConst(NULL), lightInfoBufferConst(NULL),
baseTexMapConst(NULL), layerTexConst(NULL),
lightMapTexConst(NULL),
squareSize(NULL), oneOverTerrainSize(NULL),
fogDataConst(NULL), fogColorConst(NULL)
{
}
~Pass()
{
for ( U32 i=0; i < materials.size(); i++ )
delete materials[i];
}
Vector<MaterialInfo*> materials;
/// ///
GFXShader *shader; GFXShader *mShader;
GFXShaderConstBufferRef consts; GFXShaderConstBufferRef mConsts;
GFXStateBlockRef stateBlock; GFXStateBlockRef mStateBlock;
GFXStateBlockRef wireframeStateBlock; GFXStateBlockRef mWireframeStateBlock;
GFXStateBlockRef reflectionStateBlock; GFXStateBlockRef mReflectionStateBlock;
GFXShaderConstHandle *modelViewProjConst; GFXShaderConstHandle *mModelViewProjConst;
GFXShaderConstHandle *worldViewOnly; GFXShaderConstHandle *mWorldViewOnlyConst;
GFXShaderConstHandle *viewToObj; GFXShaderConstHandle *mViewToObjConst;
GFXShaderConstHandle *eyePosWorldConst; GFXShaderConstHandle *mEyePosWorldConst;
GFXShaderConstHandle *eyePosConst; GFXShaderConstHandle *mEyePosConst;
GFXShaderConstHandle *objTransConst; GFXShaderConstHandle *mObjTransConst;
GFXShaderConstHandle *worldToObjConst; GFXShaderConstHandle *mWorldToObjConst;
GFXShaderConstHandle *vEyeConst; GFXShaderConstHandle *mVEyeConst;
GFXShaderConstHandle *layerSizeConst; GFXShaderConstHandle *mLayerSizeConst;
GFXShaderConstHandle *lightParamsConst; GFXShaderConstHandle *mLightParamsConst;
GFXShaderConstHandle *lightInfoBufferConst; GFXShaderConstHandle *mLightInfoBufferConst;
GFXShaderConstHandle *baseTexMapConst; GFXShaderConstHandle *mBaseTexMapConst;
GFXShaderConstHandle *layerTexConst; GFXShaderConstHandle *mLayerTexConst;
GFXShaderConstHandle *lightMapTexConst; GFXShaderConstHandle *mLightMapTexConst;
GFXShaderConstHandle *squareSize; GFXShaderConstHandle *mSquareSizeConst;
GFXShaderConstHandle *oneOverTerrainSize; GFXShaderConstHandle *mOneOverTerrainSizeConst;
GFXShaderConstHandle *fogDataConst; GFXShaderConstHandle* mDetailInfoVArrayConst;
GFXShaderConstHandle *fogColorConst; GFXShaderConstHandle* mDetailInfoPArrayConst;
}; GFXShaderConstHandle* mMacroInfoVArrayConst;
GFXShaderConstHandle* mMacroInfoPArrayConst;
GFXShaderConstHandle *mFogDataConst;
GFXShaderConstHandle *mFogColorConst;
GFXShaderConstHandle *mDetailTexArrayConst;
GFXShaderConstHandle *mMacroTexArrayConst;
GFXShaderConstHandle *mNormalTexArrayConst;
GFXShaderConstHandle *mOrmTexArrayConst;
TerrainBlock *mTerrain; TerrainBlock *mTerrain;
U64 mMaterials;
Vector<Pass> mPasses;
U32 mCurrPass; U32 mCurrPass;
U64 mMaterials;
Vector<MaterialInfo*> mMaterialInfos;
static const Vector<String> mSamplerNames; static const Vector<String> mSamplerNames;
GFXTexHandle mBaseMapTexture; GFXTexHandle mBaseMapTexture;
@ -175,14 +140,11 @@ protected:
/// A vector of all terrain cell materials loaded in the system. /// A vector of all terrain cell materials loaded in the system.
static Vector<TerrainCellMaterial*> smAllMaterials; static Vector<TerrainCellMaterial*> smAllMaterials;
bool _createPass( Vector<MaterialInfo*> *materials, bool _initShader( bool deferredMat,
Pass *pass,
bool firstPass,
bool deferredMat,
bool reflectMat, bool reflectMat,
bool baseOnly ); bool baseOnly );
void _updateMaterialConsts( Pass *pass ); void _updateMaterialConsts();
public: public:

View file

@ -52,6 +52,7 @@
#include "T3D/physics/physicsBody.h" #include "T3D/physics/physicsBody.h"
#include "T3D/physics/physicsCollision.h" #include "T3D/physics/physicsCollision.h"
#include "console/engineAPI.h" #include "console/engineAPI.h"
#include "core/util/safeRelease.h"
#include "T3D/assets/TerrainMaterialAsset.h" #include "T3D/assets/TerrainMaterialAsset.h"
using namespace Torque; using namespace Torque;
@ -203,7 +204,11 @@ TerrainBlock::TerrainBlock()
mScreenError( 16 ), mScreenError( 16 ),
mCastShadows( true ), mCastShadows( true ),
mZoningDirty( false ), mZoningDirty( false ),
mUpdateBasetex ( true ) mUpdateBasetex ( true ),
mDetailTextureArray( NULL ),
mMacroTextureArray( NULL ),
mOrmTextureArray( NULL ),
mNormalTextureArray( NULL )
{ {
mTypeMask = TerrainObjectType | StaticObjectType | StaticShapeObjectType; mTypeMask = TerrainObjectType | StaticObjectType | StaticShapeObjectType;
mNetFlags.set(Ghostable | ScopeAlways); mNetFlags.set(Ghostable | ScopeAlways);
@ -231,6 +236,11 @@ TerrainBlock::~TerrainBlock()
editor->detachTerrain(this); editor->detachTerrain(this);
#endif #endif
deleteZodiacPrimitiveBuffer(); deleteZodiacPrimitiveBuffer();
SAFE_RELEASE(mDetailTextureArray);
SAFE_RELEASE(mMacroTextureArray);
SAFE_RELEASE(mNormalTextureArray);
SAFE_RELEASE(mOrmTextureArray);
} }
void TerrainBlock::_onTextureEvent( GFXTexCallbackCode code ) void TerrainBlock::_onTextureEvent( GFXTexCallbackCode code )

View file

@ -135,6 +135,11 @@ protected:
/// ///
Vector<GFXTexHandle> mBaseTextures; Vector<GFXTexHandle> mBaseTextures;
GFXTextureArray* mDetailTextureArray;
GFXTextureArray* mMacroTextureArray;
GFXTextureArray* mNormalTextureArray;
GFXTextureArray* mOrmTextureArray;
/// ///
GFXTexHandle mLayerTex; GFXTexHandle mLayerTex;
@ -324,6 +329,11 @@ public:
U32 getMaterialCount() const; U32 getMaterialCount() const;
GFXTextureArray* getDetailTextureArray() const { return mDetailTextureArray; }
GFXTextureArray* getMacroTextureArray() const { return mMacroTextureArray; }
GFXTextureArray* getNormalTextureArray() const { return mNormalTextureArray; }
GFXTextureArray* getOrmTextureArray() const { return mOrmTextureArray; }
//BaseMatInstance* getMaterialInst( U32 x, U32 y ); //BaseMatInstance* getMaterialInst( U32 x, U32 y );
void setHeight( const Point2I &pos, F32 height ); void setHeight( const Point2I &pos, F32 height );

View file

@ -96,7 +96,7 @@ void TerrainBlock::_updateMaterials()
{ {
TerrainMaterial *mat = mFile->mMaterials[i]; TerrainMaterial *mat = mFile->mMaterials[i];
if (!mat->getDiffuseMap().isEmpty()) if (mat->getDiffuseMap().isNotEmpty())
{ {
mBaseTextures[i].set(mat->getDiffuseMap(), &GFXStaticTextureSRGBProfile, mBaseTextures[i].set(mat->getDiffuseMap(), &GFXStaticTextureSRGBProfile,
"TerrainBlock::_updateMaterials() - DiffuseMap"); "TerrainBlock::_updateMaterials() - DiffuseMap");
@ -114,6 +114,63 @@ void TerrainBlock::_updateMaterials()
mMaxDetailDistance = mat->getMacroDistance(); mMaxDetailDistance = mat->getMacroDistance();
} }
Vector<GFXTexHandle> detailTexArray;
detailTexArray.setSize(mFile->mMaterials.size());
Vector<GFXTexHandle> macroTexArray;
macroTexArray.setSize(mFile->mMaterials.size());
Vector<GFXTexHandle> normalTexArray;
normalTexArray.setSize(mFile->mMaterials.size());
Vector<GFXTexHandle> ormTexArray;
ormTexArray.setSize(mFile->mMaterials.size());
for (U32 i = 0; i < mFile->mMaterials.size(); i++)
{
TerrainMaterial* mat = mFile->mMaterials[i];
GFXTextureProfile* profile = &GFXStaticTextureProfile;
if (mat->getIsSRGB())
profile = &GFXStaticTextureSRGBProfile;
if (mat->getDetailMap().isNotEmpty())
detailTexArray[i] = TEXMGR->createTexture(mat->getDetailMap(), profile);
if (mat->getMacroMap().isNotEmpty())
macroTexArray[i] = TEXMGR->createTexture(mat->getMacroMap(), profile);
if (mat->getNormalMap().isNotEmpty())
normalTexArray[i] = TEXMGR->createTexture(mat->getNormalMap(), profile);
if (mat->getORMConfigMap().isNotEmpty())
ormTexArray[i] = TEXMGR->createTexture(mat->getORMConfigMap(), profile);
}
mDetailTextureArray = NULL;
mMacroTextureArray = NULL;
mNormalTextureArray = NULL;
mOrmTextureArray = NULL;
mDetailTextureArray = GFX->createTextureArray();
mMacroTextureArray = GFX->createTextureArray();
mNormalTextureArray = GFX->createTextureArray();
mOrmTextureArray = GFX->createTextureArray();
if(!mDetailTextureArray->fromTextureArray(detailTexArray))
{
Con::errorf("TerrainBlock::_updateMaterials - an issue with the diffuse terrain materials was detected. Please ensure they are all of the same size and format!");
}
if(!mMacroTextureArray->fromTextureArray(macroTexArray))
{
Con::errorf("TerrainBlock::_updateMaterials - an issue with the detail terrain materials was detected. Please ensure they are all of the same size and format!");
}
if(!mNormalTextureArray->fromTextureArray(normalTexArray))
{
Con::errorf("TerrainBlock::_updateMaterials - an issue with the normal terrain materials was detected. Please ensure they are all of the same size and format!");
}
if(!mOrmTextureArray->fromTextureArray(ormTexArray))
{
Con::errorf("TerrainBlock::_updateMaterials - an issue with the orm terrain materials was detected. Please ensure they are all of the same size and format!");
}
if ( mCell ) if ( mCell )
mCell->deleteMaterials(); mCell->deleteMaterials();
} }