Torque3D/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp

3184 lines
111 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 "shaderGen/HLSL/shaderFeatureHLSL.h"
#include "shaderGen/langElement.h"
#include "shaderGen/shaderOp.h"
#include "shaderGen/shaderGenVars.h"
#include "gfx/gfxDevice.h"
#include "materials/matInstance.h"
#include "materials/processedMaterial.h"
#include "materials/materialFeatureTypes.h"
#include "core/util/autoPtr.h"
#include "lighting/advanced/advancedLightBinManager.h"
#include "ts/tsShape.h"
2012-09-19 15:15:01 +00:00
#include "shaderGen/shaderGen.h"
2012-09-19 15:15:01 +00:00
LangElement * ShaderFeatureHLSL::setupTexSpaceMat( Vector<ShaderComponent*> &, // componentList
Var **texSpaceMat )
{
Var *N = (Var*) LangElement::find( "normal" );
Var *B = (Var*) LangElement::find( "B" );
Var *T = (Var*) LangElement::find( "T" );
Var *tangentW = (Var*) LangElement::find( "tangentW" );
// setup matrix var
*texSpaceMat = new Var;
(*texSpaceMat)->setType( "float3x3" );
(*texSpaceMat)->setName( "objToTangentSpace" );
MultiLine *meta = new MultiLine;
meta->addStatement( new GenOp( " @;\r\n", new DecOp( *texSpaceMat ) ) );
// Protect against missing normal and tangent.
if ( !N || !T )
{
meta->addStatement( new GenOp( " @[0] = float3( 1, 0, 0 ); @[1] = float3( 0, 1, 0 ); @[2] = float3( 0, 0, 1 );\r\n",
*texSpaceMat, *texSpaceMat, *texSpaceMat ) );
return meta;
}
meta->addStatement( new GenOp( " @[0] = @;\r\n", *texSpaceMat, T ) );
if ( B )
meta->addStatement( new GenOp( " @[1] = @;\r\n", *texSpaceMat, B ) );
else
{
if(dStricmp((char*)T->type, "float4") == 0)
meta->addStatement( new GenOp( " @[1] = cross( @, normalize(@) ) * @.w;\r\n", *texSpaceMat, T, N, T ) );
else if (tangentW)
meta->addStatement(new GenOp(" @[1] = cross( @, normalize(@) ) * @;\r\n", *texSpaceMat, T, N, tangentW));
2012-09-19 15:15:01 +00:00
else
meta->addStatement( new GenOp( " @[1] = cross( @, normalize(@) );\r\n", *texSpaceMat, T, N ) );
}
meta->addStatement( new GenOp( " @[2] = normalize(@);\r\n", *texSpaceMat, N ) );
return meta;
}
LangElement* ShaderFeatureHLSL::assignColor( LangElement *elem,
Material::BlendOp blend,
LangElement *lerpElem,
ShaderFeature::OutputTarget outputTarget )
{
// search for color var
Var *color = (Var*) LangElement::find( getOutputTargetVarName(outputTarget) );
if ( !color )
{
// create color var
color = new Var;
color->setType( "fragout" );
color->setName( getOutputTargetVarName(outputTarget) );
color->setStructName( "OUT" );
return new GenOp( "@ = @", color, elem );
}
LangElement *assign;
switch ( blend )
{
case Material::Add:
assign = new GenOp( "@ += @", color, elem );
break;
case Material::Sub:
assign = new GenOp( "@ -= @", color, elem );
break;
case Material::Mul:
assign = new GenOp( "@ *= @", color, elem );
break;
case Material::PreMul:
assign = new GenOp("@.rgb = @.rgb + (@.rgb*(1.0-@.a))", color, elem, color, elem);
break;
2012-09-19 15:15:01 +00:00
case Material::AddAlpha:
assign = new GenOp( "@ += @ * @.a", color, elem, elem );
break;
case Material::LerpAlpha:
if ( !lerpElem )
lerpElem = elem;
assign = new GenOp( "@.rgb = lerp( @.rgb, (@).rgb, (@).a )", color, color, elem, lerpElem );
break;
case Material::ToneMap:
assign = new GenOp( "@ = 1.0 - exp(-1.0 * @ * @)", color, color, elem );
break;
default:
AssertFatal(false, "Unrecognized color blendOp");
// Fallthru
case Material::None:
assign = new GenOp( "@ = @", color, elem );
break;
}
return assign;
}
LangElement *ShaderFeatureHLSL::expandNormalMap( LangElement *sampleNormalOp,
LangElement *normalDecl,
LangElement *normalVar,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
const bool hasBc3 = fd.features.hasFeature(MFT_IsBC3nm, getProcessIndex() );
const bool hasBc5 = fd.features.hasFeature(MFT_IsBC5nm, getProcessIndex() );
if ( hasBc3 || hasBc5 )
2012-09-19 15:15:01 +00:00
{
if ( fd.features[MFT_ImposterVert] )
{
// The imposter system uses object space normals and
// encodes them with the z axis in the alpha component.
meta->addStatement( new GenOp( " @ = float4( normalize( @.xyw * 2.0 - 1.0 ), 0.0 ); // Obj DXTnm\r\n", normalDecl, sampleNormalOp ) );
}
else if( hasBc3 )
2012-09-19 15:15:01 +00:00
{
// BC3 Swizzle trick
2012-09-19 15:15:01 +00:00
meta->addStatement( new GenOp( " @ = float4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) );
meta->addStatement( new GenOp( " @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // DXTnm\r\n", normalVar, normalVar, normalVar ) );
}
else if (hasBc5)
{
// BC5
meta->addStatement(new GenOp(" @ = float4( @.gr * 2.0 - 1.0, 0.0, 0.0 ); // bc5nm\r\n", normalDecl, sampleNormalOp ) );
meta->addStatement(new GenOp(" @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // bc5nm\r\n", normalVar, normalVar, normalVar )) ;
}
2012-09-19 15:15:01 +00:00
}
else
{
meta->addStatement( new GenOp( " @ = @;\r\n", normalDecl, sampleNormalOp ) );
meta->addStatement( new GenOp( " @.xyz = @.xyz * 2.0 - 1.0;\r\n", normalVar, normalVar ) );
}
return meta;
}
ShaderFeatureHLSL::ShaderFeatureHLSL()
{
output = NULL;
}
Var * ShaderFeatureHLSL::getVertTexCoord( const String &name )
{
Var *inTex = NULL;
for( U32 i=0; i<LangElement::elementList.size(); i++ )
{
if( !String::compare( (char*)LangElement::elementList[i]->name, name.c_str() ) )
2012-09-19 15:15:01 +00:00
{
inTex = dynamic_cast<Var*>( LangElement::elementList[i] );
if ( inTex )
{
// NOTE: This used to do this check...
//
// String::compare( (char*)inTex->structName, "IN" )
2012-09-19 15:15:01 +00:00
//
// ... to ensure that the var was from the input
// vertex structure, but this kept some features
// ( ie. imposter vert ) from decoding their own
// coords for other features to use.
//
// If we run into issues with collisions between
// IN vars and local vars we may need to revise.
break;
}
}
}
return inTex;
}
Var* ShaderFeatureHLSL::getOutObjToTangentSpace( Vector<ShaderComponent*> &componentList,
MultiLine *meta,
const MaterialFeatureData &fd )
{
Var *outObjToTangentSpace = (Var*)LangElement::find( "objToTangentSpace" );
if ( !outObjToTangentSpace )
meta->addStatement( setupTexSpaceMat( componentList, &outObjToTangentSpace ) );
return outObjToTangentSpace;
}
Var* ShaderFeatureHLSL::getOutWorldToTangent( Vector<ShaderComponent*> &componentList,
MultiLine *meta,
const MaterialFeatureData &fd )
{
Var *outWorldToTangent = (Var*)LangElement::find( "outWorldToTangent" );
if ( outWorldToTangent )
return outWorldToTangent;
Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" );
if ( !worldToTangent )
{
Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd );
if (!fd.features[MFT_ParticleNormal] )
{
// turn obj->tangent into world->tangent
worldToTangent = new Var;
worldToTangent->setType( "float3x3" );
worldToTangent->setName( "worldToTangent" );
LangElement *worldToTangentDecl = new DecOp( worldToTangent );
// Get the world->obj transform
Var *worldToObj = (Var*)LangElement::find( "worldToObj" );
if ( !worldToObj )
{
worldToObj = new Var;
worldToObj->setName( "worldToObj" );
if ( fd.features[MFT_UseInstancing] )
{
// We just use transpose to convert the 3x3 portion of
// the object transform to its inverse.
worldToObj->setType( "float3x3" );
Var *objTrans = getObjTrans( componentList, true, meta );
meta->addStatement( new GenOp( " @ = transpose( (float3x3)@ ); // Instancing!\r\n", new DecOp( worldToObj ), objTrans ) );
}
else
{
worldToObj->setType( "float4x4" );
worldToObj->uniform = true;
worldToObj->constSortPos = cspPrimitive;
}
}
// assign world->tangent transform
meta->addStatement( new GenOp( " @ = mul( @, (float3x3)@ );\r\n", worldToTangentDecl, texSpaceMat, worldToObj ) );
}
else
{
// Assume particle normal generation has set this up in the proper space
worldToTangent = texSpaceMat;
}
}
// send transform to pixel shader
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
outWorldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
outWorldToTangent->setName( "outWorldToTangent" );
outWorldToTangent->setStructName( "OUT" );
outWorldToTangent->setType( "float3x3" );
meta->addStatement( new GenOp( " @ = @;\r\n", outWorldToTangent, worldToTangent ) );
return outWorldToTangent;
}
Var* ShaderFeatureHLSL::getOutViewToTangent( Vector<ShaderComponent*> &componentList,
MultiLine *meta,
const MaterialFeatureData &fd )
{
Var *outViewToTangent = (Var*)LangElement::find( "outViewToTangent" );
if ( outViewToTangent )
return outViewToTangent;
Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" );
if ( !viewToTangent )
{
Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd );
if ( !fd.features[MFT_ParticleNormal] )
{
// turn obj->tangent into world->tangent
viewToTangent = new Var;
viewToTangent->setType( "float3x3" );
viewToTangent->setName( "viewToTangent" );
LangElement *viewToTangentDecl = new DecOp( viewToTangent );
// Get the view->obj transform
Var *viewToObj = getInvWorldView( componentList, fd.features[MFT_UseInstancing], meta );
// assign world->tangent transform
meta->addStatement( new GenOp( " @ = mul( @, (float3x3)@ );\r\n", viewToTangentDecl, texSpaceMat, viewToObj ) );
}
else
{
// Assume particle normal generation has set this up in the proper space
viewToTangent = texSpaceMat;
}
}
// send transform to pixel shader
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
outViewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
outViewToTangent->setName( "outViewToTangent" );
outViewToTangent->setStructName( "OUT" );
outViewToTangent->setType( "float3x3" );
meta->addStatement( new GenOp( " @ = @;\r\n", outViewToTangent, viewToTangent ) );
return outViewToTangent;
}
Var* ShaderFeatureHLSL::getOutTexCoord( const char *name,
const char *type,
bool useTexAnim,
MultiLine *meta,
Vector<ShaderComponent*> &componentList )
{
String outTexName = String::ToString( "out_%s", name );
Var *texCoord = (Var*)LangElement::find( outTexName );
if ( !texCoord )
{
Var *inTex = getVertTexCoord( name );
AssertFatal( inTex, "ShaderFeatureHLSL::getOutTexCoord - Unknown vertex input coord!" );
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
texCoord = connectComp->getElement( RT_TEXCOORD );
texCoord->setName( outTexName );
texCoord->setStructName( "OUT" );
texCoord->setType( type );
if ( useTexAnim )
{
2016-03-20 11:52:11 +00:00
inTex->setType( "float2" );
2012-09-19 15:15:01 +00:00
// create texture mat var
Var *texMat = new Var;
texMat->setType( "float4x4" );
texMat->setName( "texMat" );
texMat->uniform = true;
texMat->constSortPos = cspPass;
// Statement allows for casting of different types which
// eliminates vector truncation problems.
2016-03-20 11:52:11 +00:00
String statement = String::ToString(" @ = (%s)mul(@, float4(@,1,1));\r\n", type);
2012-09-19 15:15:01 +00:00
meta->addStatement( new GenOp( statement, texCoord, texMat, inTex ) );
}
else
{
// Statement allows for casting of different types which
// eliminates vector truncation problems.
String statement = String::ToString( " @ = (%s)@;\r\n", type );
meta->addStatement( new GenOp( statement, texCoord, inTex ) );
}
}
AssertFatal( String::compare( type, (const char*)texCoord->type ) == 0,
2012-09-19 15:15:01 +00:00
"ShaderFeatureHLSL::getOutTexCoord - Type mismatch!" );
return texCoord;
}
Var* ShaderFeatureHLSL::getInTexCoord( const char *name,
const char *type,
Vector<ShaderComponent*> &componentList )
{
Var* texCoord = (Var*)LangElement::find( name );
if ( !texCoord )
{
ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>( componentList[C_CONNECTOR] );
texCoord = connectComp->getElement( RT_TEXCOORD );
texCoord->setName( name );
texCoord->setStructName( "IN" );
texCoord->setType( type );
}
AssertFatal( String::compare( type, (const char*)texCoord->type ) == 0,
"ShaderFeatureHLSL::getInTexCoord - Type mismatch!" );
2012-09-19 15:15:01 +00:00
return texCoord;
}
Var* ShaderFeatureHLSL::getInColor( const char *name,
const char *type,
Vector<ShaderComponent*> &componentList )
{
Var *inColor = (Var*)LangElement::find( name );
if ( !inColor )
{
ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>( componentList[C_CONNECTOR] );
inColor = connectComp->getElement( RT_COLOR );
inColor->setName( name );
inColor->setStructName( "IN" );
inColor->setType( type );
}
AssertFatal( String::compare( type, (const char*)inColor->type ) == 0,
2012-09-19 15:15:01 +00:00
"ShaderFeatureHLSL::getInColor - Type mismatch!" );
return inColor;
}
Var* ShaderFeatureHLSL::addOutVpos( MultiLine *meta,
Vector<ShaderComponent*> &componentList )
{
// Nothing to do if we're on SM 3.0... we use the real vpos.
if ( GFX->getPixelShaderVersion() >= 3.0f )
return NULL;
// For SM 2.x we need to generate the vpos in the vertex shader
// and pass it as a texture coord to the pixel shader.
Var *outVpos = (Var*)LangElement::find( "outVpos" );
if ( !outVpos )
{
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
outVpos = connectComp->getElement( RT_TEXCOORD );
outVpos->setName( "outVpos" );
outVpos->setStructName( "OUT" );
outVpos->setType( "float4" );
2012-09-19 15:15:01 +00:00
Var *outPosition = (Var*) LangElement::find( "hpos" );
AssertFatal( outPosition, "ShaderFeatureHLSL::addOutVpos - Didn't find the output position." );
meta->addStatement( new GenOp( " @ = @;\r\n", outVpos, outPosition ) );
2012-09-19 15:15:01 +00:00
}
return outVpos;
}
Var* ShaderFeatureHLSL::getInVpos( MultiLine *meta,
Vector<ShaderComponent*> &componentList )
{
Var *inVpos = (Var*)LangElement::find( "vpos" );
if ( inVpos )
return inVpos;
2017-05-28 21:51:31 +00:00
ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
2012-09-19 15:15:01 +00:00
2017-05-28 21:51:31 +00:00
inVpos = connectComp->getElement( RT_SVPOSITION );
inVpos->setName( "vpos" );
2012-09-19 15:15:01 +00:00
inVpos->setStructName( "IN" );
inVpos->setType( "float4" );
2017-05-28 21:51:31 +00:00
return inVpos;
2012-09-19 15:15:01 +00:00
}
Var* ShaderFeatureHLSL::getInWorldToTangent( Vector<ShaderComponent*> &componentList )
{
Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" );
if ( !worldToTangent )
{
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
worldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
worldToTangent->setName( "worldToTangent" );
worldToTangent->setStructName( "IN" );
worldToTangent->setType( "float3x3" );
}
return worldToTangent;
}
Var* ShaderFeatureHLSL::getInViewToTangent( Vector<ShaderComponent*> &componentList )
{
Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" );
if ( !viewToTangent )
{
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
viewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
viewToTangent->setName( "viewToTangent" );
viewToTangent->setStructName( "IN" );
viewToTangent->setType( "float3x3" );
}
return viewToTangent;
}
Var* ShaderFeatureHLSL::getNormalMapTex()
{
2016-03-20 11:52:11 +00:00
Var *normalMap = (Var*)LangElement::find("bumpMap");
if (!normalMap)
2012-09-19 15:15:01 +00:00
{
normalMap = new Var;
2017-05-28 21:51:31 +00:00
normalMap->setType("SamplerState");
2016-03-20 11:52:11 +00:00
normalMap->setName("bumpMap");
2012-09-19 15:15:01 +00:00
normalMap->uniform = true;
normalMap->sampler = true;
normalMap->constNum = Var::getTexUnitNum();
2016-03-20 11:52:11 +00:00
2017-05-28 21:51:31 +00:00
Var* normalMapTex = new Var;
normalMapTex->setName("bumpMapTex");
normalMapTex->setType("Texture2D");
normalMapTex->uniform = true;
normalMapTex->texture = true;
normalMapTex->constNum = normalMap->constNum;
2012-09-19 15:15:01 +00:00
}
return normalMap;
}
Var* ShaderFeatureHLSL::getObjTrans( Vector<ShaderComponent*> &componentList,
bool useInstancing,
MultiLine *meta )
{
Var *objTrans = (Var*)LangElement::find( "objTrans" );
if ( objTrans )
return objTrans;
if ( useInstancing )
{
ShaderConnector *vertStruct = dynamic_cast<ShaderConnector *>( componentList[C_VERT_STRUCT] );
Var *instObjTrans = vertStruct->getElement( RT_TEXCOORD, 4, 4 );
instObjTrans->setStructName( "IN" );
instObjTrans->setName( "inst_objectTrans" );
mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+0 );
mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+1 );
mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+2 );
mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+3 );
objTrans = new Var;
objTrans->setType( "float4x4" );
objTrans->setName( "objTrans" );
meta->addStatement( new GenOp( " @ = { // Instancing!\r\n", new DecOp( objTrans ), instObjTrans ) );
meta->addStatement( new GenOp( " @[0],\r\n", instObjTrans ) );
meta->addStatement( new GenOp( " @[1],\r\n", instObjTrans ) );
meta->addStatement( new GenOp( " @[2],\r\n",instObjTrans ) );
meta->addStatement( new GenOp( " @[3] };\r\n", instObjTrans ) );
}
else
{
objTrans = new Var;
objTrans->setType( "float4x4" );
objTrans->setName( "objTrans" );
objTrans->uniform = true;
objTrans->constSortPos = cspPrimitive;
}
return objTrans;
}
Var* ShaderFeatureHLSL::getModelView( Vector<ShaderComponent*> &componentList,
bool useInstancing,
MultiLine *meta )
{
Var *modelview = (Var*)LangElement::find( "modelview" );
if ( modelview )
return modelview;
if ( useInstancing )
{
Var *objTrans = getObjTrans( componentList, useInstancing, meta );
Var *viewProj = (Var*)LangElement::find( "viewProj" );
if ( !viewProj )
{
viewProj = new Var;
viewProj->setType( "float4x4" );
viewProj->setName( "viewProj" );
viewProj->uniform = true;
viewProj->constSortPos = cspPass;
}
modelview = new Var;
modelview->setType( "float4x4" );
modelview->setName( "modelview" );
meta->addStatement( new GenOp( " @ = mul( @, @ ); // Instancing!\r\n", new DecOp( modelview ), viewProj, objTrans ) );
}
else
{
modelview = new Var;
modelview->setType( "float4x4" );
modelview->setName( "modelview" );
modelview->uniform = true;
modelview->constSortPos = cspPrimitive;
}
return modelview;
}
Var* ShaderFeatureHLSL::getWorldView( Vector<ShaderComponent*> &componentList,
bool useInstancing,
MultiLine *meta )
{
Var *worldView = (Var*)LangElement::find( "worldViewOnly" );
if ( worldView )
return worldView;
if ( useInstancing )
{
Var *objTrans = getObjTrans( componentList, useInstancing, meta );
Var *worldToCamera = (Var*)LangElement::find( "worldToCamera" );
if ( !worldToCamera )
{
worldToCamera = new Var;
worldToCamera->setType( "float4x4" );
worldToCamera->setName( "worldToCamera" );
worldToCamera->uniform = true;
worldToCamera->constSortPos = cspPass;
}
worldView = new Var;
worldView->setType( "float4x4" );
worldView->setName( "worldViewOnly" );
meta->addStatement( new GenOp( " @ = mul( @, @ ); // Instancing!\r\n", new DecOp( worldView ), worldToCamera, objTrans ) );
}
else
{
worldView = new Var;
worldView->setType( "float4x4" );
worldView->setName( "worldViewOnly" );
worldView->uniform = true;
worldView->constSortPos = cspPrimitive;
}
return worldView;
}
Var* ShaderFeatureHLSL::getInvWorldView( Vector<ShaderComponent*> &componentList,
bool useInstancing,
MultiLine *meta )
{
Var *viewToObj = (Var*)LangElement::find( "viewToObj" );
if ( viewToObj )
return viewToObj;
if ( useInstancing )
{
Var *worldView = getWorldView( componentList, useInstancing, meta );
viewToObj = new Var;
viewToObj->setType( "float3x3" );
viewToObj->setName( "viewToObj" );
// We just use transpose to convert the 3x3 portion
// of the world view transform into its inverse.
meta->addStatement( new GenOp( " @ = transpose( (float3x3)@ ); // Instancing!\r\n", new DecOp( viewToObj ), worldView ) );
}
else
{
viewToObj = new Var;
viewToObj->setType( "float4x4" );
viewToObj->setName( "viewToObj" );
viewToObj->uniform = true;
viewToObj->constSortPos = cspPrimitive;
}
return viewToObj;
}
void ShaderFeatureHLSL::getWsPosition( Vector<ShaderComponent*> &componentList,
bool useInstancing,
MultiLine *meta,
LangElement *wsPosition )
{
Var *inPosition = (Var*)LangElement::find( "wsPosition" );
if ( inPosition )
{
meta->addStatement( new GenOp( " @ = @.xyz;\r\n",
wsPosition, inPosition ) );
return;
}
// Get the input position.
inPosition = (Var*)LangElement::find( "inPosition" );
if ( !inPosition )
inPosition = (Var*)LangElement::find( "position" );
AssertFatal( inPosition, "ShaderFeatureHLSL::getWsPosition - The vertex position was not found!" );
Var *objTrans = getObjTrans( componentList, useInstancing, meta );
meta->addStatement( new GenOp( " @ = mul( @, float4( @.xyz, 1 ) ).xyz;\r\n",
wsPosition, objTrans, inPosition ) );
}
Var* ShaderFeatureHLSL::addOutWsPosition( Vector<ShaderComponent*> &componentList,
bool useInstancing,
MultiLine *meta )
{
Var *outWsPosition = (Var*)LangElement::find( "outWsPosition" );
if ( !outWsPosition )
{
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
outWsPosition = connectComp->getElement( RT_TEXCOORD );
outWsPosition->setName( "outWsPosition" );
outWsPosition->setStructName( "OUT" );
outWsPosition->setType( "float3" );
getWsPosition( componentList, useInstancing, meta, outWsPosition );
}
return outWsPosition;
}
Var* ShaderFeatureHLSL::getInWsPosition( Vector<ShaderComponent*> &componentList )
{
Var *wsPosition = (Var*)LangElement::find( "wsPosition" );
if ( !wsPosition )
{
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
wsPosition = connectComp->getElement( RT_TEXCOORD );
wsPosition->setName( "wsPosition" );
wsPosition->setStructName( "IN" );
wsPosition->setType( "float3" );
}
return wsPosition;
}
Var* ShaderFeatureHLSL::getWsView( Var *wsPosition, MultiLine *meta )
{
Var *wsView = (Var*)LangElement::find( "wsView" );
if ( !wsView )
{
wsView = new Var( "wsView", "float3" );
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
if ( !eyePos )
{
eyePos = new Var;
eyePos->setType( "float3" );
eyePos->setName( "eyePosWorld" );
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
meta->addStatement( new GenOp( " @ = @ - @;\r\n",
2012-09-19 15:15:01 +00:00
new DecOp( wsView ), eyePos, wsPosition ) );
}
return wsView;
}
Var* ShaderFeatureHLSL::getInWorldNormal(Vector<ShaderComponent*>& componentList)
{
Var* wsNormal = (Var*)LangElement::find("wsNormal");
if (!wsNormal)
{
ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
wsNormal = connectComp->getElement(RT_TEXCOORD);
wsNormal->setName("wsNormal");
wsNormal->setStructName("IN");
wsNormal->setType("float3");
}
return wsNormal;
}
2012-09-19 15:15:01 +00:00
Var* ShaderFeatureHLSL::addOutDetailTexCoord( Vector<ShaderComponent*> &componentList,
MultiLine *meta,
bool useTexAnim,
bool useFoliageTexCoord)
2012-09-19 15:15:01 +00:00
{
// Check if its already added.
Var *outTex = (Var*)LangElement::find( "detCoord" );
if ( outTex )
return outTex;
// Grab incoming texture coords.
Var *inTex = getVertTexCoord( "texCoord" );
if (useFoliageTexCoord)
inTex->setType("float4");
else
inTex->setType("float2");
2012-09-19 15:15:01 +00:00
// create detail variable
Var *detScale = new Var;
detScale->setType( "float2" );
detScale->setName( "detailScale" );
detScale->uniform = true;
detScale->constSortPos = cspPotentialPrimitive;
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
outTex = connectComp->getElement( RT_TEXCOORD );
outTex->setName( "detCoord" );
outTex->setStructName( "OUT" );
outTex->setType( "float2" );
if ( useTexAnim )
{
// Find or create the texture matrix.
Var *texMat = (Var*)LangElement::find( "texMat" );
if ( !texMat )
{
texMat = new Var;
texMat->setType( "float4x4" );
texMat->setName( "texMat" );
texMat->uniform = true;
texMat->constSortPos = cspPass;
}
meta->addStatement(new GenOp(" @ = mul(@, float4(@.xy,1,1)).xy * @;\r\n", outTex, texMat, inTex, detScale));
2012-09-19 15:15:01 +00:00
}
else
{
// setup output to mul texCoord by detail scale
meta->addStatement( new GenOp( " @ = @.xy * @;\r\n", outTex, inTex, detScale ) );
2012-09-19 15:15:01 +00:00
}
return outTex;
}
Var* ShaderFeatureHLSL::getSurface(Vector<ShaderComponent*>& componentList, MultiLine* meta, const MaterialFeatureData& fd)
{
Var *surface = (Var *)LangElement::find("surface");
if (!surface)
{
Var *diffuseColor = (Var *)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
Var *ormConfig = (Var *)LangElement::find("ORMConfig");
2020-09-30 18:51:12 +00:00
if (!ormConfig)
{
Var *metalness = (Var *)LangElement::find("metalness");
if (!metalness)
{
metalness = new Var("metalness", "float");
metalness->uniform = true;
metalness->constSortPos = cspPotentialPrimitive;
}
Var *roughness = (Var *)LangElement::find("roughness");
2020-09-30 18:51:12 +00:00
if (!roughness)
{
2020-09-30 18:51:12 +00:00
roughness = new Var("roughness", "float");
roughness->uniform = true;
roughness->constSortPos = cspPotentialPrimitive;
}
2020-09-30 18:51:12 +00:00
ormConfig = new Var("ORMConfig", "float4");
LangElement *colorDecl = new DecOp(ormConfig);
2020-09-30 18:51:12 +00:00
meta->addStatement(new GenOp(" @ = float4(0.0,1.0,@,@);\r\n", colorDecl, roughness, metalness)); //reconstruct matinfo, no ao darkening
}
Var *normal = (Var *)LangElement::find("normal");
if (!normal)
{
normal = new Var("normal", "float3");
meta->addStatement(new GenOp(" @;\r\n\n", new DecOp(normal)));
Var *wsNormal = (Var *)LangElement::find("wsNormal");
if (!wsNormal)
wsNormal = getInWorldNormal(componentList);
meta->addStatement(new GenOp(" @ = normalize( @ );\r\n", normal, wsNormal));
}
Var *wsEyePos = (Var *)LangElement::find("eyePosWorld");
2021-10-07 01:53:26 +00:00
if (!wsEyePos)
{
wsEyePos = new Var("eyePosWorld", "float3");
wsEyePos->uniform = true;
wsEyePos->constSortPos = cspPass;
}
Var *wsPosition = getInWsPosition(componentList);
Var *wsView = getWsView(wsPosition, meta);
surface = new Var("surface", "Surface");
meta->addStatement(new GenOp(" @ = createForwardSurface(@,normalize(@),@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, normal, ormConfig,
wsPosition, wsEyePos, wsView));
}
return surface;
}
2012-09-19 15:15:01 +00:00
//****************************************************************************
// Base Texture
//****************************************************************************
DiffuseMapFeatHLSL::DiffuseMapFeatHLSL()
: mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl"))
{
addDependency(&mTorqueDep);
}
2012-09-19 15:15:01 +00:00
void DiffuseMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
getOutTexCoord( "texCoord",
"float2",
fd.features[MFT_TexAnim],
meta,
componentList );
output = meta;
}
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
U32 DiffuseMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const
{
return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
}
2012-09-19 15:15:01 +00:00
void DiffuseMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// grab connector texcoord register
2017-05-28 21:51:31 +00:00
Var *inTex = getInTexCoord( "texCoord", "float2", componentList );
2012-09-19 15:15:01 +00:00
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
//determine output target
ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget;
if (fd.features[MFT_isDeferred])
targ = ShaderFeature::RenderTarget1;
2012-09-19 15:15:01 +00:00
// create texture var
Var *diffuseMap = new Var;
2017-05-28 21:51:31 +00:00
diffuseMap->setType( "SamplerState" );
2012-09-19 15:15:01 +00:00
diffuseMap->setName( "diffuseMap" );
diffuseMap->uniform = true;
diffuseMap->sampler = true;
diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
2017-05-28 21:51:31 +00:00
Var* diffuseMapTex = new Var;
diffuseMapTex->setName("diffuseMapTex");
diffuseMapTex->setType("Texture2D");
diffuseMapTex->uniform = true;
diffuseMapTex->texture = true;
diffuseMapTex->constNum = diffuseMap->constNum;
2016-03-20 11:52:11 +00:00
// create sample color
Var *diffColor = new Var;
diffColor->setType("float4");
diffColor->setName("diffuseColor");
LangElement *colorDecl = new DecOp(diffColor);
MultiLine * meta = new MultiLine;
output = meta;
2012-09-19 15:15:01 +00:00
if ( fd.features[MFT_CubeMap] )
{
2017-05-28 21:51:31 +00:00
meta->addStatement(new GenOp(" @ = @.Sample(@, @);\r\n", colorDecl, diffuseMapTex, diffuseMap, inTex));
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ)));
2012-09-19 15:15:01 +00:00
}
else if(fd.features[MFT_DiffuseMapAtlas])
{
// Handle atlased textures
// http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47
Var *atlasedTex = new Var;
atlasedTex->setName("atlasedTexCoord");
atlasedTex->setType("float2");
LangElement *atDecl = new DecOp(atlasedTex);
// Parameters of the texture atlas
2017-05-28 21:51:31 +00:00
Var *atParams = new Var;
2012-09-19 15:15:01 +00:00
atParams->setType("float4");
atParams->setName("diffuseAtlasParams");
atParams->uniform = true;
atParams->constSortPos = cspPotentialPrimitive;
// Parameters of the texture (tile) this object is using in the atlas
2017-05-28 21:51:31 +00:00
Var *tileParams = new Var;
2012-09-19 15:15:01 +00:00
tileParams->setType("float4");
tileParams->setName("diffuseAtlasTileParams");
tileParams->uniform = true;
tileParams->constSortPos = cspPotentialPrimitive;
const bool is_sm3 = (GFX->getPixelShaderVersion() > 2.0f);
if(is_sm3)
{
// Figure out the mip level
meta->addStatement(new GenOp(" float2 _dx = ddx(@ * @.z);\r\n", inTex, atParams));
meta->addStatement(new GenOp(" float2 _dy = ddy(@ * @.z);\r\n", inTex, atParams));
meta->addStatement(new GenOp(" float mipLod = 0.5 * log2(max(dot(_dx, _dx), dot(_dy, _dy)));\r\n"));
meta->addStatement(new GenOp(" mipLod = clamp(mipLod, 0.0, @.w);\r\n", atParams));
// And the size of the mip level
meta->addStatement(new GenOp(" float mipPixSz = pow(2.0, @.w - mipLod);\r\n", atParams));
meta->addStatement(new GenOp(" float2 mipSz = mipPixSz / @.xy;\r\n", atParams));
}
else
{
meta->addStatement(new GenOp(" float2 mipSz = float2(1.0, 1.0);\r\n"));
}
// Tiling mode
// TODO: Select wrap or clamp somehow
if( true ) // Wrap
meta->addStatement(new GenOp(" @ = frac(@);\r\n", atDecl, inTex));
else // Clamp
meta->addStatement(new GenOp(" @ = saturate(@);\r\n", atDecl, inTex));
// Finally scale/offset, and correct for filtering
meta->addStatement(new GenOp(" @ = @ * ((mipSz * @.xy - 1.0) / mipSz) + 0.5 / mipSz + @.xy * @.xy;\r\n",
atlasedTex, atlasedTex, atParams, atParams, tileParams));
// Add a newline
meta->addStatement(new GenOp( "\r\n"));
// For the rest of the feature...
inTex = atlasedTex;
// To dump out UV coords...
//#define DEBUG_ATLASED_UV_COORDS
#ifdef DEBUG_ATLASED_UV_COORDS
if(!fd.features[MFT_DeferredConditioner])
2012-09-19 15:15:01 +00:00
{
meta->addStatement(new GenOp(" @ = float4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams));
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
meta->addStatement(new GenOp(" @; return OUT;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) );
2012-09-19 15:15:01 +00:00
return;
}
#endif
2017-05-28 21:51:31 +00:00
meta->addStatement(new GenOp(" @ = @.SampleLevel(@,@,mipLod);\r\n",
new DecOp(diffColor), diffuseMapTex, diffuseMap, inTex));
2012-09-19 15:15:01 +00:00
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) );
2012-09-19 15:15:01 +00:00
}
else
{
2017-05-28 21:51:31 +00:00
meta->addStatement(new GenOp("@ = @.Sample(@, @);\r\n", colorDecl, diffuseMapTex, diffuseMap, inTex));
2016-03-20 11:52:11 +00:00
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ)));
}
2012-09-19 15:15:01 +00:00
}
ShaderFeature::Resources DiffuseMapFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
res.numTex = 1;
res.numTexReg = 1;
return res;
}
void DiffuseMapFeatHLSL::setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex )
{
GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap );
if ( tex )
{
passData.mSamplerNames[ texIndex ] = "diffuseMap";
2012-09-19 15:15:01 +00:00
passData.mTexSlot[ texIndex++ ].texObject = tex;
}
2012-09-19 15:15:01 +00:00
}
//****************************************************************************
// Overlay Texture
//****************************************************************************
void OverlayTexFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
Var *inTex = getVertTexCoord( "texCoord2" );
AssertFatal( inTex, "OverlayTexFeatHLSL::processVert() - The second UV set was not found!" );
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *outTex = connectComp->getElement( RT_TEXCOORD );
outTex->setName( "outTexCoord2" );
outTex->setStructName( "OUT" );
outTex->setType( "float2" );
if( fd.features[MFT_TexAnim] )
{
inTex->setType( "float4" );
// Find or create the texture matrix.
Var *texMat = (Var*)LangElement::find( "texMat" );
if ( !texMat )
{
texMat = new Var;
texMat->setType( "float4x4" );
texMat->setName( "texMat" );
texMat->uniform = true;
texMat->constSortPos = cspPass;
}
output = new GenOp( " @ = mul(@, @);\r\n", outTex, texMat, inTex );
return;
}
// setup language elements to output incoming tex coords to output
output = new GenOp( " @ = @;\r\n", outTex, inTex );
}
void OverlayTexFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *inTex = connectComp->getElement( RT_TEXCOORD );
inTex->setName( "texCoord2" );
inTex->setStructName( "IN" );
inTex->setType( "float2" );
// create texture var
Var *diffuseMap = new Var;
2017-05-28 21:51:31 +00:00
diffuseMap->setType( "SamplerState" );
2012-09-19 15:15:01 +00:00
diffuseMap->setName( "overlayMap" );
diffuseMap->uniform = true;
diffuseMap->sampler = true;
diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
2017-05-28 21:51:31 +00:00
Var* diffuseMapTex = new Var;
diffuseMapTex->setName("overlayMapTex");
diffuseMapTex->setType("Texture2D");
diffuseMapTex->uniform = true;
diffuseMapTex->texture = true;
diffuseMapTex->constNum = diffuseMap->constNum;
2016-03-20 11:52:11 +00:00
2017-05-28 21:51:31 +00:00
LangElement *statement = new GenOp("@.Sample(@, @)", diffuseMapTex, diffuseMap, inTex);
2016-03-20 11:52:11 +00:00
2012-09-19 15:15:01 +00:00
output = new GenOp( " @;\r\n", assignColor( statement, Material::LerpAlpha ) );
}
ShaderFeature::Resources OverlayTexFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
res.numTex = 1;
res.numTexReg = 1;
return res;
}
void OverlayTexFeatHLSL::setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex )
{
GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap );
if ( tex )
{
passData.mSamplerNames[texIndex] = "overlayMap";
2012-09-19 15:15:01 +00:00
passData.mTexSlot[ texIndex++ ].texObject = tex;
}
2012-09-19 15:15:01 +00:00
}
//****************************************************************************
// Diffuse color
//****************************************************************************
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
U32 DiffuseFeatureHLSL::getOutputTargets(const MaterialFeatureData &fd) const
{
return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
}
2012-09-19 15:15:01 +00:00
void DiffuseFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
Var *diffuseMaterialColor = new Var;
diffuseMaterialColor->setType( "float4" );
diffuseMaterialColor->setName( "diffuseMaterialColor" );
diffuseMaterialColor->uniform = true;
diffuseMaterialColor->constSortPos = cspPotentialPrimitive;
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
MultiLine* meta = new MultiLine;
Var *col = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget;
if (fd.features[MFT_isDeferred])
{
targ = ShaderFeature::RenderTarget1;
col = (Var*)LangElement::find(getOutputTargetVarName(targ));
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
if (!col)
{
// create color var
col = new Var;
col->setType("fragout");
col->setName(getOutputTargetVarName(targ));
col->setStructName("OUT");
2018-03-14 23:44:51 +00:00
meta->addStatement(new GenOp(" @ = float4(1.0,1.0,1.0,1.0);\r\n", col));
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
}
}
Material::BlendOp op;
if (fd.features[MFT_DiffuseMap])
op = Material::Mul;
else
op = Material::None;
meta->addStatement( new GenOp( " @;\r\n", assignColor( diffuseMaterialColor, op, NULL, targ ) ) );
2012-09-19 15:15:01 +00:00
output = meta;
}
//****************************************************************************
// Diffuse vertex color
//****************************************************************************
void DiffuseVertColorFeatureHLSL::processVert( Vector< ShaderComponent* >& componentList,
const MaterialFeatureData& fd )
{
// Create vertex color connector if it doesn't exist.
Var* outColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) );
if( !outColor )
{
// Search for vert color.
Var* inColor = dynamic_cast< Var* >( LangElement::find( "diffuse" ) );
if( !inColor )
{
output = NULL;
return;
}
// Create connector.
ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] );
AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" );
2018-03-13 23:07:58 +00:00
outColor = connectComp->getElement( RT_COLOR );
2012-09-19 15:15:01 +00:00
outColor->setName( "vertColor" );
outColor->setStructName( "OUT" );
outColor->setType( "float4" );
output = new GenOp( " @ = @.bgra;\r\n", outColor, inColor );
2012-09-19 15:15:01 +00:00
}
else
output = NULL; // Nothing we need to do.
}
void DiffuseVertColorFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
Var* vertColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) );
if( !vertColor )
{
ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] );
AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" );
vertColor = connectComp->getElement( RT_COLOR );
vertColor->setName( "vertColor" );
vertColor->setStructName( "IN" );
vertColor->setType( "float4" );
}
MultiLine* meta = new MultiLine;
if (fd.features[MFT_isDeferred])
meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1)));
else
meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul)));
2012-09-19 15:15:01 +00:00
output = meta;
}
//****************************************************************************
// Lightmap
//****************************************************************************
void LightmapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// grab tex register from incoming vert
Var *inTex = getVertTexCoord( "texCoord2" );
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *outTex = connectComp->getElement( RT_TEXCOORD );
outTex->setName( "texCoord2" );
outTex->setStructName( "OUT" );
outTex->setType( "float2" );
// setup language elements to output incoming tex coords to output
output = new GenOp( " @ = @;\r\n", outTex, inTex );
}
void LightmapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *inTex = connectComp->getElement( RT_TEXCOORD );
inTex->setName( "texCoord2" );
inTex->setStructName( "IN" );
inTex->setType( "float2" );
// create texture var
Var *lightMap = new Var;
2017-05-28 21:51:31 +00:00
lightMap->setType( "SamplerState" );
2012-09-19 15:15:01 +00:00
lightMap->setName( "lightMap" );
lightMap->uniform = true;
lightMap->sampler = true;
lightMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
2017-05-28 21:51:31 +00:00
Var *lightMapTex = new Var;
lightMapTex->setName("lightMapTex");
lightMapTex->setType("Texture2D");
lightMapTex->uniform = true;
lightMapTex->texture = true;
lightMapTex->constNum = lightMap->constNum;
2012-09-19 15:15:01 +00:00
2020-09-30 18:51:12 +00:00
// argh, ORMConfigMap should prob use this too
2012-09-19 15:15:01 +00:00
if( fd.features[MFT_NormalMap] )
{
Var *lmColor = new Var;
lmColor->setName( "lmColor" );
lmColor->setType( "float4" );
LangElement *lmColorDecl = new DecOp( lmColor );
2017-05-28 21:51:31 +00:00
output = new GenOp(" @ = @.Sample(@, @);\r\n", lmColorDecl, lightMapTex, lightMap, inTex);
2012-09-19 15:15:01 +00:00
return;
}
// Add realtime lighting, if it is available
LangElement *statement = NULL;
if( fd.features[MFT_RTLighting] )
{
// Advanced lighting is the only dynamic lighting supported right now
Var *inColor = (Var*) LangElement::find( "d_lightcolor" );
if(inColor != NULL)
{
// Find out if RTLighting should be added or substituted
bool bPreProcessedLighting = false;
AdvancedLightBinManager *lightBin;
if ( Sim::findObject( "AL_LightBinMgr", lightBin ) )
bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred();
2012-09-19 15:15:01 +00:00
// Lightmap has already been included in the advanced light bin, so
// no need to do any sampling or anything
2016-03-20 11:52:11 +00:00
if (bPreProcessedLighting)
statement = new GenOp("float4(@, 1.0)", inColor);
2012-09-19 15:15:01 +00:00
else
2016-03-20 11:52:11 +00:00
{
2017-05-28 21:51:31 +00:00
statement = new GenOp("@.Sample(@, @) + float4(@.rgb, 0.0)", lightMapTex, lightMap, inTex, inColor);
2016-03-20 11:52:11 +00:00
}
2012-09-19 15:15:01 +00:00
}
}
// If we still don't have it... then just sample the lightmap.
2016-03-20 11:52:11 +00:00
if (!statement)
{
2017-05-28 21:51:31 +00:00
statement = new GenOp("@.Sample(@, @)", lightMapTex, lightMap, inTex);
2016-03-20 11:52:11 +00:00
}
2012-09-19 15:15:01 +00:00
// Assign to proper render target
MultiLine *meta = new MultiLine;
if( fd.features[MFT_LightbufferMRT] )
{
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
2012-09-19 15:15:01 +00:00
}
else
meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ) );
output = meta;
}
ShaderFeature::Resources LightmapFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
res.numTex = 1;
res.numTexReg = 1;
return res;
}
void LightmapFeatHLSL::setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex )
{
GFXTextureObject *tex = stageDat.getTex( MFT_LightMap );
passData.mSamplerNames[ texIndex ] = "lightMap";
2012-09-19 15:15:01 +00:00
if ( tex )
passData.mTexSlot[ texIndex++ ].texObject = tex;
else
passData.mTexType[ texIndex++ ] = Material::Lightmap;
}
U32 LightmapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
{
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget;
2012-09-19 15:15:01 +00:00
}
//****************************************************************************
// Tonemap
//****************************************************************************
void TonemapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Grab the connector
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
// Set up the second set of texCoords
Var *inTex2 = getVertTexCoord( "texCoord2" );
if ( inTex2 )
{
Var *outTex2 = connectComp->getElement( RT_TEXCOORD );
outTex2->setName( "texCoord2" );
outTex2->setStructName( "OUT" );
outTex2->setType( "float2" );
output = new GenOp( " @ = @;\r\n", outTex2, inTex2 );
}
}
void TonemapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Grab connector
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *inTex2 = connectComp->getElement( RT_TEXCOORD );
inTex2->setName( "texCoord2" );
inTex2->setStructName( "IN" );
inTex2->setType( "float2" );
// create texture var
Var *toneMap = new Var;
2017-05-28 21:51:31 +00:00
toneMap->setType( "SamplerState" );
2012-09-19 15:15:01 +00:00
toneMap->setName( "toneMap" );
toneMap->uniform = true;
toneMap->sampler = true;
toneMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
2017-05-28 21:51:31 +00:00
Var *toneMapTex = new Var;
toneMapTex->setName("toneMapTex");
toneMapTex->setType("Texture2D");
toneMapTex->uniform = true;
toneMapTex->texture = true;
toneMapTex->constNum = toneMap->constNum;
2016-03-20 11:52:11 +00:00
2012-09-19 15:15:01 +00:00
MultiLine * meta = new MultiLine;
// First get the toneMap color
Var *toneMapColor = new Var;
toneMapColor->setType( "float4" );
toneMapColor->setName( "toneMapColor" );
LangElement *toneMapColorDecl = new DecOp( toneMapColor );
2017-05-28 21:51:31 +00:00
meta->addStatement(new GenOp(" @ = @.Sample(@, @);\r\n", toneMapColorDecl, toneMapTex, toneMap, inTex2));
2012-09-19 15:15:01 +00:00
// We do a different calculation if there is a diffuse map or not
Material::BlendOp blendOp = Material::Mul;
if ( fd.features[MFT_DiffuseMap] )
{
// Reverse the tonemap
meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", toneMapColor, toneMapColor ) );
// Re-tonemap with the current color factored in
blendOp = Material::ToneMap;
}
// Find out if RTLighting should be added
bool bPreProcessedLighting = false;
AdvancedLightBinManager *lightBin;
if ( Sim::findObject( "AL_LightBinMgr", lightBin ) )
bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred();
2012-09-19 15:15:01 +00:00
// Add in the realtime lighting contribution
if ( fd.features[MFT_RTLighting] )
{
// Right now, only Advanced Lighting is supported
Var *inColor = (Var*) LangElement::find( "d_lightcolor" );
if(inColor != NULL)
{
// Assign value in d_lightcolor to toneMapColor if it exists. This is
// the dynamic light buffer, and it already has the tonemap included
if(bPreProcessedLighting)
meta->addStatement( new GenOp( " @.rgb = @;\r\n", toneMapColor, inColor ) );
else
meta->addStatement( new GenOp( " @.rgb += @.rgb;\r\n", toneMapColor, inColor ) );
}
}
// Assign to proper render target
if( fd.features[MFT_LightbufferMRT] )
{
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
2012-09-19 15:15:01 +00:00
}
else
meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, blendOp ) ) );
output = meta;
}
ShaderFeature::Resources TonemapFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
res.numTex = 1;
res.numTexReg = 1;
return res;
}
void TonemapFeatHLSL::setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex )
{
GFXTextureObject *tex = stageDat.getTex( MFT_ToneMap );
if ( tex )
{
passData.mTexType[ texIndex ] = Material::ToneMapTex;
passData.mSamplerNames[ texIndex ] = "toneMap";
2012-09-19 15:15:01 +00:00
passData.mTexSlot[ texIndex++ ].texObject = tex;
}
}
U32 TonemapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
{
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget;
2012-09-19 15:15:01 +00:00
}
//****************************************************************************
// pureLIGHT Lighting
//****************************************************************************
void VertLitHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// If we have a lightMap or toneMap then our lighting will be
// handled by the MFT_LightMap or MFT_ToneNamp feature instead
if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] )
{
output = NULL;
return;
}
// Create vertex color connector if it doesn't exist.
Var* outColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) );
if( !outColor )
{
// Search for vert color
Var *inColor = (Var*) LangElement::find( "diffuse" );
// If there isn't a vertex color then we can't do anything
if( !inColor )
{
output = NULL;
return;
}
// Grab the connector color
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2018-03-13 23:07:58 +00:00
outColor = connectComp->getElement( RT_COLOR );
2012-09-19 15:15:01 +00:00
outColor->setName( "vertColor" );
outColor->setStructName( "OUT" );
outColor->setType( "float4" );
output = new GenOp( " @ = @;\r\n", outColor, inColor );
}
else
output = NULL; // Nothing we need to do.
}
void VertLitHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// If we have a lightMap or toneMap then our lighting will be
// handled by the MFT_LightMap or MFT_ToneNamp feature instead
if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] )
{
output = NULL;
return;
}
// Grab the connector color register
Var* vertColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) );
if( !vertColor )
{
ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] );
AssertFatal( connectComp, "VertLitGLSL::processVert - C_CONNECTOR is not a ShaderConnector" );
vertColor = connectComp->getElement( RT_COLOR );
vertColor->setName( "vertColor" );
vertColor->setStructName( "IN" );
vertColor->setType( "float4" );
}
MultiLine * meta = new MultiLine;
// Defaults (no diffuse map)
Material::BlendOp blendOp = Material::Mul;
LangElement *outColor = vertColor;
// We do a different calculation if there is a diffuse map or not
if ( fd.features[MFT_DiffuseMap] || fd.features[MFT_VertLitTone] )
{
Var * finalVertColor = new Var;
finalVertColor->setName( "finalVertColor" );
finalVertColor->setType( "float4" );
LangElement *finalVertColorDecl = new DecOp( finalVertColor );
// Reverse the tonemap
meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", finalVertColorDecl, vertColor ) );
// Set the blend op to tonemap
blendOp = Material::ToneMap;
outColor = finalVertColor;
}
// Add in the realtime lighting contribution, if applicable
if ( fd.features[MFT_RTLighting] )
{
Var *rtLightingColor = (Var*) LangElement::find( "d_lightcolor" );
if(rtLightingColor != NULL)
{
bool bPreProcessedLighting = false;
AdvancedLightBinManager *lightBin;
if ( Sim::findObject( "AL_LightBinMgr", lightBin ) )
bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred();
2012-09-19 15:15:01 +00:00
// Assign value in d_lightcolor to toneMapColor if it exists. This is
// the dynamic light buffer, and it already has the baked-vertex-color
// included in it
if(bPreProcessedLighting)
outColor = new GenOp( "float4(@.rgb, 1.0)", rtLightingColor );
else
outColor = new GenOp( "float4(@.rgb + @.rgb, 1.0)", rtLightingColor, outColor );
}
}
// Output the color
if ( fd.features[MFT_LightbufferMRT] )
{
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
2012-09-19 15:15:01 +00:00
}
else
meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, blendOp ) ) );
output = meta;
}
U32 VertLitHLSL::getOutputTargets( const MaterialFeatureData &fd ) const
{
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget;
2012-09-19 15:15:01 +00:00
}
//****************************************************************************
// Detail map
//****************************************************************************
void DetailFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
addOutDetailTexCoord( componentList,
meta,
fd.features[MFT_TexAnim], fd.features[MFT_Foliage] );
2012-09-19 15:15:01 +00:00
output = meta;
}
void DetailFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Get the detail texture coord.
2017-05-28 21:51:31 +00:00
Var *inTex = getInTexCoord( "detCoord", "float2", componentList );
2012-09-19 15:15:01 +00:00
// create texture var
Var *detailMap = new Var;
2017-05-28 21:51:31 +00:00
detailMap->setType( "SamplerState" );
2012-09-19 15:15:01 +00:00
detailMap->setName( "detailMap" );
detailMap->uniform = true;
detailMap->sampler = true;
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
2017-05-28 21:51:31 +00:00
Var* detailMapTex = new Var;
detailMapTex->setName("detailMapTex");
detailMapTex->setType("Texture2D");
detailMapTex->uniform = true;
detailMapTex->texture = true;
detailMapTex->constNum = detailMap->constNum;
2016-03-20 11:52:11 +00:00
2012-09-19 15:15:01 +00:00
// We're doing the standard greyscale detail map
// technique which can darken and lighten the
// diffuse texture.
// TODO: We could add a feature to toggle between this
// and a simple multiplication with the detail map.
2017-05-28 21:51:31 +00:00
LangElement *statement = new GenOp("( @.Sample(@, @) * 2.0 ) - 1.0", detailMapTex, detailMap, inTex);
2016-03-20 11:52:11 +00:00
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
if ( fd.features[MFT_isDeferred])
output = new GenOp( " @;\r\n", assignColor( statement, Material::Add, NULL, ShaderFeature::RenderTarget1 ) );
else
output = new GenOp( " @;\r\n", assignColor( statement, Material::Add ) );
2012-09-19 15:15:01 +00:00
}
ShaderFeature::Resources DetailFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
res.numTex = 1;
res.numTexReg = 1;
return res;
}
void DetailFeatHLSL::setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex )
{
GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap );
if ( tex )
{
passData.mSamplerNames[texIndex] = "detailMap";
2012-09-19 15:15:01 +00:00
passData.mTexSlot[ texIndex++ ].texObject = tex;
}
2012-09-19 15:15:01 +00:00
}
//****************************************************************************
// Vertex position
//****************************************************************************
void VertPositionHLSL::determineFeature( Material *material,
const GFXVertexFormat *vertexFormat,
U32 stageNum,
const FeatureType &type,
const FeatureSet &features,
MaterialFeatureData *outFeatureData )
{
// This feature is always on!
outFeatureData->features.addFeature( type );
}
void VertPositionHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// First check for an input position from a previous feature
// then look for the default vertex position.
Var *inPosition = (Var*)LangElement::find( "inPosition" );
if ( !inPosition )
inPosition = (Var*)LangElement::find( "position" );
// grab connector position
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
2017-05-28 21:51:31 +00:00
Var *outPosition = connectComp->getElement(RT_SVPOSITION);
2016-03-20 11:52:11 +00:00
2012-09-19 15:15:01 +00:00
outPosition->setName( "hpos" );
outPosition->setStructName( "OUT" );
MultiLine *meta = new MultiLine;
Var *modelview = getModelView( componentList, fd.features[MFT_UseInstancing], meta );
meta->addStatement( new GenOp( " @ = mul(@, float4(@.xyz,1));\r\n",
outPosition, modelview, inPosition ) );
if (fd.materialFeatures[MFT_isBackground])
{
meta->addStatement(new GenOp(" @ = @.xyww;\r\n", outPosition, outPosition));
}
2012-09-19 15:15:01 +00:00
output = meta;
}
2016-03-20 11:52:11 +00:00
void VertPositionHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd)
{
2017-05-28 21:51:31 +00:00
// grab connector position
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
Var *outPosition = connectComp->getElement(RT_SVPOSITION);
outPosition->setName("vpos");
outPosition->setStructName("IN");
2016-03-20 11:52:11 +00:00
}
2012-09-19 15:15:01 +00:00
//****************************************************************************
// Reflect Cubemap
//****************************************************************************
void ReflectCubeFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// search for vert normal
Var *inNormal = (Var*) LangElement::find( "normal" );
if ( !inNormal )
return;
MultiLine * meta = new MultiLine;
// If a base or bump tex is present in the material, but not in the
// current pass - we need to add one to the current pass to use
// its alpha channel as a gloss map. Here we just need the tex coords.
if( !fd.features[MFT_DiffuseMap] &&
!fd.features[MFT_NormalMap] )
{
if( fd.materialFeatures[MFT_DiffuseMap] ||
fd.materialFeatures[MFT_NormalMap] )
{
// find incoming texture var
Var *inTex = getVertTexCoord( "texCoord" );
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *outTex = connectComp->getElement( RT_TEXCOORD );
outTex->setName( "texCoord" );
outTex->setStructName( "OUT" );
outTex->setType( "float2" );
// setup language elements to output incoming tex coords to output
meta->addStatement( new GenOp( " @ = @;\r\n", outTex, inTex ) );
}
}
// create cubeTrans
bool useInstancing = fd.features[MFT_UseInstancing];
Var *cubeTrans = getObjTrans( componentList, useInstancing, meta );
// cube vert position
Var * cubeVertPos = new Var;
cubeVertPos->setName( "cubeVertPos" );
cubeVertPos->setType( "float3" );
LangElement *cubeVertPosDecl = new DecOp( cubeVertPos );
2014-12-15 17:28:17 +00:00
meta->addStatement( new GenOp( " @ = mul(@, float4(@,1)).xyz;\r\n",
cubeVertPosDecl, cubeTrans, LangElement::find( "position" ) ) );
// cube normal
Var * cubeNormal = new Var;
cubeNormal->setName( "cubeNormal" );
cubeNormal->setType( "float3" );
LangElement *cubeNormDecl = new DecOp( cubeNormal );
2016-03-20 11:52:11 +00:00
meta->addStatement(new GenOp(" @ = ( mul( (@), float4(@, 0) ) ).xyz;\r\n",
cubeNormDecl, cubeTrans, inNormal));
meta->addStatement(new GenOp(" @ = bool(length(@)) ? normalize(@) : @;\r\n",
cubeNormal, cubeNormal, cubeNormal, cubeNormal));
// grab the eye position
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
if ( !eyePos )
{
eyePos = new Var( "eyePosWorld", "float3" );
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
// eye to vert
Var * eyeToVert = new Var;
eyeToVert->setName( "eyeToVert" );
eyeToVert->setType( "float3" );
LangElement *e2vDecl = new DecOp( eyeToVert );
2014-12-15 17:28:17 +00:00
meta->addStatement( new GenOp( " @ = @ - @;\r\n",
e2vDecl, cubeVertPos, eyePos ) );
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *reflectVec = connectComp->getElement( RT_TEXCOORD );
reflectVec->setName( "reflectVec" );
reflectVec->setStructName( "OUT" );
reflectVec->setType( "float3" );
meta->addStatement( new GenOp( " @ = reflect(@, @);\r\n", reflectVec, eyeToVert, cubeNormal ) );
output = meta;
2012-09-19 15:15:01 +00:00
}
void ReflectCubeFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine * meta = new MultiLine;
Var *glossColor = NULL;
// If a base or bump tex is present in the material, but not in the
// current pass - we need to add one to the current pass to use
// its alpha channel as a gloss map.
if( !fd.features[MFT_DiffuseMap] &&
2016-03-20 11:52:11 +00:00
!fd.features[MFT_NormalMap])
2012-09-19 15:15:01 +00:00
{
if( fd.materialFeatures[MFT_DiffuseMap] ||
2016-03-20 11:52:11 +00:00
fd.materialFeatures[MFT_NormalMap])
2012-09-19 15:15:01 +00:00
{
// grab connector texcoord register
2017-05-28 21:51:31 +00:00
Var *inTex = getInTexCoord("texCoord", "float2", componentList);
2012-09-19 15:15:01 +00:00
// create texture var
Var *newMap = new Var;
2017-05-28 21:51:31 +00:00
newMap->setType( "SamplerState" );
2012-09-19 15:15:01 +00:00
newMap->setName( "glossMap" );
newMap->uniform = true;
newMap->sampler = true;
newMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
2016-03-20 11:52:11 +00:00
2017-05-28 21:51:31 +00:00
Var* glowMapTex = new Var;
glowMapTex->setName("glowMapTex");
glowMapTex->setType("Texture2D");
glowMapTex->uniform = true;
glowMapTex->texture = true;
glowMapTex->constNum = newMap->constNum;
2012-09-19 15:15:01 +00:00
// create sample color
Var *color = new Var;
color->setType( "float4" );
color->setName( "diffuseColor" );
LangElement *colorDecl = new DecOp( color );
glossColor = color;
2017-05-28 21:51:31 +00:00
meta->addStatement(new GenOp(" @ = @.Sample( @, @ );\r\n", colorDecl, glowMapTex, newMap, inTex));
2012-09-19 15:15:01 +00:00
}
}
if (!glossColor)
2012-09-19 15:15:01 +00:00
{
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
if (fd.features[MFT_isDeferred])
glossColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1));
if (!glossColor)
glossColor = (Var*)LangElement::find("diffuseColor");
if (!glossColor)
glossColor = (Var*)LangElement::find("bumpNormal");
2012-09-19 15:15:01 +00:00
}
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *reflectVec = connectComp->getElement( RT_TEXCOORD );
reflectVec->setName( "reflectVec" );
reflectVec->setStructName( "IN" );
reflectVec->setType( "float3" );
// create cubemap var
Var *cubeMap = new Var;
2017-05-28 21:51:31 +00:00
cubeMap->setType( "SamplerState" );
2012-09-19 15:15:01 +00:00
cubeMap->setName( "cubeMap" );
cubeMap->uniform = true;
cubeMap->sampler = true;
cubeMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
2017-05-28 21:51:31 +00:00
Var* cubeMapTex = new Var;
cubeMapTex->setName("cubeMapTex");
cubeMapTex->setType("TextureCube"); // cubeMapTex->setType("TextureCube");
cubeMapTex->uniform = true;
cubeMapTex->texture = true;
cubeMapTex->constNum = cubeMap->constNum;
2016-03-20 11:52:11 +00:00
Var *cubeMips = new Var;
cubeMips->setType("float");
cubeMips->setName("cubeMips");
cubeMips->uniform = true;
cubeMips->constSortPos = cspPotentialPrimitive;
2012-09-19 15:15:01 +00:00
// TODO: Restore the lighting attenuation here!
Var *attn = NULL;
//if ( fd.materialFeatures[MFT_DynamicLight] )
//attn = (Var*)LangElement::find("attn");
//else
if ( fd.materialFeatures[MFT_RTLighting] )
attn =(Var*)LangElement::find("d_NL_Att");
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
LangElement *texCube = NULL;
Var* matinfo = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
2020-09-30 18:51:12 +00:00
Var *roughness = (Var*)LangElement::find("roughness");
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
2020-09-30 18:51:12 +00:00
if (roughness) //try to grab roughness directly
{
2020-09-30 18:51:12 +00:00
texCube = new GenOp("@.SampleLevel( @, float3(@).rgb, min((1.0 - @)*@ + 1.0, @))", cubeMapTex, cubeMap, reflectVec, roughness, cubeMips, cubeMips);
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
}
else if (glossColor)//failing that, try and find color data
2016-03-20 11:52:11 +00:00
{
texCube = new GenOp("@.SampleLevel( @, float3(@).rgb, min((1.0 - @.b)*@ + 1.0, @))", cubeMapTex, cubeMap, reflectVec, glossColor, cubeMips, cubeMips);
}
else //failing *that*, just draw the cubemap
{
texCube = new GenOp("@.Sample( @, @ )", cubeMapTex, cubeMap, reflectVec);
2016-03-20 11:52:11 +00:00
}
2012-09-19 15:15:01 +00:00
LangElement *lerpVal = NULL;
Material::BlendOp blendOp = Material::LerpAlpha;
// Note that the lerpVal needs to be a float4 so that
// it will work with the LerpAlpha blend.
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
if (matinfo)
{
if (attn)
lerpVal = new GenOp("@ * saturate( @ )", matinfo, attn);
else
lerpVal = new GenOp("@", matinfo);
}
else if ( glossColor )
2012-09-19 15:15:01 +00:00
{
if ( attn )
lerpVal = new GenOp( "@ * saturate( @ )", glossColor, attn );
else
lerpVal = glossColor;
}
else
{
if ( attn )
lerpVal = new GenOp( "saturate( @ ).xxxx", attn );
else
blendOp = Material::Mul;
}
Var* targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget3));
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
if (fd.features[MFT_isDeferred])
{
//metalness: black(0) = color, white(1) = reflection
if (fd.features[MFT_ToneMap])
meta->addStatement(new GenOp(" @ *= @;\r\n", targ, texCube));
else
meta->addStatement(new GenOp(" @ = @;\r\n", targ, texCube));
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
}
else
{
meta->addStatement(new GenOp(" //forward lit cubemapping\r\n"));
targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
Var *metalness = (Var*)LangElement::find("metalness");
if (metalness)
{
Var *dColor = new Var("dColor", "float3");
Var *reflectColor = new Var("reflectColor", "float3");
meta->addStatement(new GenOp(" @ = @.rgb - (@.rgb * @);\r\n", new DecOp(dColor), targ, targ, metalness));
meta->addStatement(new GenOp(" @ = @.rgb*(@).rgb*@;\r\n", new DecOp(reflectColor), targ, texCube, metalness));
meta->addStatement(new GenOp(" @.rgb = @+@;\r\n", targ, dColor, reflectColor));
}
else if (lerpVal)
meta->addStatement(new GenOp(" @ *= float4(@.rgb*@.a, @.a);\r\n", targ, texCube, lerpVal, targ));
else
meta->addStatement(new GenOp(" @.rgb *= @.rgb;\r\n", targ, texCube));
}
2012-09-19 15:15:01 +00:00
output = meta;
}
ShaderFeature::Resources ReflectCubeFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
if( fd.features[MFT_DiffuseMap] ||
fd.features[MFT_NormalMap] )
{
res.numTex = 1;
res.numTexReg = 1;
}
else
{
res.numTex = 2;
res.numTexReg = 2;
}
return res;
}
void ReflectCubeFeatHLSL::setTexData( Material::StageData &stageDat,
const MaterialFeatureData &stageFeatures,
RenderPassData &passData,
U32 &texIndex )
{
// set up a gloss map if one is not present in the current pass
// but is present in the current material stage
if( !passData.mFeatureData.features[MFT_DiffuseMap] &&
!passData.mFeatureData.features[MFT_NormalMap] )
{
GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap );
if ( tex && stageFeatures.features[MFT_DiffuseMap] )
{
passData.mSamplerNames[ texIndex ] = "diffuseMap";
2012-09-19 15:15:01 +00:00
passData.mTexSlot[ texIndex++ ].texObject = tex;
}
2012-09-19 15:15:01 +00:00
else
{
tex = stageDat.getTex( MFT_NormalMap );
if ( tex && stageFeatures.features[ MFT_NormalMap ] )
{
passData.mSamplerNames[ texIndex ] = "bumpMap";
2012-09-19 15:15:01 +00:00
passData.mTexSlot[ texIndex++ ].texObject = tex;
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
}
2012-09-19 15:15:01 +00:00
}
}
2016-03-20 11:52:11 +00:00
2012-09-19 15:15:01 +00:00
if( stageDat.getCubemap() )
{
passData.mCubeMap = stageDat.getCubemap();
passData.mSamplerNames[texIndex] = "cubeMap";
2012-09-19 15:15:01 +00:00
passData.mTexType[texIndex++] = Material::Cube;
}
else
{
if( stageFeatures.features[MFT_CubeMap] )
{
// assuming here that it is a scenegraph cubemap
passData.mSamplerNames[texIndex] = "cubeMap";
2012-09-19 15:15:01 +00:00
passData.mTexType[texIndex++] = Material::SGCube;
}
}
}
//****************************************************************************
// RTLighting
//****************************************************************************
RTLightingFeatHLSL::RTLightingFeatHLSL()
: mDep(ShaderGen::smCommonShaderPath + String("/lighting.hlsl" ))
2012-09-19 15:15:01 +00:00
{
addDependency( &mDep );
}
void RTLightingFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
// Special case for lighting imposters. We dont have a vert normal and may not
// have a normal map. Generate and pass the normal data the pixel shader needs.
if ( fd.features[MFT_ImposterVert] )
{
2012-09-19 15:15:01 +00:00
if ( !fd.features[MFT_NormalMap] )
{
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
if ( !eyePos )
{
eyePos = new Var( "eyePosWorld", "float3" );
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
//Temporarily disabled while we figure out how to better handle normals without a normal map
/*Var *inPosition = (Var*)LangElement::find( "position" );
2012-09-19 15:15:01 +00:00
Var *outNormal = connectComp->getElement( RT_TEXCOORD );
outNormal->setName( "wsNormal" );
outNormal->setStructName( "OUT" );
outNormal->setType( "float3" );
// Transform the normal to world space.
meta->addStatement( new GenOp( " @ = normalize( @ - @.xyz );\r\n", outNormal, eyePos, inPosition ) );*/
2012-09-19 15:15:01 +00:00
}
addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
output = meta;
return;
}
addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
getOutWorldToTangent(componentList, meta, fd);
output = meta;
2012-09-19 15:15:01 +00:00
// Find the incoming vertex normal.
Var *inNormal = (Var*)LangElement::find( "normal" );
if ( !inNormal ||
fd.features[MFT_LightMap] ||
fd.features[MFT_ToneMap] ||
fd.features[MFT_VertLit] )
return;
// If there isn't a normal map then we need to pass
// the world space normal to the pixel shader ourselves.
if ( !fd.features[MFT_NormalMap] )
2012-09-19 15:15:01 +00:00
{
Var *outNormal = connectComp->getElement( RT_TEXCOORD );
outNormal->setName( "wsNormal" );
outNormal->setStructName( "OUT" );
outNormal->setType( "float3" );
// Get the transform to world space.
Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta );
// Transform the normal to world space.
meta->addStatement( new GenOp( " @ = mul( @, float4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) );
}
2012-09-19 15:15:01 +00:00
}
void RTLightingFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Skip out on realtime lighting if we don't have a normal
// or we're doing some sort of baked lighting.
//
// TODO: We can totally detect for this in the material
// feature setup... we should move it out of here!
//
if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit] )
return;
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
MultiLine *meta = new MultiLine;
// Now the wsPosition and wsView.
Var *wsPosition = getInWsPosition( componentList );
Var* worldToTangent = getInWorldToTangent(componentList);
Var* wsNormal = getInWorldNormal(componentList);
2012-09-19 15:15:01 +00:00
Var *wsView = getWsView( wsPosition, meta );
2012-09-19 15:15:01 +00:00
// Look for a light mask generated from a previous
// feature (this is done for BL terrain lightmaps).
LangElement *lightMask = LangElement::find( "lightMask" );
if ( !lightMask )
lightMask = new GenOp( "float4( 1, 1, 1, 1 )" );
// Get all the light constants.
Var *inLightPos = new Var( "inLightPos", "float4" );
inLightPos->uniform = true;
inLightPos->arraySize = 4;
2012-09-19 15:15:01 +00:00
inLightPos->constSortPos = cspPotentialPrimitive;
Var * inLightConfigData = new Var( "inLightConfigData", "float4" );
inLightConfigData->uniform = true;
inLightConfigData->arraySize = 4;
inLightConfigData->constSortPos = cspPotentialPrimitive;
2012-09-19 15:15:01 +00:00
Var *inLightColor = new Var( "inLightColor", "float4" );
inLightColor->uniform = true;
inLightColor->arraySize = 4;
inLightColor->constSortPos = cspPotentialPrimitive;
Var *inLightSpotDir = new Var( "inLightSpotDir", "float4" );
inLightSpotDir->uniform = true;
inLightSpotDir->arraySize = 4;
2012-09-19 15:15:01 +00:00
inLightSpotDir->constSortPos = cspPotentialPrimitive;
Var * lightSpotParams = new Var( "inlightSpotParams", "float2" );
lightSpotParams->uniform = true;
lightSpotParams->arraySize = 4;
lightSpotParams->constSortPos = cspPotentialPrimitive;
2012-09-19 15:15:01 +00:00
Var* hasVectorLight = new Var("hasVectorLight", "int");
hasVectorLight->uniform = true;
hasVectorLight->constSortPos = cspPotentialPrimitive;
Var* vectorLightDirection = new Var("vectorLightDirection", "float4");
vectorLightDirection->uniform = true;
vectorLightDirection->constSortPos = cspPotentialPrimitive;
Var* vectorLightColor = new Var("vectorLightColor", "float4");
vectorLightColor->uniform = true;
vectorLightColor->constSortPos = cspPotentialPrimitive;
Var* vectorLightBrightness = new Var("vectorLightBrightness", "float");
vectorLightBrightness->uniform = true;
vectorLightBrightness->constSortPos = cspPotentialPrimitive;
Var* surface = getSurface(componentList, meta, fd);
if (!surface)
{
Con::errorf("ShaderGen::RTLightingFeatHLSL() - failed to generate surface!");
return;
}
2020-09-30 18:51:12 +00:00
Var *roughness = (Var*)LangElement::find("roughness");
2012-09-19 15:15:01 +00:00
Var *metalness = (Var*)LangElement::find("metalness");
2012-09-19 15:15:01 +00:00
Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
2012-09-19 15:15:01 +00:00
Var *ambient = new Var( "ambient", "float4" );
ambient->uniform = true;
ambient->constSortPos = cspPass;
2019-07-03 00:22:55 +00:00
Var* lighting = new Var("lighting", "float4");
meta->addStatement(new GenOp(" @ = compute4Lights( @, @, @, @,\r\n"
" @, @, @, @, @, @, @);\r\n",
new DecOp(lighting), surface, lightMask, inLightPos, inLightConfigData, inLightColor, inLightSpotDir, lightSpotParams,
hasVectorLight, vectorLightDirection, vectorLightColor, vectorLightBrightness));
meta->addStatement(new GenOp(" @.rgb += @.rgb;\r\n", curColor, lighting));
2012-09-19 15:15:01 +00:00
output = meta;
}
ShaderFeature::Resources RTLightingFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
// These features disable realtime lighting.
if ( !fd.features[MFT_LightMap] &&
!fd.features[MFT_ToneMap] &&
!fd.features[MFT_VertLit] )
{
// If enabled we pass the position.
res.numTexReg = 1;
// If there isn't a bump map then we pass the
// world space normal as well.
if ( !fd.features[MFT_NormalMap] )
res.numTexReg++;
}
return res;
}
//****************************************************************************
// Fog
//****************************************************************************
FogFeatHLSL::FogFeatHLSL()
: mFogDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" ))
2012-09-19 15:15:01 +00:00
{
addDependency( &mFogDep );
}
void FogFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
const bool vertexFog = Con::getBoolVariable( "$useVertexFog", false );
if ( vertexFog || GFX->getPixelShaderVersion() < 3.0 )
{
// Grab the eye position.
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
if ( !eyePos )
{
eyePos = new Var( "eyePosWorld", "float3" );
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
Var *fogData = new Var( "fogData", "float3" );
fogData->uniform = true;
fogData->constSortPos = cspPass;
Var *wsPosition = new Var( "fogPos", "float3" );
getWsPosition( componentList,
fd.features[MFT_UseInstancing],
meta,
new DecOp( wsPosition ) );
// We pass the fog amount to the pixel shader.
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *fogAmount = connectComp->getElement( RT_TEXCOORD );
fogAmount->setName( "fogAmount" );
fogAmount->setStructName( "OUT" );
fogAmount->setType( "float" );
meta->addStatement( new GenOp( " @ = saturate( computeSceneFog( @, @, @.r, @.g, @.b ) );\r\n",
fogAmount, eyePos, wsPosition, fogData, fogData, fogData ) );
}
else
{
// We fog in world space... make sure the world space
// position is passed to the pixel shader. This is
// often already passed for lighting, so it takes up
// no extra output registers.
addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
}
output = meta;
}
void FogFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
Var *fogColor = new Var;
fogColor->setType( "float4" );
fogColor->setName( "fogColor" );
fogColor->uniform = true;
fogColor->constSortPos = cspPass;
// Get the out color.
Var *color = (Var*) LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
if (fd.features[MFT_isDeferred])
color = (Var *)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1));
2012-09-19 15:15:01 +00:00
if ( !color )
{
color = new Var;
color->setType( "fragout" );
color->setName( "col" );
color->setStructName( "OUT" );
}
Var *fogAmount;
const bool vertexFog = Con::getBoolVariable( "$useVertexFog", false );
if ( vertexFog || GFX->getPixelShaderVersion() < 3.0 )
{
// Per-vertex.... just get the fog amount.
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
fogAmount = connectComp->getElement( RT_TEXCOORD );
fogAmount->setName( "fogAmount" );
fogAmount->setStructName( "IN" );
fogAmount->setType( "float" );
}
else
{
Var *wsPosition = getInWsPosition( componentList );
// grab the eye position
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
if ( !eyePos )
{
eyePos = new Var( "eyePosWorld", "float3" );
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
Var *fogData = new Var( "fogData", "float3" );
fogData->uniform = true;
fogData->constSortPos = cspPass;
/// Get the fog amount.
fogAmount = new Var( "fogAmount", "float" );
meta->addStatement( new GenOp( " @ = saturate( computeSceneFog( @, @, @.r, @.g, @.b ) );\r\n",
new DecOp( fogAmount ), eyePos, wsPosition, fogData, fogData, fogData ) );
}
// Lerp between the fog color and diffuse color.
LangElement *fogLerp = new GenOp( "lerp( @.rgb, @.rgb, @ )", fogColor, color, fogAmount );
meta->addStatement( new GenOp( " @.rgb = @;\r\n", color, fogLerp ) );
output = meta;
}
ShaderFeature::Resources FogFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
res.numTexReg = 1;
return res;
}
//****************************************************************************
// Visibility
//****************************************************************************
VisibilityFeatHLSL::VisibilityFeatHLSL()
: mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" ))
2012-09-19 15:15:01 +00:00
{
addDependency( &mTorqueDep );
}
void VisibilityFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
output = meta;
if ( fd.features[ MFT_UseInstancing ] )
{
// We pass the visibility to the pixel shader via
// another output register.
//
// TODO: We should see if we can share this register
// with some other common instanced data.
//
ShaderConnector *conn = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *outVisibility = conn->getElement( RT_TEXCOORD );
outVisibility->setStructName( "OUT" );
outVisibility->setName( "visibility" );
outVisibility->setType( "float" );
ShaderConnector *vertStruct = dynamic_cast<ShaderConnector *>( componentList[C_VERT_STRUCT] );
Var *instVisibility = vertStruct->getElement( RT_TEXCOORD, 1 );
instVisibility->setStructName( "IN" );
instVisibility->setName( "inst_visibility" );
instVisibility->setType( "float" );
mInstancingFormat->addElement( "visibility", GFXDeclType_Float, instVisibility->constNum );
meta->addStatement( new GenOp( " @ = @; // Instancing!\r\n", outVisibility, instVisibility ) );
}
if ( fd.features[ MFT_IsTranslucent ] )
return;
addOutVpos( meta, componentList );
}
void VisibilityFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Get the visibility constant.
Var *visibility = NULL;
if ( fd.features[ MFT_UseInstancing ] )
2017-05-28 21:51:31 +00:00
visibility = getInTexCoord( "visibility", "float", componentList );
2012-09-19 15:15:01 +00:00
else
{
visibility = (Var*)LangElement::find( "visibility" );
if ( !visibility )
{
visibility = new Var();
visibility->setType( "float" );
visibility->setName( "visibility" );
visibility->uniform = true;
visibility->constSortPos = cspPotentialPrimitive;
}
}
MultiLine *meta = new MultiLine;
output = meta;
// Translucent objects do a simple alpha fade.
if ( fd.features[ MFT_IsTranslucent ] )
{
Var *color = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
2012-09-19 15:15:01 +00:00
meta->addStatement( new GenOp( " @.a *= @;\r\n", color, visibility ) );
return;
}
// Everything else does a fizzle.
Var *vPos = getInVpos( meta, componentList );
2016-03-20 11:52:11 +00:00
// vpos is a float4 in d3d11
meta->addStatement( new GenOp( " fizzle( @.xy, @ );\r\n", vPos, visibility ) );
2012-09-19 15:15:01 +00:00
}
ShaderFeature::Resources VisibilityFeatHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
// TODO: Fix for instancing.
if ( !fd.features[ MFT_IsTranslucent ] )
res.numTexReg = 1;
return res;
}
//****************************************************************************
// AlphaTest
//****************************************************************************
void AlphaTestHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// If we're below SM3 and don't have a depth output
// feature then don't waste an instruction here.
if (( GFX->getPixelShaderVersion() < 3.0 &&
2012-09-19 15:15:01 +00:00
!fd.features[ MFT_EyeSpaceDepthOut ] &&
!fd.features[ MFT_DepthOut ] ) ||
fd.features[MFT_IsTranslucent])
2012-09-19 15:15:01 +00:00
{
output = NULL;
return;
}
// If we don't have a color var then we cannot do an alpha test.
Var *color = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1));
engine: defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout) script: removes dead material features (ie: those that never functioned to begin with) shader: bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly) purpose: _A)_ Small primer on how material features function: When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features. Relevant execution of this is as follows: DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance) class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition { getName -embeded in the proceedural shader as a remline both up top and before actual code insertions processPix - pixel shader codeline insertions getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets) getResources - associated with the Resources struct, closely aligned with the hardware regestry getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting) setTexData - ??? processVert - vertex shader codeline insertions }; _B)_ The resultant Gbuffer layout defined by the previous commit therefore is as follows: defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting) color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency) color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains: red channel comprising material flags such as metalness, emissive, ect, green channel for translucency (light shining through, as oposed to see-through transparency), blue for blue for specular strength (how much light influences net color) alpha for specular power (generally how reflective/glossy an object is) long term purpose: further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
if (!color)
color = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
2012-09-19 15:15:01 +00:00
if ( !color )
{
output = NULL;
return;
}
// Now grab the alpha test value.
Var *alphaTestVal = new Var;
alphaTestVal->setType( "float" );
alphaTestVal->setName( "alphaTestValue" );
alphaTestVal->uniform = true;
alphaTestVal->constSortPos = cspPotentialPrimitive;
// Do the clip.
output = new GenOp( " clip( @.a - @ );\r\n", color, alphaTestVal );
}
//****************************************************************************
// GlowMask
//****************************************************************************
void GlowMaskHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
output = NULL;
// Get the output color... and make it black to mask out
// glow passes rendered before us.
//
// The shader compiler will optimize out all the other
// code above that doesn't contribute to the alpha mask.
Var *color = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
2012-09-19 15:15:01 +00:00
if ( color )
output = new GenOp( " @.rgb = 0;\r\n", color );
}
//****************************************************************************
// RenderTargetZero
//****************************************************************************
void RenderTargetZeroHLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// Do not actually assign zero, but instead a number so close to zero it may as well be zero.
// This will prevent a divide by zero causing an FP special on float render targets
output = new GenOp( " @;\r\n", assignColor( new GenOp( "0.00001" ), Material::None, NULL, mOutputTargetMask ) );
}
//****************************************************************************
// HDR Output
//****************************************************************************
HDROutHLSL::HDROutHLSL()
: mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" ))
2012-09-19 15:15:01 +00:00
{
addDependency( &mTorqueDep );
}
void HDROutHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Let the helper function do the work.
Var *color = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
2012-09-19 15:15:01 +00:00
if ( color )
output = new GenOp( " @ = hdrEncode( @ );\r\n", color, color );
}
//****************************************************************************
// FoliageFeatureHLSL
//****************************************************************************
#include "T3D/fx/groundCover.h"
FoliageFeatureHLSL::FoliageFeatureHLSL()
: mDep(ShaderGen::smCommonShaderPath + String("/foliage.hlsl" ))
2012-09-19 15:15:01 +00:00
{
addDependency( &mDep );
}
void FoliageFeatureHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Get the input variables we need.
Var *inPosition = (Var*)LangElement::find( "inPosition" );
if ( !inPosition )
inPosition = (Var*)LangElement::find( "position" );
Var *inColor = (Var*)LangElement::find( "diffuse" );
Var *inParams = (Var*)LangElement::find( "texCoord" );
MultiLine *meta = new MultiLine;
// Declare the normal and tangent variables since they do not exist
// in this vert type, but we do need to set them up for others.
Var *normal = (Var*)LangElement::find( "normal" );
AssertFatal( normal, "FoliageFeatureHLSL requires vert normal!" );
Var *tangent = new Var;
tangent->setType( "float3" );
tangent->setName( "T" );
LangElement *tangentDec = new DecOp( tangent );
meta->addStatement( new GenOp( " @ = float3(1.0,0,0);\n", tangentDec ) );
2012-09-19 15:15:01 +00:00
// We add a float foliageFade to the OUT structure.
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *fade = connectComp->getElement( RT_TEXCOORD );
fade->setName( "foliageFade" );
fade->setStructName( "OUT" );
fade->setType( "float" );
// grab the eye position
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
if ( !eyePos )
{
eyePos = new Var( "eyePosWorld", "float3" );
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
// All actual work is offloaded to this method.
meta->addStatement( new GenOp( " foliageProcessVert( @, @, @, @, @, @ );\r\n", inPosition, inColor, inParams, normal, tangent, eyePos ) );
// Assign to foliageFade. InColor.a was set to the correct value inside foliageProcessVert.
meta->addStatement( new GenOp( " @ = @.a;\r\n", fade, inColor ) );
output = meta;
}
void FoliageFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Find / create IN.foliageFade
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *fade = connectComp->getElement( RT_TEXCOORD );
fade->setName( "foliageFade" );
fade->setStructName( "IN" );
fade->setType( "float" );
// Find / create visibility
Var *visibility = (Var*) LangElement::find( "visibility" );
if ( !visibility )
{
visibility = new Var();
visibility->setType( "float" );
visibility->setName( "visibility" );
visibility->uniform = true;
visibility->constSortPos = cspPotentialPrimitive;
}
MultiLine *meta = new MultiLine;
// Multiply foliageFade into visibility.
meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) );
output = meta;
}
void FoliageFeatureHLSL::determineFeature( Material *material, const GFXVertexFormat *vertexFormat, U32 stageNum, const FeatureType &type, const FeatureSet &features, MaterialFeatureData *outFeatureData )
{
// This isn't really necessary since the outFeatureData will be filtered after
// this call.
if ( features.hasFeature( MFT_Foliage ) )
outFeatureData->features.addFeature( type );
}
ShaderFeatureConstHandles* FoliageFeatureHLSL::createConstHandles( GFXShader *shader, SimObject *userObject )
{
GroundCover *gcover = dynamic_cast< GroundCover* >( userObject );
AssertFatal( gcover != NULL, "FoliageFeatureHLSL::createConstHandles - userObject was not valid!" );
GroundCoverShaderConstHandles *handles = new GroundCoverShaderConstHandles();
handles->mGroundCover = gcover;
handles->init( shader );
return handles;
}
void ParticleNormalFeatureHLSL::processVert(Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd)
{
MultiLine *meta = new MultiLine;
output = meta;
// Calculate normal and tangent values since we want to keep particle verts
// as light-weight as possible
Var *normal = (Var*) LangElement::find("normal");
if(normal == NULL)
{
normal = new Var;
normal->setType( "float3" );
normal->setName( "normal" );
// These values are not accidental. It is slightly adjusted from facing straight into the
// screen because there is a discontinuity at (0, 1, 0) for gbuffer encoding. Do not
// cause this value to be (0, -1, 0) or interlaced normals will be discontinuous.
// [11/23/2009 Pat]
meta->addStatement(new GenOp(" @ = float3(0.0, -0.97, 0.14);\r\n", new DecOp(normal)));
}
Var *T = (Var*) LangElement::find( "T" );
if(T == NULL)
{
T = new Var;
T->setType( "float3" );
T->setName( "T" );
meta->addStatement(new GenOp(" @ = float3(0.0, 0.0, -1.0);\r\n", new DecOp(T)));
}
}
//****************************************************************************
// ImposterVertFeatureHLSL
//****************************************************************************
ImposterVertFeatureHLSL::ImposterVertFeatureHLSL()
: mDep(ShaderGen::smCommonShaderPath + String("/imposter.hlsl" ))
2012-09-19 15:15:01 +00:00
{
addDependency( &mDep );
}
void ImposterVertFeatureHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
output = meta;
// Get the input vertex variables.
Var *inPosition = (Var*)LangElement::find( "position" );
Var *inMiscParams = (Var*)LangElement::find( "tcImposterParams" );
Var *inUpVec = (Var*)LangElement::find( "tcImposterUpVec" );
Var *inRightVec = (Var*)LangElement::find( "tcImposterRightVec" );
// Get the input shader constants.
Var *imposterLimits = new Var;
imposterLimits->setType( "float4" );
imposterLimits->setName( "imposterLimits" );
imposterLimits->uniform = true;
imposterLimits->constSortPos = cspPotentialPrimitive;
Var *imposterUVs = new Var;
imposterUVs->setType( "float4" );
imposterUVs->setName( "imposterUVs" );
imposterUVs->arraySize = 64; // See imposter.hlsl
imposterUVs->uniform = true;
imposterUVs->constSortPos = cspPotentialPrimitive;
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
if ( !eyePos )
{
eyePos = new Var( "eyePosWorld", "float3" );
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
// Declare the outputs from this feature.
Var *outInPosition = new Var;
outInPosition->setType( "float3" );
outInPosition->setName( "inPosition" );
meta->addStatement( new GenOp( " @;\r\n", new DecOp( outInPosition ) ) );
Var *outTexCoord = new Var;
outTexCoord->setType( "float2" );
outTexCoord->setName( "texCoord" );
meta->addStatement( new GenOp( " @;\r\n", new DecOp( outTexCoord ) ) );
Var *outWorldToTangent = new Var;
outWorldToTangent->setType( "float3x3" );
outWorldToTangent->setName( "worldToTangent" );
meta->addStatement( new GenOp( " @;\r\n", new DecOp( outWorldToTangent ) ) );
// Add imposterFade to the OUT structure.
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *outFade = connectComp->getElement( RT_TEXCOORD );
outFade->setName( "imposterFade" );
outFade->setStructName( "OUT" );
outFade->setType( "float" );
// Assign OUT.imposterFade
meta->addStatement( new GenOp( " @ = @.y;\r\n", outFade, inMiscParams ) );
// All actual work is done in this method.
meta->addStatement( new GenOp( " imposter_v( @.xyz, @.w, @.x * length(@), normalize(@), normalize(@), @.y, @.x, @.z, @.w, @, @, @, @, @ );\r\n",
inPosition,
inPosition,
inMiscParams,
inRightVec,
inUpVec,
inRightVec,
imposterLimits,
imposterLimits,
imposterLimits,
imposterLimits,
eyePos,
imposterUVs,
outInPosition,
outTexCoord,
outWorldToTangent ) );
// Copy the position to wsPosition for use in shaders
// down stream instead of looking for objTrans.
Var *wsPosition = new Var;
wsPosition->setType( "float3" );
wsPosition->setName( "wsPosition" );
meta->addStatement( new GenOp( " @ = @.xyz;\r\n", new DecOp( wsPosition ), outInPosition ) );
// If we new viewToTangent... its the same as the
// world to tangent for an imposter.
Var *viewToTangent = new Var;
viewToTangent->setType( "float3x3" );
viewToTangent->setName( "viewToTangent" );
meta->addStatement( new GenOp( " @ = @;\r\n", new DecOp( viewToTangent ), outWorldToTangent ) );
}
void ImposterVertFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
// Find / create IN.imposterFade
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
Var *fade = connectComp->getElement( RT_TEXCOORD );
fade->setName( "imposterFade" );
fade->setStructName( "IN" );
fade->setType( "float" );
// Find / create visibility
Var *visibility = (Var*) LangElement::find( "visibility" );
if ( !visibility )
{
visibility = new Var();
visibility->setType( "float" );
visibility->setName( "visibility" );
visibility->uniform = true;
visibility->constSortPos = cspPotentialPrimitive;
}
MultiLine *meta = new MultiLine;
// Multiply foliageFade into visibility.
meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) );
output = meta;
}
void ImposterVertFeatureHLSL::determineFeature( Material *material,
const GFXVertexFormat *vertexFormat,
U32 stageNum,
const FeatureType &type,
const FeatureSet &features,
MaterialFeatureData *outFeatureData )
{
if ( features.hasFeature( MFT_ImposterVert ) )
outFeatureData->features.addFeature( MFT_ImposterVert );
}
//****************************************************************************
// HardwareSkinningFeatureHLSL
//****************************************************************************
void HardwareSkinningFeatureHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
Var *inPosition = (Var*)LangElement::find( "inPosition" );
Var *inNormal = (Var*)LangElement::find( "inNormal" );
if ( !inPosition )
inPosition = (Var*)LangElement::find( "position" );
if ( !inNormal )
inNormal = (Var*)LangElement::find( "normal" );
Var* posePos = new Var("posePos", "float3");
Var* poseNormal = new Var("poseNormal", "float3");
Var* poseMat = new Var("poseMat", "float4x3");
Var* poseRotMat = new Var("poseRotMat", "float3x3");
Var* nodeTransforms = (Var*)LangElement::find("nodeTransforms");
if (!nodeTransforms)
{
nodeTransforms = new Var("nodeTransforms", "float4x3");
nodeTransforms->uniform = true;
nodeTransforms->arraySize = TSShape::smMaxSkinBones;
nodeTransforms->constSortPos = cspPotentialPrimitive;
}
U32 numIndices = mVertexFormat->getNumBlendIndices();
meta->addStatement( new GenOp( " @ = 0.0;\r\n", new DecOp( posePos ) ) );
meta->addStatement( new GenOp( " @ = 0.0;\r\n", new DecOp( poseNormal ) ) );
meta->addStatement( new GenOp( " @;\r\n", new DecOp( poseMat ) ) );
meta->addStatement(new GenOp(" @;\r\n int i;\r\n", new DecOp(poseRotMat)));
for (U32 i=0; i<numIndices; i++)
{
// NOTE: To keep things simple, we assume all 4 bone indices are used in each element chunk.
LangElement* inIndices = (Var*)LangElement::find(String::ToString( "blendIndices%d", i ));
LangElement* inWeights = (Var*)LangElement::find(String::ToString( "blendWeight%d", i ));
AssertFatal(inIndices && inWeights, "Something went wrong here");
AssertFatal(poseMat && nodeTransforms && posePos && inPosition && inWeights && poseNormal && inNormal && poseRotMat, "Something went REALLY wrong here");
meta->addStatement( new GenOp( " for (i=0; i<4; i++) {\r\n" ) );
meta->addStatement( new GenOp( " int poseIdx = int(@[i]);\r\n", inIndices ) );
meta->addStatement( new GenOp( " float poseWeight = @[i];\r\n", inWeights) );
meta->addStatement( new GenOp( " @ = @[poseIdx];\r\n", poseMat, nodeTransforms) );
meta->addStatement( new GenOp( " @ = (float3x3)@;\r\n", poseRotMat, poseMat) );
meta->addStatement( new GenOp( " @ += (mul(float4(@, 1), @)).xyz * poseWeight;\r\n", posePos, inPosition, poseMat) );
meta->addStatement( new GenOp( " @ += (mul(@,@) * poseWeight);\r\n", poseNormal, inNormal, poseRotMat) );
meta->addStatement( new GenOp( " }\r\n" ) );
}
// Assign new position and normal
meta->addStatement( new GenOp( " @ = @;\r\n", inPosition, posePos ) );
meta->addStatement( new GenOp( " @ = normalize(@);\r\n", inNormal, poseNormal ) );
output = meta;
}
//****************************************************************************
// ReflectionProbeFeatHLSL
//****************************************************************************
ReflectionProbeFeatHLSL::ReflectionProbeFeatHLSL()
: mDep(ShaderGen::smCommonShaderPath + String("/lighting.hlsl"))
{
addDependency(&mDep);
}
void ReflectionProbeFeatHLSL::processVert(Vector<ShaderComponent*>& componentList,
const MaterialFeatureData& fd)
{
MultiLine* meta = new MultiLine;
output = meta;
// Also output the worldToTanget transform which
// we use to create the world space normal.
//getOutWorldToTangent(componentList, meta, fd);
}
void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd)
{
// Skip out on realtime lighting if we're doing some sort of baked lighting.
//
// TODO: We can totally detect for this in the material
// feature setup... we should move it out of here!
//
if (fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit])
return;
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
MultiLine *meta = new MultiLine;
// Now the wsPosition and wsView.
Var* wsPosition = getInWsPosition(componentList);
Var* worldToTangent = getInWorldToTangent(componentList);
Var *wsNormal = getInWorldNormal(componentList);
Var *wsView = getWsView(wsPosition, meta);
//Reflection Probe WIP
U32 MAX_FORWARD_PROBES = 4;
Var *numProbes = new Var("inNumProbes", "int");
numProbes->uniform = true;
numProbes->constSortPos = cspPotentialPrimitive;
Var *cubeMips = new Var("cubeMips", "float");
cubeMips->uniform = true;
cubeMips->constSortPos = cspPotentialPrimitive;
Var * skylightCubemapIdx = new Var("inSkylightCubemapIdx", "float");
skylightCubemapIdx->uniform = true;
skylightCubemapIdx->constSortPos = cspPotentialPrimitive;
Var *inProbePosArray = new Var("inProbePosArray", "float4");
inProbePosArray->arraySize = MAX_FORWARD_PROBES;
inProbePosArray->uniform = true;
inProbePosArray->constSortPos = cspPotentialPrimitive;
Var *inRefPosArray = new Var("inRefPosArray", "float4");
inRefPosArray->arraySize = MAX_FORWARD_PROBES;
inRefPosArray->uniform = true;
inRefPosArray->constSortPos = cspPotentialPrimitive;
Var * refScaleArray = new Var("inRefScaleArray", "float4");
refScaleArray->arraySize = MAX_FORWARD_PROBES;
refScaleArray->uniform = true;
refScaleArray->constSortPos = cspPotentialPrimitive;
Var *probeConfigData = new Var("inProbeConfigDataArray", "float4");
probeConfigData->arraySize = MAX_FORWARD_PROBES;
probeConfigData->uniform = true;
probeConfigData->constSortPos = cspPotentialPrimitive;
Var *worldToObjArray = new Var("inWorldToObjArray", "float4x4");
worldToObjArray->arraySize = MAX_FORWARD_PROBES;
worldToObjArray->uniform = true;
worldToObjArray->constSortPos = cspPotentialPrimitive;
Var *BRDFTexture = new Var("BRDFTexture", "SamplerState");
BRDFTexture->uniform = true;
BRDFTexture->sampler = true;
BRDFTexture->constNum = Var::getTexUnitNum(); // used as texture unit num here
Var *BRDFTextureTex = new Var("texture_BRDFTexture", "Texture2D");
BRDFTextureTex->uniform = true;
BRDFTextureTex->texture = true;
BRDFTextureTex->constNum = BRDFTexture->constNum;
Var *specularCubemapAR = new Var("SpecularCubemapAR", "SamplerState");
specularCubemapAR->uniform = true;
specularCubemapAR->sampler = true;
specularCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here
Var *specularCubemapARTex = new Var("texture_SpecularCubemapAR", "TextureCubeArray");
specularCubemapARTex->uniform = true;
specularCubemapARTex->texture = true;
specularCubemapARTex->constNum = specularCubemapAR->constNum;
Var *irradianceCubemapAR = new Var("IrradianceCubemapAR", "SamplerState");
irradianceCubemapAR->uniform = true;
irradianceCubemapAR->sampler = true;
irradianceCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here
Var *irradianceCubemapARTex = new Var("texture_IrradianceCubemapAR", "TextureCubeArray");
irradianceCubemapARTex->uniform = true;
irradianceCubemapARTex->texture = true;
irradianceCubemapARTex->constNum = irradianceCubemapAR->constNum;
Var* surface = getSurface(componentList, meta, fd);
if (!surface)
{
Con::errorf("ShaderGen::ReflectionProbeFeatHLSL() - failed to generate surface!");
return;
}
Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
//Reflection vec
Var* ibl = (Var*)LangElement::find("ibl");
if (!ibl)
{
ibl = new Var("ibl", "float3");
}
Var* eyePos = (Var*)LangElement::find("eyePosWorld");
if (!eyePos)
{
eyePos = new Var;
eyePos->setType("float3");
eyePos->setName("eyePosWorld");
eyePos->uniform = true;
eyePos->constSortPos = cspPass;
}
String computeForwardProbes = String(" @ = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
computeForwardProbes += String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t");
computeForwardProbes += String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n");
meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray, eyePos,
skylightCubemapIdx, BRDFTexture,
irradianceCubemapAR, specularCubemapAR));
meta->addStatement(new GenOp(" @.rgb = @.rgb;\r\n", curColor, ibl));
output = meta;
}
ShaderFeature::Resources ReflectionProbeFeatHLSL::getResources(const MaterialFeatureData &fd)
{
Resources res;
res.numTex = 3;
res.numTexReg = 3;
return res;
}
void ReflectionProbeFeatHLSL::setTexData(Material::StageData &stageDat,
const MaterialFeatureData &stageFeatures,
RenderPassData &passData,
U32 &texIndex)
{
if (stageFeatures.features[MFT_ReflectionProbes])
{
passData.mSamplerNames[texIndex] = "BRDFTexture";
passData.mTexType[texIndex++] = Material::Standard;
// assuming here that it is a scenegraph cubemap
passData.mSamplerNames[texIndex] = "SpecularCubemapAR";
passData.mTexType[texIndex++] = Material::SGCube;
passData.mSamplerNames[texIndex] = "IrradianceCubemapAR";
passData.mTexType[texIndex++] = Material::SGCube;
}
}