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/GLSL/shaderFeatureGLSL.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"
|
2015-01-10 19:41:25 +00:00
|
|
|
#include "ts/tsShape.h"
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2017-07-24 05:40:27 +00:00
|
|
|
#include "shaderGen/shaderGen.h"
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
LangElement * ShaderFeatureGLSL::setupTexSpaceMat( Vector<ShaderComponent*> &, // componentList
|
|
|
|
|
Var **texSpaceMat )
|
|
|
|
|
{
|
|
|
|
|
Var *N = (Var*) LangElement::find( "normal" );
|
|
|
|
|
Var *B = (Var*) LangElement::find( "B" );
|
|
|
|
|
Var *T = (Var*) LangElement::find( "T" );
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *tangentW = (Var*) LangElement::find( "tangentW" );
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
// setup matrix var
|
|
|
|
|
*texSpaceMat = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
(*texSpaceMat)->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
(*texSpaceMat)->setName( "objToTangentSpace" );
|
|
|
|
|
|
|
|
|
|
MultiLine * meta = new MultiLine;
|
2015-09-01 03:26:50 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = float3x3(1,0,0, 0,1,0, 0,0,1);\r\n", new DecOp( *texSpaceMat ) ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// Protect against missing normal and tangent.
|
|
|
|
|
if ( !N || !T )
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " tSetMatrixRow(@, 0, float3( 1, 0, 0 )); tSetMatrixRow(@, 1,float3( 0, 1, 0 )); tSetMatrixRow(@,2, float3( 0, 0, 1 ));\r\n",
|
|
|
|
|
*texSpaceMat, *texSpaceMat, *texSpaceMat ) );
|
|
|
|
|
return meta;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " tSetMatrixRow(@, 0, @);\r\n", *texSpaceMat, T ) );
|
|
|
|
|
if ( B )
|
|
|
|
|
meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, @);\r\n", *texSpaceMat, B ) );
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(dStricmp((char*)T->type, "vec4") == 0)
|
|
|
|
|
meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ) * @.w);\r\n", *texSpaceMat, T, N, T ) );
|
2016-12-11 20:58:52 +00:00
|
|
|
else if(tangentW)
|
|
|
|
|
meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ) * @);\r\n", *texSpaceMat, T, N, tangentW ) );
|
2014-04-17 15:44:49 +00:00
|
|
|
else
|
|
|
|
|
meta->addStatement( new GenOp( " tSetMatrixRow(@, 1, cross( @, normalize(@) ));\r\n", *texSpaceMat, T, N ) );
|
|
|
|
|
}
|
|
|
|
|
meta->addStatement( new GenOp( " tSetMatrixRow(@, 2, normalize(@));\r\n", *texSpaceMat, N ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
return meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LangElement* ShaderFeatureGLSL::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( "vec4" );
|
2014-11-30 04:32:40 +00:00
|
|
|
color->setName( getOutputTargetVarName( outputTarget ) );
|
|
|
|
|
color->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-11-30 04:32:40 +00:00
|
|
|
return new GenOp( "@ = @", color, elem );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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::AddAlpha:
|
|
|
|
|
assign = new GenOp( "@ += @ * @.a", color, elem, elem );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Material::LerpAlpha:
|
|
|
|
|
if ( !lerpElem )
|
|
|
|
|
lerpElem = elem;
|
2014-04-17 15:44:49 +00:00
|
|
|
assign = new GenOp( "@.rgb = lerp( @.rgb, (@).rgb, (@).a )", color, color, elem, lerpElem );
|
2012-09-19 15:15:01 +00:00
|
|
|
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 *ShaderFeatureGLSL::expandNormalMap( LangElement *sampleNormalOp,
|
|
|
|
|
LangElement *normalDecl,
|
|
|
|
|
LangElement *normalVar,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
2017-06-23 16:36:20 +00:00
|
|
|
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
|
|
|
{
|
2014-04-17 15:44:49 +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 ) );
|
|
|
|
|
}
|
2017-06-23 16:36:20 +00:00
|
|
|
else if (hasBc3)
|
2014-04-17 15:44:49 +00:00
|
|
|
{
|
2017-06-23 16:36:20 +00:00
|
|
|
// BC3 Swizzle trick
|
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( " @ = 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 ) );
|
|
|
|
|
}
|
2017-06-23 16:36:20 +00:00
|
|
|
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 ) );
|
|
|
|
|
}
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeatureGLSL::ShaderFeatureGLSL()
|
|
|
|
|
{
|
|
|
|
|
output = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var * ShaderFeatureGLSL::getVertTexCoord( const String &name )
|
|
|
|
|
{
|
|
|
|
|
Var *inTex = NULL;
|
|
|
|
|
|
|
|
|
|
for( U32 i=0; i<LangElement::elementList.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
if( !dStrcmp( (char*)LangElement::elementList[i]->name, name.c_str() ) )
|
|
|
|
|
{
|
|
|
|
|
inTex = dynamic_cast<Var*>( LangElement::elementList[i] );
|
|
|
|
|
if ( inTex )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
// NOTE: This used to do this check...
|
|
|
|
|
//
|
|
|
|
|
// dStrcmp( (char*)inTex->structName, "IN" )
|
|
|
|
|
//
|
|
|
|
|
// ... 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.
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return inTex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::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* ShaderFeatureGLSL::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;
|
2014-04-17 15:44:49 +00:00
|
|
|
worldToTangent->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
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" );
|
2012-09-19 15:15:01 +00:00
|
|
|
worldToObj->uniform = true;
|
|
|
|
|
worldToObj->constSortPos = cspPrimitive;
|
|
|
|
|
}
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// assign world->tangent transform
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tMul( @, float3x3(@) );\r\n", worldToTangentDecl, texSpaceMat, worldToObj ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
// Assume particle normal generation has set this up in the proper space
|
2012-09-19 15:15:01 +00:00
|
|
|
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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outWorldToTangent->setStructName( "OUT" );
|
|
|
|
|
outWorldToTangent->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = @;\r\n", outWorldToTangent, worldToTangent ) );
|
|
|
|
|
|
|
|
|
|
return outWorldToTangent;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
Var* ShaderFeatureGLSL::getOutViewToTangent( Vector<ShaderComponent*> &componentList,
|
2012-09-19 15:15:01 +00:00
|
|
|
MultiLine *meta,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Var *outViewToTangent = (Var*)LangElement::find( "outViewToTangent" );
|
|
|
|
|
if ( outViewToTangent )
|
|
|
|
|
return outViewToTangent;
|
|
|
|
|
|
|
|
|
|
Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" );
|
|
|
|
|
if ( !viewToTangent )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd );
|
|
|
|
|
|
|
|
|
|
if(!fd.features[MFT_ParticleNormal])
|
|
|
|
|
{
|
|
|
|
|
// turn obj->tangent into world->tangent
|
|
|
|
|
viewToTangent = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
viewToTangent->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
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
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tMul( (@), float3x3(@) );\r\n", viewToTangentDecl, texSpaceMat, viewToObj ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outViewToTangent->setStructName( "OUT" );
|
|
|
|
|
outViewToTangent->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = @;\r\n", outViewToTangent, viewToTangent ) );
|
|
|
|
|
|
|
|
|
|
return outViewToTangent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::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, "ShaderFeatureGLSL::getOutTexCoord - Unknown vertex input coord!" );
|
|
|
|
|
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
|
|
|
|
|
texCoord = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
texCoord->setName( outTexName );
|
2014-04-17 15:44:49 +00:00
|
|
|
texCoord->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
texCoord->setType( type );
|
|
|
|
|
|
|
|
|
|
if( useTexAnim )
|
|
|
|
|
{
|
|
|
|
|
inTex->setType( "vec4" );
|
|
|
|
|
|
|
|
|
|
// create texture mat var
|
|
|
|
|
Var *texMat = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
texMat->setType( "float4x4" );
|
2012-09-19 15:15:01 +00:00
|
|
|
texMat->setName( "texMat" );
|
|
|
|
|
texMat->uniform = true;
|
|
|
|
|
texMat->constSortPos = cspPass;
|
|
|
|
|
|
|
|
|
|
// Statement allows for casting of different types which
|
|
|
|
|
// eliminates vector truncation problems.
|
2016-02-26 06:21:01 +00:00
|
|
|
String statement = String::ToString( " @ = %s(tMul(@, @).xy);\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.
|
2014-04-17 15:44:49 +00:00
|
|
|
String statement = String::ToString( " @ = %s(@);\r\n", type );
|
2012-09-19 15:15:01 +00:00
|
|
|
meta->addStatement( new GenOp( statement, texCoord, inTex ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AssertFatal( dStrcmp( type, (const char*)texCoord->type ) == 0,
|
|
|
|
|
"ShaderFeatureGLSL::getOutTexCoord - Type mismatch!" );
|
|
|
|
|
|
|
|
|
|
return texCoord;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::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 );
|
2014-04-17 15:44:49 +00:00
|
|
|
texCoord->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
texCoord->setType( type );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AssertFatal( dStrcmp( type, (const char*)texCoord->type ) == 0,
|
|
|
|
|
"ShaderFeatureGLSL::getInTexCoord - Type mismatch!" );
|
|
|
|
|
|
|
|
|
|
return texCoord;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
Var* ShaderFeatureGLSL::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( dStrcmp( type, (const char*)inColor->type ) == 0,
|
|
|
|
|
"ShaderFeatureGLSL::getInColor - Type mismatch!" );
|
|
|
|
|
|
|
|
|
|
return inColor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::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( "vec4" );
|
|
|
|
|
|
|
|
|
|
Var *outPosition = (Var*) LangElement::find( "gl_Position" );
|
|
|
|
|
AssertFatal( outPosition, "ShaderFeatureGLSL::addOutVpos - Didn't find the output position." );
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " @ = @;\r\n", outVpos, outPosition ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return outVpos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::getInVpos( MultiLine *meta,
|
|
|
|
|
Vector<ShaderComponent*> &componentList )
|
|
|
|
|
{
|
|
|
|
|
Var *inVpos = (Var*)LangElement::find( "vpos" );
|
|
|
|
|
if ( inVpos )
|
|
|
|
|
return inVpos;
|
|
|
|
|
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>( componentList[C_CONNECTOR] );
|
|
|
|
|
/*
|
|
|
|
|
if ( GFX->getPixelShaderVersion() >= 3.0f )
|
|
|
|
|
{
|
|
|
|
|
inVpos = connectComp->getElement( RT_VPOS );
|
|
|
|
|
inVpos->setName( "vpos" );
|
|
|
|
|
inVpos->setStructName( "IN" );
|
|
|
|
|
inVpos->setType( "vec2" );
|
|
|
|
|
return inVpos;
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
inVpos = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
inVpos->setName( "inVpos" );
|
|
|
|
|
inVpos->setStructName( "IN" );
|
|
|
|
|
inVpos->setType( "vec4" );
|
|
|
|
|
|
|
|
|
|
Var *vpos = new Var( "vpos", "vec2" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = @.xy / @.w;\r\n", new DecOp( vpos ), inVpos, inVpos ) );
|
|
|
|
|
|
|
|
|
|
return vpos;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
Var* ShaderFeatureGLSL::getInWorldToTangent( Vector<ShaderComponent*> &componentList )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" );
|
2012-09-19 15:15:01 +00:00
|
|
|
if ( !worldToTangent )
|
|
|
|
|
{
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
worldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
|
2014-04-17 15:44:49 +00:00
|
|
|
worldToTangent->setName( "worldToTangent" );
|
|
|
|
|
worldToTangent->setStructName( "IN" );
|
|
|
|
|
worldToTangent->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return worldToTangent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::getInViewToTangent( Vector<ShaderComponent*> &componentList )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" );
|
2012-09-19 15:15:01 +00:00
|
|
|
if ( !viewToTangent )
|
|
|
|
|
{
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
viewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 );
|
2014-04-17 15:44:49 +00:00
|
|
|
viewToTangent->setName( "viewToTangent" );
|
|
|
|
|
viewToTangent->setStructName( "IN" );
|
|
|
|
|
viewToTangent->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return viewToTangent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::getNormalMapTex()
|
|
|
|
|
{
|
|
|
|
|
Var *normalMap = (Var*)LangElement::find( "bumpMap" );
|
|
|
|
|
if ( !normalMap )
|
|
|
|
|
{
|
|
|
|
|
normalMap = new Var;
|
|
|
|
|
normalMap->setType( "sampler2D" );
|
|
|
|
|
normalMap->setName( "bumpMap" );
|
|
|
|
|
normalMap->uniform = true;
|
|
|
|
|
normalMap->sampler = true;
|
|
|
|
|
normalMap->constNum = Var::getTexUnitNum();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return normalMap;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
Var* ShaderFeatureGLSL::getObjTrans( Vector<ShaderComponent*> &componentList,
|
2012-09-19 15:15:01 +00:00
|
|
|
bool useInstancing,
|
|
|
|
|
MultiLine *meta )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *objTrans = (Var*)LangElement::find( "objTrans" );
|
|
|
|
|
if ( objTrans )
|
2012-09-19 15:15:01 +00:00
|
|
|
return objTrans;
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
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( "mat4x4" );
|
|
|
|
|
objTrans->setName( "objTrans" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = mat4x4( // 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" );
|
2012-09-19 15:15:01 +00:00
|
|
|
objTrans->setName( "objTrans" );
|
|
|
|
|
objTrans->uniform = true;
|
|
|
|
|
objTrans->constSortPos = cspPrimitive;
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
return objTrans;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::getModelView( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
bool useInstancing,
|
|
|
|
|
MultiLine *meta )
|
|
|
|
|
{
|
|
|
|
|
Var *modelview = (Var*)LangElement::find( "modelview" );
|
|
|
|
|
if ( modelview )
|
|
|
|
|
return modelview;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
modelview = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
modelview->setType( "float4x4" );
|
|
|
|
|
modelview->setName( "modelview" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = tMul( @, @ ); // Instancing!\r\n", new DecOp( modelview ), viewProj, objTrans ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
modelview = new Var;
|
|
|
|
|
modelview->setType( "float4x4" );
|
2012-09-19 15:15:01 +00:00
|
|
|
modelview->setName( "modelview" );
|
|
|
|
|
modelview->uniform = true;
|
|
|
|
|
modelview->constSortPos = cspPrimitive;
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
return modelview;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::getWorldView( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
bool useInstancing,
|
|
|
|
|
MultiLine *meta )
|
|
|
|
|
{
|
|
|
|
|
Var *worldView = (Var*)LangElement::find( "worldViewOnly" );
|
|
|
|
|
if ( worldView )
|
|
|
|
|
return worldView;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
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( " @ = tMul( @, @ ); // Instancing!\r\n", new DecOp( worldView ), worldToCamera, objTrans ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-09-19 15:15:01 +00:00
|
|
|
worldView = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
worldView->setType( "float4x4" );
|
2012-09-19 15:15:01 +00:00
|
|
|
worldView->setName( "worldViewOnly" );
|
|
|
|
|
worldView->uniform = true;
|
|
|
|
|
worldView->constSortPos = cspPrimitive;
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
return worldView;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
Var* ShaderFeatureGLSL::getInvWorldView( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
bool useInstancing,
|
|
|
|
|
MultiLine *meta )
|
|
|
|
|
{
|
|
|
|
|
Var *viewToObj = (Var*)LangElement::find( "viewToObj" );
|
|
|
|
|
if ( viewToObj )
|
|
|
|
|
return viewToObj;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
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
|
|
|
|
|
{
|
2012-09-19 15:15:01 +00:00
|
|
|
viewToObj = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
viewToObj->setType( "float4x4" );
|
2012-09-19 15:15:01 +00:00
|
|
|
viewToObj->setName( "viewToObj" );
|
|
|
|
|
viewToObj->uniform = true;
|
|
|
|
|
viewToObj->constSortPos = cspPrimitive;
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
return viewToObj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShaderFeatureGLSL::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, "ShaderFeatureGLSL::getWsPosition - The vertex position was not found!" );
|
|
|
|
|
|
|
|
|
|
Var *objTrans = getObjTrans( componentList, useInstancing, 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
|
|
|
meta->addStatement( new GenOp( " @ = tMul( @, vec4( @.xyz, 1 ) ).xyz;\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
wsPosition, objTrans, inPosition ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outWsPosition->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outWsPosition->setType( "vec3" );
|
|
|
|
|
|
|
|
|
|
getWsPosition( componentList, useInstancing, meta, outWsPosition );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return outWsPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::getInWsPosition( Vector<ShaderComponent*> &componentList )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *wsPosition = (Var*)LangElement::find( "wsPosition" );
|
2012-09-19 15:15:01 +00:00
|
|
|
if ( !wsPosition )
|
|
|
|
|
{
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
wsPosition = connectComp->getElement( RT_TEXCOORD );
|
2014-04-17 15:44:49 +00:00
|
|
|
wsPosition->setName( "wsPosition" );
|
|
|
|
|
wsPosition->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
wsPosition->setType( "vec3" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return wsPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::getWsView( Var *wsPosition, MultiLine *meta )
|
|
|
|
|
{
|
|
|
|
|
Var *wsView = (Var*)LangElement::find( "wsView" );
|
|
|
|
|
if ( !wsView )
|
|
|
|
|
{
|
|
|
|
|
wsView = new Var( "wsView", "vec3" );
|
|
|
|
|
|
|
|
|
|
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
|
|
|
|
|
if ( !eyePos )
|
|
|
|
|
{
|
|
|
|
|
eyePos = new Var;
|
|
|
|
|
eyePos->setType( "vec3" );
|
|
|
|
|
eyePos->setName( "eyePosWorld" );
|
|
|
|
|
eyePos->uniform = true;
|
|
|
|
|
eyePos->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " @ = normalize( @ - @ );\r\n",
|
|
|
|
|
new DecOp( wsView ), eyePos, wsPosition ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return wsView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* ShaderFeatureGLSL::addOutDetailTexCoord( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
MultiLine *meta,
|
|
|
|
|
bool useTexAnim )
|
|
|
|
|
{
|
|
|
|
|
// Check if its already added.
|
|
|
|
|
Var *outTex = (Var*)LangElement::find( "detCoord" );
|
|
|
|
|
if ( outTex )
|
|
|
|
|
return outTex;
|
|
|
|
|
|
|
|
|
|
// Grab incoming texture coords.
|
|
|
|
|
Var *inTex = getVertTexCoord( "texCoord" );
|
|
|
|
|
|
|
|
|
|
// create detail variable
|
|
|
|
|
Var *detScale = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
detScale->setType( "vec2" );
|
2012-09-19 15:15:01 +00:00
|
|
|
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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outTex->setStructName( "OUT" );
|
|
|
|
|
outTex->setType( "vec2" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
if ( useTexAnim )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
inTex->setType( "vec4" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Find or create the texture matrix.
|
|
|
|
|
Var *texMat = (Var*)LangElement::find( "texMat" );
|
|
|
|
|
if ( !texMat )
|
|
|
|
|
{
|
|
|
|
|
texMat = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
texMat->setType( "float4x4" );
|
2012-09-19 15:15:01 +00:00
|
|
|
texMat->setName( "texMat" );
|
|
|
|
|
texMat->uniform = true;
|
|
|
|
|
texMat->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-26 06:21:01 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tMul(@, @).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( " @ = @ * @;\r\n", outTex, inTex, detScale ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return outTex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// Base Texture
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
2015-11-11 19:52:46 +00:00
|
|
|
DiffuseMapFeatGLSL::DiffuseMapFeatGLSL()
|
2017-07-24 05:40:27 +00:00
|
|
|
: mTorqueDep(ShaderGen::smCommonShaderPath + String("/gl/torque.glsl"))
|
2015-11-11 19:52:46 +00:00
|
|
|
{
|
|
|
|
|
addDependency(&mTorqueDep);
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
void DiffuseMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
2012-09-19 15:15:01 +00:00
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
getOutTexCoord( "texCoord",
|
|
|
|
|
"vec2",
|
|
|
|
|
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 DiffuseMapFeatGLSL::getOutputTargets(const MaterialFeatureData &fd) const
|
|
|
|
|
{
|
|
|
|
|
return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
void DiffuseMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
// grab connector texcoord register
|
2017-05-28 21:51:31 +00:00
|
|
|
Var *inTex = getInTexCoord( "texCoord", "vec2", 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;
|
|
|
|
|
diffuseMap->setType( "sampler2D" );
|
|
|
|
|
diffuseMap->setName( "diffuseMap" );
|
|
|
|
|
diffuseMap->uniform = true;
|
|
|
|
|
diffuseMap->sampler = true;
|
|
|
|
|
diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
2015-11-11 19:52:46 +00:00
|
|
|
// create sample color var
|
|
|
|
|
Var *diffColor = new Var;
|
|
|
|
|
diffColor->setType("vec4");
|
|
|
|
|
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] )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
colorDecl,
|
|
|
|
|
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");
|
2014-04-17 15:44:49 +00:00
|
|
|
atlasedTex->setType("vec2");
|
2012-09-19 15:15:01 +00:00
|
|
|
LangElement *atDecl = new DecOp(atlasedTex);
|
|
|
|
|
|
|
|
|
|
// Parameters of the texture atlas
|
|
|
|
|
Var *atParams = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
atParams->setType("vec4");
|
2012-09-19 15:15:01 +00:00
|
|
|
atParams->setName("diffuseAtlasParams");
|
|
|
|
|
atParams->uniform = true;
|
|
|
|
|
atParams->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
// Parameters of the texture (tile) this object is using in the atlas
|
|
|
|
|
Var *tileParams = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
tileParams->setType("vec4");
|
2012-09-19 15:15:01 +00:00
|
|
|
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
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement(new GenOp(" float2 _dx = ddx(@ * @.z);\r\n", inTex, atParams));
|
|
|
|
|
meta->addStatement(new GenOp(" float2 _dy = ddy(@ * @.z);\r\n", inTex, atParams));
|
2012-09-19 15:15:01 +00:00
|
|
|
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));
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement(new GenOp(" float2 mipSz = mipPixSz / @.xy;\r\n", atParams));
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement(new GenOp(" float2 mipSz = float2(1.0, 1.0);\r\n"));
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tiling mode
|
|
|
|
|
// TODO: Select wrap or clamp somehow
|
|
|
|
|
if( true ) // Wrap
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement(new GenOp(" @ = frac(@);\r\n", atDecl, inTex));
|
2012-09-19 15:15:01 +00:00
|
|
|
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
|
2017-04-11 05:23:14 +00:00
|
|
|
if(!fd.features[MFT_DeferredConditioner])
|
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(" @ = vec4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams));
|
|
|
|
|
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-06-23 16:36:20 +00:00
|
|
|
|
|
|
|
|
meta->addStatement(new GenOp( " @ = tex2Dlod(@, float4(@, 0.0, mipLod));\r\n",
|
|
|
|
|
new DecOp(diffColor), 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
|
|
|
|
|
{
|
2015-11-11 19:52:46 +00:00
|
|
|
meta->addStatement(new GenOp("@ = tex2D(@, @);\r\n", colorDecl, 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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources DiffuseMapFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
res.numTex = 1;
|
|
|
|
|
res.numTexReg = 1;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DiffuseMapFeatGLSL::setTexData( Material::StageData &stageDat,
|
|
|
|
|
const MaterialFeatureData &fd,
|
|
|
|
|
RenderPassData &passData,
|
|
|
|
|
U32 &texIndex )
|
|
|
|
|
{
|
2015-01-20 18:13:25 +00:00
|
|
|
GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap );
|
2015-01-21 13:39:05 +00:00
|
|
|
passData.mSamplerNames[ texIndex ] = "diffuseMap";
|
|
|
|
|
passData.mTexSlot[ texIndex++ ].texObject = tex;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// Overlay Texture
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
void OverlayTexFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Var *inTex = getVertTexCoord( "texCoord2" );
|
|
|
|
|
AssertFatal( inTex, "OverlayTexFeatGLSL::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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outTex->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outTex->setType( "vec2" );
|
|
|
|
|
|
|
|
|
|
if( fd.features[MFT_TexAnim] )
|
|
|
|
|
{
|
|
|
|
|
inTex->setType( "vec4" );
|
|
|
|
|
|
|
|
|
|
// Find or create the texture matrix.
|
|
|
|
|
Var *texMat = (Var*)LangElement::find( "texMat" );
|
|
|
|
|
if ( !texMat )
|
|
|
|
|
{
|
|
|
|
|
texMat = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
texMat->setType( "float4x4" );
|
2012-09-19 15:15:01 +00:00
|
|
|
texMat->setName( "texMat" );
|
|
|
|
|
texMat->uniform = true;
|
|
|
|
|
texMat->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
output = new GenOp( " @ = tMul(@, @);\r\n", outTex, texMat, inTex );
|
2012-09-19 15:15:01 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setup language elements to output incoming tex coords to output
|
|
|
|
|
output = new GenOp( " @ = @;\r\n", outTex, inTex );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OverlayTexFeatGLSL::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 );
|
2014-04-17 15:44:49 +00:00
|
|
|
inTex->setName( "texCoord2" );
|
|
|
|
|
inTex->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
inTex->setType( "vec2" );
|
|
|
|
|
|
|
|
|
|
// create texture var
|
|
|
|
|
Var *diffuseMap = new Var;
|
|
|
|
|
diffuseMap->setType( "sampler2D" );
|
|
|
|
|
diffuseMap->setName( "overlayMap" );
|
|
|
|
|
diffuseMap->uniform = true;
|
|
|
|
|
diffuseMap->sampler = true;
|
|
|
|
|
diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
LangElement *statement = new GenOp( "tex2D(@, @)", diffuseMap, inTex );
|
2012-09-19 15:15:01 +00:00
|
|
|
output = new GenOp( " @;\r\n", assignColor( statement, Material::LerpAlpha ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources OverlayTexFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
res.numTex = 1;
|
|
|
|
|
res.numTexReg = 1;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OverlayTexFeatGLSL::setTexData( Material::StageData &stageDat,
|
|
|
|
|
const MaterialFeatureData &fd,
|
|
|
|
|
RenderPassData &passData,
|
|
|
|
|
U32 &texIndex )
|
|
|
|
|
{
|
|
|
|
|
GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap );
|
|
|
|
|
if ( tex )
|
2014-11-08 16:41:17 +00:00
|
|
|
{
|
|
|
|
|
passData.mSamplerNames[ texIndex ] = "overlayMap";
|
2012-09-19 15:15:01 +00:00
|
|
|
passData.mTexSlot[ texIndex++ ].texObject = tex;
|
2014-11-08 16:41:17 +00:00
|
|
|
}
|
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 DiffuseFeatureGLSL::getOutputTargets(const MaterialFeatureData &fd) const
|
|
|
|
|
{
|
|
|
|
|
return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
void DiffuseFeatureGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Var* diffuseMaterialColor = new Var;
|
|
|
|
|
diffuseMaterialColor->setType( "vec4" );
|
|
|
|
|
diffuseMaterialColor->setName( "diffuseMaterialColor" );
|
|
|
|
|
diffuseMaterialColor->uniform = true;
|
|
|
|
|
diffuseMaterialColor->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
MultiLine* meta = new MultiLine;
|
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
|
|
|
Var *col = (Var*)LangElement::find("col");
|
|
|
|
|
ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget;
|
|
|
|
|
if (fd.features[MFT_isDeferred])
|
|
|
|
|
{
|
|
|
|
|
targ = ShaderFeature::RenderTarget1;
|
|
|
|
|
|
|
|
|
|
col = (Var*)LangElement::find("col1");
|
2018-03-13 23:07:58 +00:00
|
|
|
meta = new MultiLine;
|
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("vec4");
|
|
|
|
|
col->setName(getOutputTargetVarName(targ));
|
|
|
|
|
col->setStructName("OUT");
|
|
|
|
|
meta->addStatement(new GenOp(" @ = vec4(1.0);\r\n", col));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 DiffuseVertColorFeatureGLSL::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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outColor->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outColor->setType( "vec4" );
|
|
|
|
|
|
|
|
|
|
output = new GenOp( " @ = @;\r\n", outColor, inColor );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
output = NULL; // Nothing we need to do.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DiffuseVertColorFeatureGLSL::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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
vertColor->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
vertColor->setType( "vec4" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MultiLine* meta = new MultiLine;
|
2016-05-25 08:08:28 +00:00
|
|
|
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 LightmapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
// grab tex register from incoming vert
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *inTex = getVertTexCoord( "texCoord2" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// grab connector texcoord register
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
Var *outTex = connectComp->getElement( RT_TEXCOORD );
|
2014-04-17 15:44:49 +00:00
|
|
|
outTex->setName( "texCoord2" );
|
|
|
|
|
outTex->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outTex->setType( "vec2" );
|
|
|
|
|
|
|
|
|
|
// setup language elements to output incoming tex coords to output
|
|
|
|
|
output = new GenOp( " @ = @;\r\n", outTex, inTex );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LightmapFeatGLSL::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 );
|
2014-04-17 15:44:49 +00:00
|
|
|
inTex->setName( "texCoord2" );
|
|
|
|
|
inTex->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
inTex->setType( "vec2" );
|
|
|
|
|
|
|
|
|
|
// create texture var
|
|
|
|
|
Var *lightMap = new Var;
|
|
|
|
|
lightMap->setType( "sampler2D" );
|
|
|
|
|
lightMap->setName( "lightMap" );
|
|
|
|
|
lightMap->uniform = true;
|
|
|
|
|
lightMap->sampler = true;
|
|
|
|
|
lightMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// argh, pixel specular should prob use this too
|
|
|
|
|
if( fd.features[MFT_NormalMap] )
|
|
|
|
|
{
|
|
|
|
|
Var *lmColor = new Var;
|
|
|
|
|
lmColor->setName( "lmColor" );
|
|
|
|
|
lmColor->setType( "vec4" );
|
|
|
|
|
LangElement *lmColorDecl = new DecOp( lmColor );
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
output = new GenOp( " @ = tex2D(@, @);\r\n", lmColorDecl, 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 ) )
|
2017-04-11 05:23:14 +00:00
|
|
|
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
|
|
|
|
|
if(bPreProcessedLighting)
|
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
|
|
|
statement = new GenOp( "vec4(@, 1.0)", inColor );
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
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
|
|
|
statement = new GenOp( "tex2D(@, @) + vec4(@.rgb, 0.0)", lightMap, inTex, inColor );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
// If we still don't have it... then just sample the lightmap.
|
|
|
|
|
if ( !statement )
|
|
|
|
|
statement = new GenOp( "tex2D(@, @)", lightMap, inTex );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Assign to proper render target
|
2014-04-17 15:44:49 +00:00
|
|
|
MultiLine *meta = new MultiLine;
|
2012-09-19 15:15:01 +00:00
|
|
|
if( fd.features[MFT_LightbufferMRT] )
|
2014-04-17 15:44:49 +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( statement, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
|
|
|
|
|
meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources LightmapFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
res.numTex = 1;
|
|
|
|
|
res.numTexReg = 1;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LightmapFeatGLSL::setTexData( Material::StageData &stageDat,
|
|
|
|
|
const MaterialFeatureData &fd,
|
|
|
|
|
RenderPassData &passData,
|
|
|
|
|
U32 &texIndex )
|
|
|
|
|
{
|
|
|
|
|
GFXTextureObject *tex = stageDat.getTex( MFT_LightMap );
|
2014-04-17 15:44:49 +00:00
|
|
|
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 LightmapFeatGLSL::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 TonemapFeatGLSL::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 );
|
2014-04-17 15:44:49 +00:00
|
|
|
outTex2->setName( "texCoord2" );
|
|
|
|
|
outTex2->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outTex2->setType( "vec2" );
|
|
|
|
|
|
|
|
|
|
output = new GenOp( " @ = @;\r\n", outTex2, inTex2 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TonemapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
// Grab connector
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
|
|
|
|
|
Var *inTex2 = connectComp->getElement( RT_TEXCOORD );
|
2014-04-17 15:44:49 +00:00
|
|
|
inTex2->setName( "texCoord2" );
|
|
|
|
|
inTex2->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
inTex2->setType( "vec2" );
|
|
|
|
|
|
|
|
|
|
// create texture var
|
|
|
|
|
Var *toneMap = new Var;
|
|
|
|
|
toneMap->setType( "sampler2D" );
|
|
|
|
|
toneMap->setName( "toneMap" );
|
|
|
|
|
toneMap->uniform = true;
|
|
|
|
|
toneMap->sampler = true;
|
|
|
|
|
toneMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
|
|
|
|
MultiLine * meta = new MultiLine;
|
|
|
|
|
|
|
|
|
|
// First get the toneMap color
|
|
|
|
|
Var *toneMapColor = new Var;
|
|
|
|
|
toneMapColor->setType( "vec4" );
|
|
|
|
|
toneMapColor->setName( "toneMapColor" );
|
|
|
|
|
LangElement *toneMapColorDecl = new DecOp( toneMapColor );
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", toneMapColorDecl, 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
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", toneMapColor, toneMapColor ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// 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 ) )
|
2017-04-11 05:23:14 +00:00
|
|
|
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] )
|
2014-04-17 15:44:49 +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( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
|
|
|
|
|
meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
|
|
|
|
meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, blendOp ) ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources TonemapFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
res.numTex = 1;
|
|
|
|
|
res.numTexReg = 1;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TonemapFeatGLSL::setTexData( Material::StageData &stageDat,
|
|
|
|
|
const MaterialFeatureData &fd,
|
|
|
|
|
RenderPassData &passData,
|
|
|
|
|
U32 &texIndex )
|
|
|
|
|
{
|
|
|
|
|
GFXTextureObject *tex = stageDat.getTex( MFT_ToneMap );
|
|
|
|
|
if ( tex )
|
|
|
|
|
{
|
|
|
|
|
passData.mTexType[ texIndex ] = Material::ToneMapTex;
|
2014-04-17 15:44:49 +00:00
|
|
|
passData.mSamplerNames[ texIndex ] = "toneMap";
|
2012-09-19 15:15:01 +00:00
|
|
|
passData.mTexSlot[ texIndex++ ].texObject = tex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U32 TonemapFeatGLSL::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 VertLitGLSL::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 )
|
|
|
|
|
{
|
2015-01-19 19:56:02 +00:00
|
|
|
// 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 );
|
2015-01-19 19:56:02 +00:00
|
|
|
outColor->setName( "vertColor" );
|
|
|
|
|
outColor->setStructName( "OUT" );
|
|
|
|
|
outColor->setType( "vec4" );
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
output = new GenOp( " @ = @;\r\n", outColor, inColor );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
output = NULL; // Nothing we need to do.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VertLitGLSL::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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
vertColor->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
vertColor->setType( "vec4" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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( "vec4" );
|
|
|
|
|
LangElement *finalVertColorDecl = new DecOp( finalVertColor );
|
|
|
|
|
|
|
|
|
|
// Reverse the tonemap
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", finalVertColorDecl, vertColor ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// 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 ) )
|
2017-04-11 05:23:14 +00:00
|
|
|
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)
|
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
|
|
|
outColor = new GenOp( "vec4(@.rgb, 1.0)", rtLightingColor );
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
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
|
|
|
outColor = new GenOp( "vec4(@.rgb + @.rgb, 1.0)", rtLightingColor, outColor );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Output the color
|
|
|
|
|
if ( fd.features[MFT_LightbufferMRT] )
|
2014-04-17 15:44:49 +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( outColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) );
|
|
|
|
|
meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) );
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
|
|
|
|
meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, blendOp ) ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U32 VertLitGLSL::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 DetailFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
addOutDetailTexCoord( componentList,
|
|
|
|
|
meta,
|
|
|
|
|
fd.features[MFT_TexAnim] );
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DetailFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
// Get the detail texture coord.
|
2017-05-28 21:51:31 +00:00
|
|
|
Var *inTex = getInTexCoord( "detCoord", "vec2", componentList );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// create texture var
|
|
|
|
|
Var *detailMap = new Var;
|
|
|
|
|
detailMap->setType( "sampler2D" );
|
|
|
|
|
detailMap->setName( "detailMap" );
|
|
|
|
|
detailMap->uniform = true;
|
|
|
|
|
detailMap->sampler = true;
|
|
|
|
|
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
LangElement *statement = new GenOp( "( tex2D(@, @) * 2.0 ) - 1.0", detailMap, 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
|
|
|
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 DetailFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
res.numTex = 1;
|
|
|
|
|
res.numTexReg = 1;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DetailFeatGLSL::setTexData( Material::StageData &stageDat,
|
|
|
|
|
const MaterialFeatureData &fd,
|
|
|
|
|
RenderPassData &passData,
|
|
|
|
|
U32 &texIndex )
|
|
|
|
|
{
|
|
|
|
|
GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap );
|
|
|
|
|
if ( tex )
|
2014-04-17 15:44:49 +00:00
|
|
|
{
|
|
|
|
|
passData.mSamplerNames[texIndex] = "detailMap";
|
2012-09-19 15:15:01 +00:00
|
|
|
passData.mTexSlot[ texIndex++ ].texObject = tex;
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// Vertex position
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
void VertPositionGLSL::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 );
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
void VertPositionGLSL::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] );
|
|
|
|
|
Var *outPosition = connectComp->getElement( RT_POSITION );
|
|
|
|
|
outPosition->setName( "gl_Position" );
|
|
|
|
|
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
|
|
|
|
Var *modelview = getModelView( componentList, fd.features[MFT_UseInstancing], 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
|
|
|
meta->addStatement( new GenOp( " @ = tMul(@, vec4(@.xyz,1));\r\n",
|
2014-04-17 15:44:49 +00:00
|
|
|
outPosition, modelview, inPosition ) );
|
2018-11-18 12:36:16 +00:00
|
|
|
if (fd.materialFeatures[MFT_SkyBox])
|
|
|
|
|
{
|
|
|
|
|
meta->addStatement(new GenOp(" @ = @.xyww;\r\n", outPosition, outPosition));
|
|
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// Reflect Cubemap
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
void ReflectCubeFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
// search for vert normal
|
|
|
|
|
Var *inNormal = (Var*) LangElement::find( "normal" );
|
|
|
|
|
if ( !inNormal )
|
|
|
|
|
return;
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
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 );
|
2014-04-17 15:44:49 +00:00
|
|
|
outTex->setName( "texCoord" );
|
|
|
|
|
outTex->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outTex->setType( "vec2" );
|
|
|
|
|
|
|
|
|
|
// setup language elements to output incoming tex coords to output
|
|
|
|
|
meta->addStatement( new GenOp( " @ = @;\r\n", outTex, inTex ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create cubeTrans
|
2014-04-17 15:44:49 +00:00
|
|
|
bool useInstancing = fd.features[MFT_UseInstancing];
|
|
|
|
|
Var *cubeTrans = getObjTrans( componentList, useInstancing, meta );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// cube vert position
|
|
|
|
|
Var * cubeVertPos = new Var;
|
|
|
|
|
cubeVertPos->setName( "cubeVertPos" );
|
2014-04-17 15:44:49 +00:00
|
|
|
cubeVertPos->setType( "vec3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
LangElement *cubeVertPosDecl = new DecOp( cubeVertPos );
|
|
|
|
|
|
2014-12-15 17:28:17 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tMul( @, float4(@,1)).xyz;\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
cubeVertPosDecl, cubeTrans, LangElement::find( "position" ) ) );
|
|
|
|
|
|
|
|
|
|
// cube normal
|
|
|
|
|
Var * cubeNormal = new Var;
|
|
|
|
|
cubeNormal->setName( "cubeNormal" );
|
2014-04-17 15:44:49 +00:00
|
|
|
cubeNormal->setType( "vec3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
LangElement *cubeNormDecl = new DecOp( cubeNormal );
|
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( " @ = ( tMul( (@), vec4(@, 0) ) ).xyz;\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
cubeNormDecl, cubeTrans, inNormal ) );
|
|
|
|
|
|
2014-12-15 17:28:17 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = bool(length(@)) ? normalize(@) : @;\r\n",
|
|
|
|
|
cubeNormal, cubeNormal, cubeNormal, cubeNormal ) );
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// grab the eye position
|
|
|
|
|
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
|
|
|
|
|
if ( !eyePos )
|
|
|
|
|
{
|
|
|
|
|
eyePos = new Var( "eyePosWorld", "vec3" );
|
|
|
|
|
eyePos->uniform = true;
|
|
|
|
|
eyePos->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
// eye to vert
|
|
|
|
|
Var * eyeToVert = new Var;
|
|
|
|
|
eyeToVert->setName( "eyeToVert" );
|
2014-04-17 15:44:49 +00:00
|
|
|
eyeToVert->setType( "vec3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
LangElement *e2vDecl = new DecOp( eyeToVert );
|
|
|
|
|
|
2014-12-15 17:28:17 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = @ - @;\r\n",
|
|
|
|
|
e2vDecl, cubeVertPos, eyePos ) );
|
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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
reflectVec->setStructName( "OUT" );
|
|
|
|
|
reflectVec->setType( "vec3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " @ = reflect(@, @);\r\n", reflectVec, eyeToVert, cubeNormal ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReflectCubeFeatGLSL::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] &&
|
|
|
|
|
!fd.features[MFT_NormalMap] )
|
|
|
|
|
{
|
|
|
|
|
if( fd.materialFeatures[MFT_DiffuseMap] ||
|
|
|
|
|
fd.materialFeatures[MFT_NormalMap] )
|
|
|
|
|
{
|
|
|
|
|
// grab connector texcoord register
|
2017-05-28 21:51:31 +00:00
|
|
|
Var *inTex = getInTexCoord( "texCoord", "vec2", componentList );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// create texture var
|
|
|
|
|
Var *newMap = new Var;
|
|
|
|
|
newMap->setType( "sampler2D" );
|
|
|
|
|
newMap->setName( "glossMap" );
|
|
|
|
|
newMap->uniform = true;
|
|
|
|
|
newMap->sampler = true;
|
|
|
|
|
newMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
|
|
|
|
// create sample color
|
|
|
|
|
Var *color = new Var;
|
|
|
|
|
color->setType( "vec4" );
|
|
|
|
|
color->setName( "diffuseColor" );
|
|
|
|
|
LangElement *colorDecl = new DecOp( color );
|
|
|
|
|
|
|
|
|
|
glossColor = color;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tex2D( @, @ );\r\n", colorDecl, newMap, inTex ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-09-16 01:19:57 +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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
reflectVec->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
reflectVec->setType( "vec3" );
|
|
|
|
|
|
|
|
|
|
// create cubemap var
|
|
|
|
|
Var *cubeMap = new Var;
|
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
|
|
|
cubeMap->setType( "samplerCube" );
|
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
|
|
|
|
|
|
2018-09-16 01:19:57 +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) );
|
2018-09-16 01:19:57 +00:00
|
|
|
Var *smoothness = (Var*)LangElement::find("smoothness");
|
|
|
|
|
if (smoothness) //try to grab smoothness directly
|
|
|
|
|
texCube = new GenOp("textureLod( @, @, min((1.0 - @)*@ + 1.0, @))", cubeMap, reflectVec, smoothness, cubeMips, cubeMips);
|
|
|
|
|
else if (glossColor) //failing that, try and find color data
|
|
|
|
|
texCube = new GenOp("textureLod( @, @, min((1.0 - @.b)*@ + 1.0, @))", cubeMap, reflectVec, glossColor, cubeMips, cubeMips);
|
|
|
|
|
else //failing *that*, just draw the cubemap
|
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
|
|
|
texCube = new GenOp("texture( @, @)", cubeMap, reflectVec);
|
|
|
|
|
|
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 )
|
2015-01-20 16:02:56 +00:00
|
|
|
lerpVal = new GenOp( "vec4( saturate( @ ) ).xxxx", attn );
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
|
|
|
|
blendOp = Material::Mul;
|
|
|
|
|
}
|
2018-09-16 01:19:57 +00:00
|
|
|
|
|
|
|
|
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])
|
|
|
|
|
{
|
2018-09-16 01:19:57 +00:00
|
|
|
//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
|
2018-09-16 01:19:57 +00:00
|
|
|
{
|
|
|
|
|
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", "vec3");
|
|
|
|
|
Var *envColor = new Var("envColor", "vec3");
|
|
|
|
|
meta->addStatement(new GenOp(" @ = @.rgb - (@.rgb * @);\r\n", new DecOp(dColor), targ, targ, metalness));
|
|
|
|
|
meta->addStatement(new GenOp(" @ = @.rgb*(@).rgb;\r\n", new DecOp(envColor), targ, texCube));
|
|
|
|
|
}
|
|
|
|
|
else if (lerpVal)
|
|
|
|
|
meta->addStatement(new GenOp(" @ *= vec4(@.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 ReflectCubeFeatGLSL::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 ReflectCubeFeatGLSL::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 );
|
2014-04-17 15:44:49 +00:00
|
|
|
if ( tex && stageFeatures.features[MFT_DiffuseMap] )
|
|
|
|
|
{
|
|
|
|
|
passData.mSamplerNames[ texIndex ] = "diffuseMap";
|
2012-09-19 15:15:01 +00:00
|
|
|
passData.mTexSlot[ texIndex++ ].texObject = tex;
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tex = stageDat.getTex( MFT_NormalMap );
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
if ( tex && stageFeatures.features[ MFT_NormalMap ] )
|
|
|
|
|
{
|
|
|
|
|
passData.mSamplerNames[ texIndex ] = "bumpMap";
|
2012-09-19 15:15:01 +00:00
|
|
|
passData.mTexSlot[ texIndex++ ].texObject = tex;
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( stageDat.getCubemap() )
|
|
|
|
|
{
|
|
|
|
|
passData.mCubeMap = stageDat.getCubemap();
|
2014-04-17 15:44:49 +00:00
|
|
|
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
|
2014-04-17 15:44:49 +00:00
|
|
|
passData.mSamplerNames[texIndex] = "cubeMap";
|
2012-09-19 15:15:01 +00:00
|
|
|
passData.mTexType[texIndex++] = Material::SGCube;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// RTLighting
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
RTLightingFeatGLSL::RTLightingFeatGLSL()
|
2017-07-24 05:40:27 +00:00
|
|
|
: mDep(ShaderGen::smCommonShaderPath + String("/gl/lighting.glsl" ))
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
|
|
|
|
addDependency( &mDep );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTLightingFeatGLSL::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] )
|
|
|
|
|
{
|
|
|
|
|
if ( !fd.features[MFT_NormalMap] )
|
|
|
|
|
{
|
|
|
|
|
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
|
|
|
|
|
if ( !eyePos )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
eyePos = new Var( "eyePosWorld", "vec3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
eyePos->uniform = true;
|
|
|
|
|
eyePos->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var *inPosition = (Var*)LangElement::find( "position" );
|
|
|
|
|
|
|
|
|
|
Var *outNormal = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
outNormal->setName( "wsNormal" );
|
|
|
|
|
outNormal->setStructName( "OUT" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outNormal->setType( "vec3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Transform the normal to world space.
|
|
|
|
|
meta->addStatement( new GenOp( " @ = normalize( @ - @.xyz );\r\n", outNormal, eyePos, inPosition ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find the incoming vertex normal.
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *inNormal = (Var*)LangElement::find( "normal" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Skip out on realtime lighting if we don't have a normal
|
|
|
|
|
// or we're doing some sort of baked lighting.
|
|
|
|
|
if ( !inNormal ||
|
|
|
|
|
fd.features[MFT_LightMap] ||
|
|
|
|
|
fd.features[MFT_ToneMap] ||
|
|
|
|
|
fd.features[MFT_VertLit] )
|
2014-04-17 15:44:49 +00:00
|
|
|
return;
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// 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] )
|
|
|
|
|
{
|
|
|
|
|
Var *outNormal = connectComp->getElement( RT_TEXCOORD );
|
2014-04-17 15:44:49 +00:00
|
|
|
outNormal->setName( "wsNormal" );
|
|
|
|
|
outNormal->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outNormal->setType( "vec3" );
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
// Get the transform to world space.
|
|
|
|
|
Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Transform the normal to world space.
|
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( " @ = tMul( @, vec4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTLightingFeatGLSL::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;
|
|
|
|
|
|
|
|
|
|
// Look for a wsNormal or grab it from the connector.
|
|
|
|
|
Var *wsNormal = (Var*)LangElement::find( "wsNormal" );
|
|
|
|
|
if ( !wsNormal )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
wsNormal = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
wsNormal->setName( "wsNormal" );
|
|
|
|
|
wsNormal->setStructName( "IN" );
|
|
|
|
|
wsNormal->setType( "vec3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// If we loaded the normal its our responsibility
|
2012-09-19 15:15:01 +00:00
|
|
|
// to normalize it... the interpolators won't.
|
2014-04-17 15:44:49 +00:00
|
|
|
//
|
|
|
|
|
// Note we cast to half here to get partial precision
|
|
|
|
|
// optimized code which is an acceptable loss of
|
|
|
|
|
// precision for normals and performs much better
|
|
|
|
|
// on older Geforce cards.
|
|
|
|
|
//
|
|
|
|
|
meta->addStatement( new GenOp( " @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// Now the wsPosition and wsView.
|
|
|
|
|
Var *wsPosition = getInWsPosition( componentList );
|
|
|
|
|
Var *wsView = getWsView( wsPosition, meta );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Create temporaries to hold results of lighting.
|
|
|
|
|
Var *rtShading = new Var( "rtShading", "vec4" );
|
|
|
|
|
Var *specular = new Var( "specular", "vec4" );
|
|
|
|
|
meta->addStatement( new GenOp( " @; @;\r\n",
|
|
|
|
|
new DecOp( rtShading ), new DecOp( specular ) ) );
|
|
|
|
|
|
|
|
|
|
// Look for a light mask generated from a previous
|
|
|
|
|
// feature (this is done for BL terrain lightmaps).
|
2014-04-17 15:44:49 +00:00
|
|
|
LangElement *lightMask = LangElement::find( "lightMask" );
|
|
|
|
|
if ( !lightMask )
|
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
|
|
|
lightMask = new GenOp( "vec4( 1, 1, 1, 1 )" );
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
// Get all the light constants.
|
|
|
|
|
Var *inLightPos = new Var( "inLightPos", "vec4" );
|
|
|
|
|
inLightPos->uniform = true;
|
|
|
|
|
inLightPos->arraySize = 3;
|
|
|
|
|
inLightPos->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var *inLightInvRadiusSq = new Var( "inLightInvRadiusSq", "vec4" );
|
|
|
|
|
inLightInvRadiusSq->uniform = true;
|
|
|
|
|
inLightInvRadiusSq->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var *inLightColor = new Var( "inLightColor", "vec4" );
|
|
|
|
|
inLightColor->uniform = true;
|
|
|
|
|
inLightColor->arraySize = 4;
|
|
|
|
|
inLightColor->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var *inLightSpotDir = new Var( "inLightSpotDir", "vec4" );
|
|
|
|
|
inLightSpotDir->uniform = true;
|
|
|
|
|
inLightSpotDir->arraySize = 3;
|
|
|
|
|
inLightSpotDir->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var *inLightSpotAngle = new Var( "inLightSpotAngle", "vec4" );
|
|
|
|
|
inLightSpotAngle->uniform = true;
|
|
|
|
|
inLightSpotAngle->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var *lightSpotFalloff = new Var( "inLightSpotFalloff", "vec4" );
|
|
|
|
|
lightSpotFalloff->uniform = true;
|
|
|
|
|
lightSpotFalloff->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
2018-09-16 01:19:57 +00:00
|
|
|
Var *smoothness = (Var*)LangElement::find("smoothness");
|
|
|
|
|
if (!fd.features[MFT_SpecularMap])
|
|
|
|
|
{
|
|
|
|
|
if (!smoothness)
|
|
|
|
|
{
|
|
|
|
|
smoothness = new Var("smoothness", "float");
|
|
|
|
|
smoothness->uniform = true;
|
|
|
|
|
smoothness->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2018-09-16 01:19:57 +00:00
|
|
|
Var *metalness = (Var*)LangElement::find("metalness");
|
|
|
|
|
if (!fd.features[MFT_SpecularMap])
|
2014-04-17 15:44:49 +00:00
|
|
|
{
|
2018-09-16 01:19:57 +00:00
|
|
|
if (!metalness)
|
|
|
|
|
{
|
|
|
|
|
metalness = new Var("metalness", "float");
|
|
|
|
|
metalness->uniform = true;
|
|
|
|
|
metalness->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
}
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
2018-09-16 01:19:57 +00:00
|
|
|
Var *albedo = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *ambient = new Var( "ambient", "vec4" );
|
|
|
|
|
ambient->uniform = true;
|
|
|
|
|
ambient->constSortPos = cspPass;
|
|
|
|
|
|
|
|
|
|
// Calculate the diffuse shading and specular powers.
|
|
|
|
|
meta->addStatement( new GenOp( " compute4Lights( @, @, @, @,\r\n"
|
2018-09-16 01:19:57 +00:00
|
|
|
" @, @, @, @, @, @, @, @, @,\r\n"
|
2014-04-17 15:44:49 +00:00
|
|
|
" @, @ );\r\n",
|
|
|
|
|
wsView, wsPosition, wsNormal, lightMask,
|
2018-09-16 01:19:57 +00:00
|
|
|
inLightPos, inLightInvRadiusSq, inLightColor, inLightSpotDir, inLightSpotAngle, lightSpotFalloff, smoothness, metalness, albedo,
|
2014-04-17 15:44:49 +00:00
|
|
|
rtShading, specular ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Apply the lighting to the 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
|
|
|
LangElement *lighting = new GenOp( "vec4( @.rgb + @.rgb, 1 )", rtShading, ambient );
|
2012-09-19 15:15:01 +00:00
|
|
|
meta->addStatement( new GenOp( " @;\r\n", assignColor( lighting, Material::Mul ) ) );
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources RTLightingFeatGLSL::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
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
FogFeatGLSL::FogFeatGLSL()
|
2017-07-24 05:40:27 +00:00
|
|
|
: mFogDep(ShaderGen::smCommonShaderPath + String("/gl/torque.glsl" ))
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
|
|
|
|
addDependency( &mFogDep );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FogFeatGLSL::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", "vec3" );
|
|
|
|
|
eyePos->uniform = true;
|
|
|
|
|
eyePos->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var *fogData = new Var( "fogData", "vec3" );
|
|
|
|
|
fogData->uniform = true;
|
|
|
|
|
fogData->constSortPos = cspPass;
|
|
|
|
|
|
|
|
|
|
Var *wsPosition = new Var( "fogPos", "vec3" );
|
|
|
|
|
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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
fogAmount->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
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 FogFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
|
|
|
|
Var *fogColor = new Var;
|
|
|
|
|
fogColor->setType( "vec4" );
|
|
|
|
|
fogColor->setName( "fogColor" );
|
|
|
|
|
fogColor->uniform = true;
|
|
|
|
|
fogColor->constSortPos = cspPass;
|
|
|
|
|
|
|
|
|
|
// Get the out color.
|
|
|
|
|
Var *color = (Var*) LangElement::find( "col" );
|
|
|
|
|
if ( !color )
|
|
|
|
|
{
|
|
|
|
|
color = new Var;
|
|
|
|
|
color->setType( "vec4" );
|
|
|
|
|
color->setName( "col" );
|
2014-11-30 04:32:40 +00:00
|
|
|
color->setStructName("OUT");
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
fogAmount->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
fogAmount->setType( "float" );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Var *wsPosition = getInWsPosition( componentList );
|
|
|
|
|
|
|
|
|
|
// grab the eye position
|
|
|
|
|
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
|
|
|
|
|
if ( !eyePos )
|
|
|
|
|
{
|
|
|
|
|
eyePos = new Var( "eyePosWorld", "vec3" );
|
|
|
|
|
eyePos->uniform = true;
|
|
|
|
|
eyePos->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var *fogData = new Var( "fogData", "vec3" );
|
|
|
|
|
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.
|
2014-04-17 15:44:49 +00:00
|
|
|
LangElement *fogLerp = new GenOp( "lerp( @.rgb, @.rgb, @ )", fogColor, color, fogAmount );
|
2012-09-19 15:15:01 +00:00
|
|
|
meta->addStatement( new GenOp( " @.rgb = @;\r\n", color, fogLerp ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources FogFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
res.numTexReg = 1;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// Visibility
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
VisibilityFeatGLSL::VisibilityFeatGLSL()
|
2017-07-24 05:40:27 +00:00
|
|
|
: mTorqueDep(ShaderGen::smCommonShaderPath + String("/gl/torque.glsl" ))
|
2014-04-17 15:44:49 +00:00
|
|
|
{
|
|
|
|
|
addDependency( &mTorqueDep );
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
void VisibilityFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
output = meta;
|
|
|
|
|
|
|
|
|
|
if ( fd.features[ MFT_UseInstancing ] )
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
// 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 );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = @; // Instancing!\r\n", outVisibility, instVisibility ) );
|
|
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
if ( fd.features[ MFT_IsTranslucent ] )
|
|
|
|
|
return;
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
addOutVpos( meta, componentList );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VisibilityFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
2014-04-17 15:44:49 +00:00
|
|
|
{
|
|
|
|
|
// 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 );
|
2014-04-17 15:44:49 +00:00
|
|
|
else
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
visibility = (Var*)LangElement::find( "visibility" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
if ( !visibility )
|
|
|
|
|
{
|
|
|
|
|
visibility = new Var();
|
|
|
|
|
visibility->setType( "float" );
|
|
|
|
|
visibility->setName( "visibility" );
|
|
|
|
|
visibility->uniform = true;
|
|
|
|
|
visibility->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MultiLine* meta = new MultiLine;
|
|
|
|
|
output = meta;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// Translucent objects do a simple alpha fade.
|
|
|
|
|
if ( fd.features[ MFT_IsTranslucent ] )
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *color = (Var*) LangElement::find( "col" );
|
|
|
|
|
meta->addStatement( new GenOp( " @.a *= @;\r\n", color, visibility ) );
|
|
|
|
|
return;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// Everything else does a fizzle.
|
|
|
|
|
Var *vPos = getInVpos( meta, componentList );
|
|
|
|
|
meta->addStatement( new GenOp( " fizzle( @, @ );\r\n", vPos, visibility ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources VisibilityFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// TODO: Fix for instancing.
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
if ( !fd.features[ MFT_IsTranslucent ] )
|
|
|
|
|
res.numTexReg = 1;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// AlphaTest
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
void AlphaTestGLSL::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 &&
|
|
|
|
|
!fd.features[ MFT_EyeSpaceDepthOut ] &&
|
|
|
|
|
!fd.features[ MFT_DepthOut ] )
|
|
|
|
|
{
|
|
|
|
|
output = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we don't have a color var then we cannot do an alpha test.
|
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
|
|
|
Var *color = (Var*)LangElement::find( "col1" );
|
|
|
|
|
if ( !color )
|
|
|
|
|
color = (Var*)LangElement::find("col");
|
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.
|
2014-04-17 15:44:49 +00:00
|
|
|
output = new GenOp( " clip( @.a - @ );\r\n", color, alphaTestVal );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// GlowMask
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
void GlowMaskGLSL::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( "col" );
|
|
|
|
|
if ( color )
|
2014-11-08 16:41:17 +00:00
|
|
|
output = new GenOp( " @.rgb = vec3(0);\r\n", color );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
//****************************************************************************
|
|
|
|
|
// RenderTargetZero
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
void RenderTargetZeroGLSL::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
|
2014-11-27 18:07:01 +00:00
|
|
|
output = new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(0.00001)" ), Material::None, NULL, mOutputTargetMask ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// HDR Output
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
HDROutGLSL::HDROutGLSL()
|
2017-07-24 05:40:27 +00:00
|
|
|
: mTorqueDep(ShaderGen::smCommonShaderPath + String("/gl/torque.glsl" ))
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
|
|
|
|
addDependency( &mTorqueDep );
|
|
|
|
|
}
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
void HDROutGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
// Let the helper function do the work.
|
|
|
|
|
Var *color = (Var*)LangElement::find( "col" );
|
|
|
|
|
if ( color )
|
|
|
|
|
output = new GenOp( " @ = hdrEncode( @ );\r\n", color, color );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// FoliageFeatureGLSL
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
#include "T3D/fx/groundCover.h"
|
|
|
|
|
|
|
|
|
|
FoliageFeatureGLSL::FoliageFeatureGLSL()
|
2017-07-24 05:40:27 +00:00
|
|
|
: mDep(ShaderGen::smCommonShaderPath + String("/gl/foliage.glsl" ))
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
|
|
|
|
addDependency( &mDep );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FoliageFeatureGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
// Get the input variables we need.
|
|
|
|
|
|
|
|
|
|
Var *inPosition = (Var*)LangElement::find( "inPosition" );
|
2014-04-17 15:44:49 +00:00
|
|
|
if ( !inPosition )
|
|
|
|
|
inPosition = (Var*)LangElement::find( "position" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
Var *inColor = (Var*)LangElement::find( "diffuse" );
|
|
|
|
|
|
|
|
|
|
Var *inParams = (Var*)LangElement::find( "texCoord" );
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
MultiLine *meta = new MultiLine;
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *normal = (Var*)LangElement::find( "normal" );
|
|
|
|
|
AssertFatal( normal, "FoliageFeatureGLSL requires vert normal!" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
Var *tangent = new Var;
|
|
|
|
|
tangent->setType( "vec3" );
|
|
|
|
|
tangent->setName( "T" );
|
|
|
|
|
LangElement *tangentDec = new DecOp( tangent );
|
|
|
|
|
meta->addStatement( new GenOp( " @;\n", tangentDec ) );
|
|
|
|
|
|
|
|
|
|
// 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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
fade->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
fade->setType( "float" );
|
|
|
|
|
|
|
|
|
|
// grab the eye position
|
|
|
|
|
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
|
|
|
|
|
if ( !eyePos )
|
|
|
|
|
{
|
|
|
|
|
eyePos = new Var( "eyePosWorld", "vec3" );
|
|
|
|
|
eyePos->uniform = true;
|
|
|
|
|
eyePos->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// All actual work is offloaded to this method.
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " foliageProcessVert( @, @, @, @, @, @ );\r\n", inPosition, inColor, inParams, normal, tangent, eyePos ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Assign to foliageFade. InColor.a was set to the correct value inside foliageProcessVert.
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = @.a;\r\n", fade, inColor ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FoliageFeatureGLSL::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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
fade->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
fade->setType( "float" );
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
// 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;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FoliageFeatureGLSL::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 );
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
ShaderFeatureConstHandles* FoliageFeatureGLSL::createConstHandles( GFXShader *shader, SimObject *userObject )
|
|
|
|
|
{
|
|
|
|
|
GroundCover *gcover = dynamic_cast< GroundCover* >( userObject );
|
|
|
|
|
AssertFatal( gcover != NULL, "FoliageFeatureGLSL::createConstHandles - userObject was not valid!" );
|
|
|
|
|
|
|
|
|
|
GroundCoverShaderConstHandles *handles = new GroundCoverShaderConstHandles();
|
|
|
|
|
handles->mGroundCover = gcover;
|
|
|
|
|
|
|
|
|
|
handles->init( shader );
|
|
|
|
|
|
|
|
|
|
return handles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ParticleNormalFeatureGLSL::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( "vec3" );
|
|
|
|
|
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]
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement(new GenOp(" @ = float3(0.0, -0.97, 0.14);\r\n", new DecOp(normal)));
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var *T = (Var*) LangElement::find( "T" );
|
|
|
|
|
if(T == NULL)
|
|
|
|
|
{
|
|
|
|
|
T = new Var;
|
|
|
|
|
T->setType( "vec3" );
|
|
|
|
|
T->setName( "T" );
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement(new GenOp(" @ = float3(0.0, 0.0, -1.0);\r\n", new DecOp(T)));
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// ImposterVertFeatureGLSL
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
ImposterVertFeatureGLSL::ImposterVertFeatureGLSL()
|
2017-07-24 05:40:27 +00:00
|
|
|
: mDep(ShaderGen::smCommonShaderPath + String("/gl/imposter.glsl" ))
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
|
|
|
|
addDependency( &mDep );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImposterVertFeatureGLSL::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( "vec4" );
|
|
|
|
|
imposterLimits->setName( "imposterLimits" );
|
|
|
|
|
imposterLimits->uniform = true;
|
|
|
|
|
imposterLimits->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var *imposterUVs = new Var;
|
|
|
|
|
imposterUVs->setType( "vec4" );
|
|
|
|
|
imposterUVs->setName( "imposterUVs" );
|
2014-04-17 15:44:49 +00:00
|
|
|
imposterUVs->arraySize = 64; // See imposter.glsl
|
2012-09-19 15:15:01 +00:00
|
|
|
imposterUVs->uniform = true;
|
|
|
|
|
imposterUVs->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var *eyePos = (Var*)LangElement::find( "eyePosWorld" );
|
|
|
|
|
if ( !eyePos )
|
|
|
|
|
{
|
|
|
|
|
eyePos = new Var( "eyePosWorld", "vec3" );
|
|
|
|
|
eyePos->uniform = true;
|
|
|
|
|
eyePos->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Declare the outputs from this feature.
|
|
|
|
|
Var *outInPosition = new Var;
|
|
|
|
|
outInPosition->setType( "vec3" );
|
|
|
|
|
outInPosition->setName( "inPosition" );
|
|
|
|
|
meta->addStatement( new GenOp( " @;\r\n", new DecOp( outInPosition ) ) );
|
|
|
|
|
|
|
|
|
|
Var *outTexCoord = new Var;
|
|
|
|
|
outTexCoord->setType( "vec2" );
|
|
|
|
|
outTexCoord->setName( "texCoord" );
|
|
|
|
|
meta->addStatement( new GenOp( " @;\r\n", new DecOp( outTexCoord ) ) );
|
|
|
|
|
|
|
|
|
|
Var *outWorldToTangent = new Var;
|
2014-04-17 15:44:49 +00:00
|
|
|
outWorldToTangent->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outFade->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
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, int(@.w), @.x * length(@), normalize(@), normalize(@), int(@.y), int(@.x), @.z, bool(@.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( "vec3" );
|
|
|
|
|
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;
|
2014-04-17 15:44:49 +00:00
|
|
|
viewToTangent->setType( "float3x3" );
|
2012-09-19 15:15:01 +00:00
|
|
|
viewToTangent->setName( "viewToTangent" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = @;\r\n", new DecOp( viewToTangent ), outWorldToTangent ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImposterVertFeatureGLSL::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" );
|
2014-04-17 15:44:49 +00:00
|
|
|
fade->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
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.
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImposterVertFeatureGLSL::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 );
|
2015-01-10 19:41:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// HardwareSkinningFeatureGLSL
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
void HardwareSkinningFeatureGLSL::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", "vec3");
|
|
|
|
|
Var* poseNormal = new Var("poseNormal", "vec3");
|
|
|
|
|
Var* poseMat = new Var("poseMat", "mat4x3");
|
|
|
|
|
Var* poseRotMat = new Var("poseRotMat", "mat3x3");
|
|
|
|
|
Var* nodeTransforms = (Var*)LangElement::find("nodeTransforms");
|
|
|
|
|
|
|
|
|
|
if (!nodeTransforms)
|
|
|
|
|
{
|
|
|
|
|
nodeTransforms = new Var("nodeTransforms", "mat4x3");
|
|
|
|
|
nodeTransforms->uniform = true;
|
|
|
|
|
nodeTransforms->arraySize = TSShape::smMaxSkinBones;
|
|
|
|
|
nodeTransforms->constSortPos = cspPrimitive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U32 numIndices = mVertexFormat->getNumBlendIndices();
|
|
|
|
|
meta->addStatement(new GenOp(" @ = vec3(0.0);\r\n", new DecOp(posePos)));
|
|
|
|
|
meta->addStatement(new GenOp(" @ = vec3(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("vBlendIndex%d", i));
|
|
|
|
|
LangElement* inWeights = (Var*)LangElement::find(String::ToString("vBlendWeight%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(" @ = mat3x3(@);\r\n", poseRotMat, poseMat));
|
|
|
|
|
meta->addStatement(new GenOp(" @ += (@ * vec4(@, 1)).xyz * poseWeight;\r\n", posePos, poseMat, inPosition));
|
|
|
|
|
meta->addStatement(new GenOp(" @ += ((@ * @) * poseWeight);\r\n", poseNormal, poseRotMat, inNormal));
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-04-28 11:24:19 +00:00
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
// ReflectionProbeFeatHLSL
|
|
|
|
|
//****************************************************************************
|
|
|
|
|
|
|
|
|
|
ReflectionProbeFeatGLSL::ReflectionProbeFeatGLSL()
|
|
|
|
|
: mDep(ShaderGen::smCommonShaderPath + String("/gl/lighting.glsl"))
|
|
|
|
|
{
|
|
|
|
|
addDependency(&mDep);
|
|
|
|
|
}
|
|
|
|
|
void ReflectionProbeFeatGLSL::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 * wsView = getWsView(wsPosition, meta);
|
|
|
|
|
|
|
|
|
|
Var * albedo = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
|
|
|
|
|
|
|
|
|
|
//Reflection Probe WIP
|
|
|
|
|
U32 MAX_FORWARD_PROBES = 4;
|
|
|
|
|
|
|
|
|
|
Var * numProbes = new Var("numProbes", "float");
|
|
|
|
|
numProbes->uniform = true;
|
|
|
|
|
numProbes->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var * cubeMips = new Var("cubeMips", "float");
|
|
|
|
|
cubeMips->uniform = true;
|
|
|
|
|
cubeMips->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var * hasSkylight = new Var("hasSkylight", "float");
|
|
|
|
|
hasSkylight->uniform = true;
|
|
|
|
|
hasSkylight->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var * inProbePosArray = new Var("inProbePosArray", "vec4");
|
|
|
|
|
inProbePosArray->arraySize = MAX_FORWARD_PROBES;
|
|
|
|
|
inProbePosArray->uniform = true;
|
|
|
|
|
inProbePosArray->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var * inRefPosArray = new Var("inRefPosArray", "vec4");
|
|
|
|
|
inRefPosArray->arraySize = MAX_FORWARD_PROBES;
|
|
|
|
|
inRefPosArray->uniform = true;
|
|
|
|
|
inRefPosArray->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var * bbMinArray = new Var("inProbeBoxMin", "vec4");
|
|
|
|
|
bbMinArray->arraySize = MAX_FORWARD_PROBES;
|
|
|
|
|
bbMinArray->uniform = true;
|
|
|
|
|
bbMinArray->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var * bbMaxArray = new Var("inProbeBoxMax", "vec4");
|
|
|
|
|
bbMaxArray->arraySize = MAX_FORWARD_PROBES;
|
|
|
|
|
bbMaxArray->uniform = true;
|
|
|
|
|
bbMaxArray->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var * probeConfigData = new Var("probeConfigData", "vec4");
|
|
|
|
|
probeConfigData->arraySize = MAX_FORWARD_PROBES;
|
|
|
|
|
probeConfigData->uniform = true;
|
|
|
|
|
probeConfigData->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
Var * worldToObjArray = new Var("worldToObjArray", "mat4x4");
|
|
|
|
|
worldToObjArray->arraySize = MAX_FORWARD_PROBES;
|
|
|
|
|
worldToObjArray->uniform = true;
|
|
|
|
|
worldToObjArray->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
// create texture var
|
|
|
|
|
Var* BRDFTexture = new Var;
|
|
|
|
|
BRDFTexture->setType("sampler2D");
|
|
|
|
|
BRDFTexture->setName("BRDFTexture");
|
|
|
|
|
BRDFTexture->uniform = true;
|
|
|
|
|
BRDFTexture->sampler = true;
|
|
|
|
|
BRDFTexture->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
|
|
|
|
Var * specularCubemapAR = new Var("specularCubemapAR", "samplerCubeArray");
|
|
|
|
|
specularCubemapAR->uniform = true;
|
|
|
|
|
specularCubemapAR->sampler = true;
|
|
|
|
|
specularCubemapAR->constNum = Var::getTexUnitNum();
|
|
|
|
|
|
|
|
|
|
Var * irradianceCubemapAR = new Var("irradianceCubemapAR", "samplerCubeArray");
|
|
|
|
|
irradianceCubemapAR->uniform = true;
|
|
|
|
|
irradianceCubemapAR->sampler = true;
|
|
|
|
|
irradianceCubemapAR->constNum = Var::getTexUnitNum();
|
|
|
|
|
|
|
|
|
|
Var * skylightSpecularMap = new Var("skylightSpecularMap", "samplerCube");
|
|
|
|
|
skylightSpecularMap->uniform = true;
|
|
|
|
|
skylightSpecularMap->sampler = true;
|
|
|
|
|
skylightSpecularMap->constNum = Var::getTexUnitNum();
|
|
|
|
|
|
|
|
|
|
Var * skylightIrradMap = new Var("skylightIrradMap", "samplerCube");
|
|
|
|
|
skylightIrradMap->uniform = true;
|
|
|
|
|
skylightIrradMap->sampler = true;
|
|
|
|
|
skylightIrradMap->constNum = Var::getTexUnitNum();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Var * inTex = getInTexCoord("texCoord", "vec2", componentList);
|
|
|
|
|
if (!inTex)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Var * diffuseColor = (Var*)LangElement::find("diffuseColor");
|
|
|
|
|
if (!diffuseColor)
|
|
|
|
|
{
|
|
|
|
|
diffuseColor = new Var;
|
|
|
|
|
diffuseColor->setType("vec4");
|
|
|
|
|
diffuseColor->setName("diffuseColor");
|
|
|
|
|
LangElement* colorDecl = new DecOp(diffuseColor);
|
|
|
|
|
meta->addStatement(new GenOp(" @ = vec4(1.0,1.0,1.0,1.0);\r\n", colorDecl)); //default to flat white
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-30 00:40:22 +00:00
|
|
|
Var* matinfo = (Var*)LangElement::find("PBRConfig");
|
2019-04-28 11:24:19 +00:00
|
|
|
if (!matinfo)
|
|
|
|
|
{
|
|
|
|
|
Var* metalness = (Var*)LangElement::find("metalness");
|
|
|
|
|
if (!metalness)
|
|
|
|
|
{
|
|
|
|
|
metalness = new Var("metalness", "float");
|
|
|
|
|
metalness->uniform = true;
|
|
|
|
|
metalness->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* smoothness = (Var*)LangElement::find("smoothness");
|
|
|
|
|
if (!smoothness)
|
|
|
|
|
{
|
|
|
|
|
smoothness = new Var("smoothness", "float");
|
|
|
|
|
smoothness->uniform = true;
|
|
|
|
|
smoothness->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-30 00:40:22 +00:00
|
|
|
matinfo = new Var("PBRConfig", "vec4");
|
2019-04-28 11:24:19 +00:00
|
|
|
LangElement* colorDecl = new DecOp(matinfo);
|
|
|
|
|
meta->addStatement(new GenOp(" @ = vec4(0.0,1.0,@,@);\r\n", colorDecl, smoothness, metalness)); //reconstruct matinfo, no ao darkening
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* bumpNormal = (Var*)LangElement::find("bumpNormal");
|
|
|
|
|
if (!bumpNormal)
|
|
|
|
|
{
|
|
|
|
|
bumpNormal = new Var("bumpNormal", "vec4");
|
|
|
|
|
LangElement* colorDecl = new DecOp(bumpNormal);
|
|
|
|
|
meta->addStatement(new GenOp(" @ = vec4(1.0,0.0,0.0,0.0);\r\n", colorDecl)); //default to identity normal
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* wsEyePos = (Var*)LangElement::find("eyePosWorld");
|
|
|
|
|
|
|
|
|
|
Var* worldToCamera = (Var*)LangElement::find("worldToCamera");
|
|
|
|
|
if (!worldToCamera)
|
|
|
|
|
{
|
|
|
|
|
worldToCamera = new Var;
|
|
|
|
|
worldToCamera->setType("mat4x4");
|
|
|
|
|
worldToCamera->setName("worldToCamera");
|
|
|
|
|
worldToCamera->uniform = true;
|
|
|
|
|
worldToCamera->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Reflection vec
|
|
|
|
|
Var* surface = new Var("surface", "Surface");
|
|
|
|
|
meta->addStatement(new GenOp(" @ = createForwardSurface(@,@,@,@,@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, bumpNormal, matinfo,
|
|
|
|
|
inTex, wsPosition, wsEyePos, wsView, worldToCamera));
|
|
|
|
|
String computeForwardProbes = String::String(" @.rgb += computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
|
|
|
|
|
computeForwardProbes += String::String("@,@,\r\n\t\t");
|
|
|
|
|
computeForwardProbes += String::String("@, @, \r\n\t\t");
|
|
|
|
|
computeForwardProbes += String::String("@,@).rgb; \r\n");
|
|
|
|
|
|
|
|
|
|
meta->addStatement(new GenOp(computeForwardProbes.c_str(), albedo, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, bbMinArray, bbMaxArray, inRefPosArray,
|
|
|
|
|
hasSkylight, BRDFTexture,
|
|
|
|
|
skylightIrradMap, skylightSpecularMap,
|
|
|
|
|
irradianceCubemapAR, specularCubemapAR));
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources ReflectionProbeFeatGLSL::getResources(const MaterialFeatureData& fd)
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
|
|
|
|
|
res.numTex = 5;
|
|
|
|
|
res.numTexReg = 5;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReflectionProbeFeatGLSL::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;
|
|
|
|
|
passData.mSamplerNames[texIndex] = "skylightSpecularMap";
|
|
|
|
|
passData.mTexType[texIndex++] = Material::SGCube;
|
|
|
|
|
passData.mSamplerNames[texIndex] = "skylightIrradMap";
|
|
|
|
|
passData.mTexType[texIndex++] = Material::SGCube;
|
|
|
|
|
}
|
|
|
|
|
}
|