Torque3D/Engine/source/gfx/gfxShader.cpp

199 lines
6 KiB
C++
Raw Normal View History

2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "gfx/gfxShader.h"
#include "shaderGen/conditionerFeature.h"
#include "core/volume.h"
#include "console/engineAPI.h"
Vector<GFXShaderMacro> GFXShader::smGlobalMacros;
bool GFXShader::smLogErrors = true;
bool GFXShader::smLogWarnings = true;
GFXShader::GFXShader()
: mPixVersion( 0.0f ),
2016-03-20 11:52:11 +00:00
mReloadKey( 0 ),
mInstancingFormat( NULL )
2012-09-19 15:15:01 +00:00
{
}
GFXShader::~GFXShader()
{
Torque::FS::RemoveChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
Torque::FS::RemoveChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
2016-03-20 11:52:11 +00:00
SAFE_DELETE(mInstancingFormat);
2012-09-19 15:15:01 +00:00
}
#ifndef TORQUE_OPENGL
2012-09-19 15:15:01 +00:00
bool GFXShader::init( const Torque::Path &vertFile,
const Torque::Path &pixFile,
F32 pixVersion,
const Vector<GFXShaderMacro> &macros )
{
Vector<String> samplerNames;
return init( vertFile, pixFile, pixVersion, macros, samplerNames );
}
#endif
bool GFXShader::init( const Torque::Path &vertFile,
const Torque::Path &pixFile,
F32 pixVersion,
const Vector<GFXShaderMacro> &macros,
2016-03-20 11:52:11 +00:00
const Vector<String> &samplerNames,
GFXVertexFormat *instanceFormat)
2012-09-19 15:15:01 +00:00
{
2016-03-20 11:52:11 +00:00
// Take care of instancing
if (instanceFormat)
{
mInstancingFormat = new GFXVertexFormat;
mInstancingFormat->copy(*instanceFormat);
}
2012-09-19 15:15:01 +00:00
// Store the inputs for use in reloading.
mVertexFile = vertFile;
mPixelFile = pixFile;
mPixVersion = pixVersion;
mMacros = macros;
mSamplerNamesOrdered = samplerNames;
2012-09-19 15:15:01 +00:00
// Before we compile the shader make sure the
// conditioner features have been updated.
ConditionerFeature::updateConditioners();
// Now do the real initialization.
if ( !_init() )
return false;
_updateDesc();
// Add file change notifications for reloads.
Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged );
Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged );
return true;
}
bool GFXShader::reload()
{
// Before we compile the shader make sure the
// conditioner features have been updated.
ConditionerFeature::updateConditioners();
mReloadKey++;
// Init does the work.
bool success = _init();
if ( success )
_updateDesc();
// Let anything that cares know that
// this shader has reloaded
mReloadSignal.trigger();
return success;
}
void GFXShader::_updateDesc()
{
mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ",
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), mPixVersion );
GFXShaderMacro::stringize( smGlobalMacros, &mDescription );
GFXShaderMacro::stringize( mMacros, &mDescription );
}
void GFXShader::addGlobalMacro( const String &name, const String &value )
{
// Check to see if we already have this macro.
Vector<GFXShaderMacro>::iterator iter = smGlobalMacros.begin();
for ( ; iter != smGlobalMacros.end(); iter++ )
{
if ( iter->name == name )
{
if ( iter->value != value )
iter->value = value;
return;
}
}
// Add a new macro.
smGlobalMacros.increment();
smGlobalMacros.last().name = name;
smGlobalMacros.last().value = value;
}
bool GFXShader::removeGlobalMacro( const String &name )
{
Vector<GFXShaderMacro>::iterator iter = smGlobalMacros.begin();
for ( ; iter != smGlobalMacros.end(); iter++ )
{
if ( iter->name == name )
{
smGlobalMacros.erase( iter );
return true;
}
}
return false;
}
void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf )
{
Vector<GFXShaderConstBuffer*>::iterator iter = mActiveBuffers.begin();
for ( ; iter != mActiveBuffers.end(); iter++ )
{
if ( *iter == buf )
{
mActiveBuffers.erase_fast( iter );
return;
}
}
AssertFatal( false, "GFXShader::_unlinkBuffer - buffer was not found?" );
}
DefineEngineFunction( addGlobalShaderMacro, void,
( const char *name, const char *value ), ( nullAsType<const char*>() ),
2012-09-19 15:15:01 +00:00
"Adds a global shader macro which will be merged with the script defined "
"macros on every shader. The macro will replace the value of an existing "
"macro of the same name. For the new macro to take effect all the shaders "
"in the system need to be reloaded.\n"
"@see resetLightManager, removeGlobalShaderMacro\n"
"@ingroup Rendering\n" )
{
GFXShader::addGlobalMacro( name, value );
}
DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),,
"Removes an existing global macro by name.\n"
"@see addGlobalShaderMacro\n"
"@ingroup Rendering\n" )
{
GFXShader::removeGlobalMacro( name );
}