Turn shader on/off at runtime
by Bryan Stroebel · in Torque Game Engine Advanced · 05/19/2006 (2:41 pm) · 2 replies
If you want to toggle shaders on/off at runtime while in the game here's what you need to do:
First we need to modify material.h . Add this right after DECLARE_CONOBJECT(Material);
Next we need to modify material.cpp. add this in the Material::Material() constructor function, at the end:
next add this to the end of material.cpp:
next we need to modify customMaterial.cpp. find CustomMaterial::setupSubPass( SceneGraphData &sgData ) and replace this:
Now open matInstance.h and put the following right under void construct();
now open matInstance.cpp and find the MatInstance::processMaterial() function. and change this:
next find MatInstance::setupPass( SceneGraphData &sgData ) and add the following right after
CustomMaterial *custMat = dynamic_cast(mMaterial);
First we need to modify material.h . Add this right after DECLARE_CONOBJECT(Material);
bool shaderON;//shader on/off bool tsSwitch;//toggle shader switch. needed for normal materials
Next we need to modify material.cpp. add this in the Material::Material() constructor function, at the end:
//BCS - Set defaults for toggleshader() and ChangeMaterial() shaderON = true; tsSwitch = false;
next add this to the end of material.cpp:
//BCS - toggle shader off/on
ConsoleMethod(Material,toggleshader,void,2,2,"toggleshader()")
{
object->tsSwitch = true;
object->shaderON = !object->shaderON;
}next we need to modify customMaterial.cpp. find CustomMaterial::setupSubPass( SceneGraphData &sgData ) and replace this:
if( mShaderData && mShaderData->shader)with this:
if( mShaderData && mShaderData->shader && shaderON)
Now open matInstance.h and put the following right under void construct();
//BCS - toggle shader off/on void disableShaderFeatures( U32 stageNum, U32 maxstages, GFXShaderFeatureData &fd ); void enableStageFeatures(U32 stageNum, U32 maxstages); Vector<bool> vMatboolSet; //holds all original material bool settings
now open matInstance.cpp and find the MatInstance::processMaterial() function. and change this:
for( U32 i=0; i<mMaxStages; i++ )
{
GFXShaderFeatureData fd;
determineFeatures( i, fd );
if( fd.codify() )
{
createPasses( fd, i );
}
}to this:for( U32 i=0; i<mMaxStages; i++ )
{
GFXShaderFeatureData fd;
//BCS - added support for toggle shader on/off
if(mMaterial->shaderON)
{
if(mMaterial->tsSwitch)
{
enableStageFeatures(i,mMaxStages);
}
determineFeatures( i, fd );
}
else
{
disableShaderFeatures( i, mMaxStages, fd );
}
//********************************************
if( fd.codify() )
{
createPasses( fd, i );
}
}
if(mMaterial->shaderON){vMatboolSet.clear();}next find MatInstance::setupPass( SceneGraphData &sgData ) and add the following right after
CustomMaterial *custMat = dynamic_cast
//BCS - reinit material if toggleing shader ********************
if(mMaterial->tsSwitch)
{
reInit();
mMaterial->tsSwitch = false;
}
Torque Owner Bryan Stroebel
now add these two functions to the end of the matInstance.cpp file:
//BCS - disables all shader features for a material when toggleshader() //turns the shader off. shaderON = false void MatInstance::disableShaderFeatures( U32 stageNum, U32 maxstages, GFXShaderFeatureData &fd ) { //before we disable all the shader features and values we need //to place the original values in a vector incase we want to turn //the shader back on. if(stageNum == 0) { // on the first stage save the non-stage data to the vector vMatboolSet.push_back(mMaterial->castsShadow); vMatboolSet.push_back(mMaterial->breakable); vMatboolSet.push_back(mMaterial->doubleSided); vMatboolSet.push_back(mMaterial->dynamicCubemap); vMatboolSet.push_back(mMaterial->translucent); vMatboolSet.push_back(mMaterial->translucentZWrite); vMatboolSet.push_back(mMaterial->planarReflection); // and disable the non-stage data on the material. mMaterial->castsShadow = false; mMaterial->breakable = false; mMaterial->doubleSided = false; mMaterial->dynamicCubemap = false; mMaterial->translucent = false; mMaterial->translucentZWrite = false; mMaterial->planarReflection = false; } //for each stage save the stage data to the vector vMatboolSet.push_back(mMaterial->pixelSpecular[stageNum]); vMatboolSet.push_back(mMaterial->vertexSpecular[stageNum]); vMatboolSet.push_back(mMaterial->glow[stageNum]); vMatboolSet.push_back(mMaterial->emissive[stageNum]); //disable all shader features per pass except for the base texture // we still want the base texture to show. for( U32 i=0; i<GFXShaderFeatureData::NumFeatures; i++ ) { if( i == GFXShaderFeatureData::BaseTex) { fd.features[i] = true; } else { fd.features[i] = false; } } //disable stage data for each stage mMaterial->pixelSpecular[stageNum] = false; mMaterial->vertexSpecular[stageNum] = false; mMaterial->glow[stageNum] = false; mMaterial->emissive[stageNum] = false; } //BCS - enables the original shader boolean values when //toggleshader() turns the shader back on. shaderON = true void MatInstance::enableStageFeatures(U32 stageNum,U32 maxstages) { U32 i = stageNum * 4; //on the first stage set the materials non-stage values //from the vector. if(stageNum == 0) { mMaterial->castsShadow = vMatboolSet[stageNum]; mMaterial->breakable = vMatboolSet[stageNum+1]; mMaterial->doubleSided = vMatboolSet[stageNum+2]; mMaterial->dynamicCubemap = vMatboolSet[stageNum+3]; mMaterial->translucent = vMatboolSet[stageNum+4]; mMaterial->translucentZWrite = vMatboolSet[stageNum+5]; mMaterial->planarReflection = vMatboolSet[stageNum+6]; } //set the original stage values, for each stage, from the vector mMaterial->pixelSpecular[stageNum] = vMatboolSet[i+7]; mMaterial->vertexSpecular[stageNum] = vMatboolSet[i+8]; mMaterial->glow[stageNum] = vMatboolSet[i+9]; mMaterial->emissive[stageNum] = vMatboolSet[i+10]; }What happens is, when we turn the shader off we save the origianl shader values in a vector so we can reassign them when we turn the shader back on.
Now compile and run TSE. Use the following to toggle the shader off and on:
material.toggleshader();
for example: to toggle the orcskin shader off and on you would type:
orckskin.toggleshader();
orckskin.toggleshader();
Right now this turns all shading features off but you could look at the disableShaderFeatures function and only turn off what you want.
Hope this helps.