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 "terrain/glsl/terrFeatureGLSL.h"
|
|
|
|
|
|
|
|
|
|
#include "terrain/terrFeatureTypes.h"
|
|
|
|
|
#include "materials/materialFeatureTypes.h"
|
|
|
|
|
#include "materials/materialFeatureData.h"
|
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
|
|
|
#include "materials/processedMaterial.h"
|
2012-09-19 15:15:01 +00:00
|
|
|
#include "gfx/gfxDevice.h"
|
|
|
|
|
#include "shaderGen/langElement.h"
|
|
|
|
|
#include "shaderGen/shaderOp.h"
|
|
|
|
|
#include "shaderGen/featureMgr.h"
|
2014-04-17 15:44:49 +00:00
|
|
|
#include "shaderGen/shaderGen.h"
|
2012-09-19 15:15:01 +00:00
|
|
|
#include "core/module.h"
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
void register_glsl_shader_features_for_terrain(GFXAdapterType type)
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
if(type != OpenGL)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatGLSL );
|
2014-04-17 15:44:49 +00:00
|
|
|
FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureGLSL( "Terrain Parallax Texture" ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatGLSL );
|
|
|
|
|
FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatGLSL );
|
2014-04-17 15:44:49 +00:00
|
|
|
FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatGLSL );
|
2012-09-19 15:15:01 +00:00
|
|
|
FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL );
|
|
|
|
|
FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) );
|
2014-04-17 15:44:49 +00:00
|
|
|
FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL );
|
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
|
|
|
FEATUREMGR->registerFeature( MFT_DeferredTerrainBaseMap, new TerrainBaseMapFeatGLSL );
|
|
|
|
|
FEATUREMGR->registerFeature( MFT_DeferredTerrainMacroMap, new TerrainMacroMapFeatGLSL );
|
|
|
|
|
FEATUREMGR->registerFeature( MFT_DeferredTerrainDetailMap, new TerrainDetailMapFeatGLSL );
|
|
|
|
|
FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatGLSL );
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MODULE_BEGIN( TerrainFeatGLSL )
|
|
|
|
|
|
|
|
|
|
MODULE_INIT_AFTER( ShaderGen )
|
|
|
|
|
|
|
|
|
|
MODULE_INIT
|
|
|
|
|
{
|
|
|
|
|
SHADERGEN->getFeatureInitSignal().notify(®ister_glsl_shader_features_for_terrain);
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MODULE_END;
|
|
|
|
|
|
|
|
|
|
|
2015-11-11 19:52:46 +00:00
|
|
|
TerrainFeatGLSL::TerrainFeatGLSL()
|
2017-02-24 08:40:56 +00:00
|
|
|
: mTorqueDep(String(Con::getVariable("$Core::CommonShaderPath")) + String("/gl/torque.glsl" ))
|
2015-11-11 19:52:46 +00:00
|
|
|
{
|
|
|
|
|
addDependency( &mTorqueDep );
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
Var* TerrainFeatGLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp )
|
|
|
|
|
{
|
|
|
|
|
Var *theVar = (Var*)LangElement::find( name );
|
|
|
|
|
if ( !theVar )
|
|
|
|
|
{
|
|
|
|
|
theVar = new Var;
|
|
|
|
|
theVar->setType( type );
|
|
|
|
|
theVar->setName( name );
|
|
|
|
|
theVar->uniform = true;
|
|
|
|
|
theVar->constSortPos = csp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return theVar;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* TerrainFeatGLSL::_getInDetailCoord( Vector<ShaderComponent*> &componentList )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
String name( String::ToString( "detCoord%d", getProcessIndex() ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
Var *inDet = (Var*)LangElement::find( name );
|
|
|
|
|
|
|
|
|
|
if ( !inDet )
|
|
|
|
|
{
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
|
|
|
|
|
inDet = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
inDet->setName( name );
|
2014-04-17 15:44:49 +00:00
|
|
|
inDet->setStructName( "IN" );
|
2012-09-19 15:15:01 +00:00
|
|
|
inDet->setType( "vec4" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return inDet;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
Var* TerrainFeatGLSL::_getInMacroCoord( Vector<ShaderComponent*> &componentList )
|
|
|
|
|
{
|
|
|
|
|
String name( String::ToString( "macroCoord%d", getProcessIndex() ) );
|
|
|
|
|
Var *inDet = (Var*)LangElement::find( name );
|
|
|
|
|
|
|
|
|
|
if ( !inDet )
|
|
|
|
|
{
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
|
|
|
|
|
inDet = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
inDet->setName( name );
|
|
|
|
|
inDet->setStructName( "IN" );
|
|
|
|
|
inDet->setType( "vec4" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return inDet;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
Var* TerrainFeatGLSL::_getNormalMapTex()
|
|
|
|
|
{
|
|
|
|
|
String name( String::ToString( "normalMap%d", getProcessIndex() ) );
|
|
|
|
|
Var *normalMap = (Var*)LangElement::find( name );
|
|
|
|
|
|
|
|
|
|
if ( !normalMap )
|
|
|
|
|
{
|
|
|
|
|
normalMap = new Var;
|
|
|
|
|
normalMap->setType( "sampler2D" );
|
|
|
|
|
normalMap->setName( name );
|
|
|
|
|
normalMap->uniform = true;
|
|
|
|
|
normalMap->sampler = true;
|
|
|
|
|
normalMap->constNum = Var::getTexUnitNum();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return normalMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var* TerrainFeatGLSL::_getDetailIdStrengthParallax()
|
|
|
|
|
{
|
|
|
|
|
String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
|
|
|
|
|
|
|
|
|
|
Var *detailInfo = (Var*)LangElement::find( name );
|
|
|
|
|
if ( !detailInfo )
|
|
|
|
|
{
|
|
|
|
|
detailInfo = new Var;
|
|
|
|
|
detailInfo->setType( "vec3" );
|
|
|
|
|
detailInfo->setName( name );
|
|
|
|
|
detailInfo->uniform = true;
|
|
|
|
|
detailInfo->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return detailInfo;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
Var* TerrainFeatGLSL::_getMacroIdStrengthParallax()
|
|
|
|
|
{
|
|
|
|
|
String name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) );
|
|
|
|
|
|
|
|
|
|
Var *detailInfo = (Var*)LangElement::find( name );
|
|
|
|
|
if ( !detailInfo )
|
|
|
|
|
{
|
|
|
|
|
detailInfo = new Var;
|
|
|
|
|
detailInfo->setType( "vec3" );
|
|
|
|
|
detailInfo->setName( name );
|
|
|
|
|
detailInfo->uniform = true;
|
|
|
|
|
detailInfo->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return detailInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
void TerrainBaseMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
output = meta;
|
|
|
|
|
|
|
|
|
|
// Generate the incoming texture var.
|
|
|
|
|
Var *inTex;
|
|
|
|
|
{
|
|
|
|
|
Var *inPos = (Var*)LangElement::find( "inPosition" );
|
|
|
|
|
if ( !inPos )
|
|
|
|
|
inPos = (Var*)LangElement::find( "position" );
|
|
|
|
|
|
|
|
|
|
inTex = new Var( "texCoord", "vec3" );
|
|
|
|
|
|
|
|
|
|
Var *oneOverTerrainSize = _getUniformVar( "oneOverTerrainSize", "float", cspPass );
|
|
|
|
|
|
|
|
|
|
// NOTE: The y coord here should be negative to have
|
|
|
|
|
// the texture maps not end up flipped which also caused
|
|
|
|
|
// normal and parallax mapping to be incorrect.
|
|
|
|
|
//
|
|
|
|
|
// This mistake early in development means that the layer
|
|
|
|
|
// id bilinear blend depends on it being that way.
|
|
|
|
|
//
|
|
|
|
|
// So instead i fixed this by flipping the base and detail
|
|
|
|
|
// coord y scale to compensate when rendering.
|
|
|
|
|
//
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
|
|
|
|
|
// Pass the texture coord to the pixel shader.
|
|
|
|
|
Var *outTex = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
outTex->setName( "outTexCoord" );
|
2014-04-17 15:44:49 +00:00
|
|
|
outTex->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outTex->setType( "vec3" );
|
|
|
|
|
meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) );
|
|
|
|
|
|
|
|
|
|
// If this shader has a side projected layer then we
|
|
|
|
|
// pass the dot product between the +Y and the normal
|
|
|
|
|
// thru outTexCoord.z for use in blending the textures.
|
|
|
|
|
if ( fd.features.hasFeature( MFT_TerrainSideProject ) )
|
|
|
|
|
{
|
|
|
|
|
Var *inNormal = (Var*)LangElement::find( "normal" );
|
|
|
|
|
meta->addStatement(
|
2014-04-17 15:44:49 +00:00
|
|
|
new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
outTex, inNormal, inNormal ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
meta->addStatement( new GenOp( " @.z = 0;\r\n", outTex ) );
|
|
|
|
|
|
|
|
|
|
// HACK: This is sort of lazy... we generate the tanget
|
|
|
|
|
// vector here so that we're sure it exists in the parallax
|
|
|
|
|
// and normal features which will expect "T" to exist.
|
|
|
|
|
//
|
|
|
|
|
// If this shader doesn't use it the shader compiler will
|
|
|
|
|
// optimize away this code.
|
|
|
|
|
//
|
|
|
|
|
Var *inTangentZ = getVertTexCoord( "tcTangentZ" );
|
|
|
|
|
Var *inTanget = new Var( "T", "vec3" );
|
|
|
|
|
Var *squareSize = _getUniformVar( "squareSize", "float", cspPass );
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
new DecOp( inTanget ), squareSize, inTangentZ ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TerrainBaseMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
// grab connector texcoord register
|
2017-05-28 21:51:31 +00:00
|
|
|
Var *texCoord = getInTexCoord( "texCoord", "vec3", componentList );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// create texture var
|
|
|
|
|
Var *diffuseMap = new Var;
|
|
|
|
|
diffuseMap->setType( "sampler2D" );
|
|
|
|
|
diffuseMap->setName( "baseTexMap" );
|
|
|
|
|
diffuseMap->uniform = true;
|
|
|
|
|
diffuseMap->sampler = true;
|
|
|
|
|
diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
|
|
|
|
Var *baseColor = new Var;
|
|
|
|
|
baseColor->setType( "vec4" );
|
|
|
|
|
baseColor->setName( "baseColor" );
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor ), diffuseMap, texCoord ) );
|
2015-11-11 19:52:46 +00:00
|
|
|
meta->addStatement(new GenOp(" @ = toLinear(@);\r\n", baseColor, baseColor));
|
engine:
defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout)
script:
removes dead material features (ie: those that never functioned to begin with)
shader:
bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly)
purpose:
_A)_ Small primer on how material features function:
When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features.
Relevant execution of this is as follows:
DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name
ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order
FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code
alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance)
class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition
{
getName -embeded in the proceedural shader as a remline both up top and before actual code insertions
processPix - pixel shader codeline insertions
getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets)
getResources - associated with the Resources struct, closely aligned with the hardware regestry
getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting)
setTexData - ???
processVert - vertex shader codeline insertions
};
_B)_
The resultant Gbuffer layout defined by the previous commit therefore is as follows:
defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting)
color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency)
color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains:
red channel comprising material flags such as metalness, emissive, ect,
green channel for translucency (light shining through, as oposed to see-through transparency), blue for
blue for specular strength (how much light influences net color)
alpha for specular power (generally how reflective/glossy an object is)
long term purpose:
further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
|
|
|
|
|
|
|
|
ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget;
|
|
|
|
|
|
|
|
|
|
if(fd.features.hasFeature(MFT_isDeferred))
|
|
|
|
|
{
|
|
|
|
|
target= ShaderFeature::RenderTarget1;
|
|
|
|
|
}
|
|
|
|
|
meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul,NULL,target ) ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources TerrainBaseMapFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
res.numTexReg = 1;
|
|
|
|
|
res.numTex = 1;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
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 TerrainBaseMapFeatGLSL::getOutputTargets( const MaterialFeatureData &fd ) const
|
|
|
|
|
{
|
|
|
|
|
return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
TerrainDetailMapFeatGLSL::TerrainDetailMapFeatGLSL()
|
2017-02-24 08:40:56 +00:00
|
|
|
: mTorqueDep(String(Con::getVariable("$Core::CommonShaderPath")) + String("/gl/torque.glsl" )),
|
|
|
|
|
mTerrainDep(String(Con::getVariable("$Core::CommonShaderPath")) + String("/terrain/terrain.glsl" ))
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
addDependency( &mTorqueDep );
|
2012-09-19 15:15:01 +00:00
|
|
|
addDependency( &mTerrainDep );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TerrainDetailMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
2016-02-21 12:24:05 +00:00
|
|
|
const S32 detailIndex = getProcessIndex();
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Grab incoming texture coords... the base map feature
|
|
|
|
|
// made sure this was created.
|
|
|
|
|
Var *inTex = (Var*)LangElement::find( "texCoord" );
|
|
|
|
|
AssertFatal( inTex, "The texture coord is missing!" );
|
|
|
|
|
|
|
|
|
|
// Grab the input position.
|
|
|
|
|
Var *inPos = (Var*)LangElement::find( "inPosition" );
|
|
|
|
|
if ( !inPos )
|
|
|
|
|
inPos = (Var*)LangElement::find( "position" );
|
|
|
|
|
|
|
|
|
|
// Get the object space eye position.
|
|
|
|
|
Var *eyePos = _getUniformVar( "eyePos", "vec3", cspPotentialPrimitive );
|
|
|
|
|
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// If we have parallax mapping then make sure we've sent
|
|
|
|
|
// the negative view vector to the pixel shader.
|
|
|
|
|
if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
|
|
|
|
|
!LangElement::find( "outNegViewTS" ) )
|
|
|
|
|
{
|
|
|
|
|
// Get the object to tangent transform which
|
|
|
|
|
// will consume 3 output registers.
|
|
|
|
|
Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd );
|
|
|
|
|
|
|
|
|
|
// Now use a single output register to send the negative
|
|
|
|
|
// view vector in tangent space to the pixel shader.
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
outNegViewTS->setName( "outNegViewTS" );
|
|
|
|
|
outNegViewTS->setStructName( "OUT" );
|
|
|
|
|
outNegViewTS->setType( "vec3" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = tMul( @, float3( @ - @.xyz ) );\r\n",
|
|
|
|
|
outNegViewTS, objToTangentSpace, eyePos, inPos ) );
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
// Get the distance from the eye to this vertex.
|
|
|
|
|
Var *dist = (Var*)LangElement::find( "dist" );
|
|
|
|
|
if ( !dist )
|
|
|
|
|
{
|
|
|
|
|
dist = new Var;
|
|
|
|
|
dist->setType( "float" );
|
|
|
|
|
dist->setName( "dist" );
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
|
|
|
|
|
new DecOp( dist ), inPos, eyePos ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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( String::ToString( "detCoord%d", detailIndex ) );
|
|
|
|
|
outTex->setStructName( "OUT" );
|
2012-09-19 15:15:01 +00:00
|
|
|
outTex->setType( "vec4" );
|
|
|
|
|
|
|
|
|
|
// Get the detail scale and fade info.
|
|
|
|
|
Var *detScaleAndFade = new Var;
|
|
|
|
|
detScaleAndFade->setType( "vec4" );
|
|
|
|
|
detScaleAndFade->setName( String::ToString( "detailScaleAndFade%d", detailIndex ) );
|
|
|
|
|
detScaleAndFade->uniform = true;
|
|
|
|
|
detScaleAndFade->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
// Setup the detail coord.
|
|
|
|
|
//
|
|
|
|
|
// NOTE: You see here we scale the texture coord by 'xyx'
|
|
|
|
|
// to generate the detail coord. This y is here because
|
|
|
|
|
// its scale is flipped to correct for the non negative y
|
|
|
|
|
// in texCoord.
|
|
|
|
|
//
|
2014-04-17 15:44:49 +00:00
|
|
|
// See TerrainBaseMapFeatGLSL::processVert().
|
2012-09-19 15:15:01 +00:00
|
|
|
//
|
|
|
|
|
meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
|
|
|
|
|
|
|
|
|
|
// And sneak the detail fade thru the w detailCoord.
|
|
|
|
|
meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
|
|
|
|
|
outTex, detScaleAndFade, dist, detScaleAndFade ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
2016-02-21 12:24:05 +00:00
|
|
|
const S32 detailIndex = getProcessIndex();
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *inTex = getVertTexCoord( "texCoord" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
MultiLine *meta = new MultiLine;
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// We need the negative tangent space view vector
|
|
|
|
|
// as in parallax mapping we step towards the camera.
|
|
|
|
|
Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
|
|
|
|
|
if ( !negViewTS &&
|
|
|
|
|
fd.features.hasFeature( MFT_TerrainParallaxMap ) )
|
|
|
|
|
{
|
|
|
|
|
Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
|
|
|
|
|
if ( !inNegViewTS )
|
|
|
|
|
{
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
inNegViewTS = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
inNegViewTS->setName( "outNegViewTS" );
|
|
|
|
|
inNegViewTS->setStructName( "IN" );
|
|
|
|
|
inNegViewTS->setType( "vec3" );
|
|
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
negViewTS = new Var( "negViewTS", "vec3" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
|
|
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Get the layer samples.
|
|
|
|
|
Var *layerSample = (Var*)LangElement::find( "layerSample" );
|
|
|
|
|
if ( !layerSample )
|
|
|
|
|
{
|
|
|
|
|
layerSample = new Var;
|
|
|
|
|
layerSample->setType( "vec4" );
|
|
|
|
|
layerSample->setName( "layerSample" );
|
|
|
|
|
|
|
|
|
|
// Get the layer texture var
|
|
|
|
|
Var *layerTex = new Var;
|
|
|
|
|
layerTex->setType( "sampler2D" );
|
|
|
|
|
layerTex->setName( "layerTex" );
|
|
|
|
|
layerTex->uniform = true;
|
|
|
|
|
layerTex->sampler = true;
|
|
|
|
|
layerTex->constNum = Var::getTexUnitNum();
|
|
|
|
|
|
|
|
|
|
// Read the layer texture to get the samples.
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
new DecOp( layerSample ), layerTex, inTex ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var *layerSize = (Var*)LangElement::find( "layerSize" );
|
|
|
|
|
if ( !layerSize )
|
|
|
|
|
{
|
|
|
|
|
layerSize = new Var;
|
|
|
|
|
layerSize->setType( "float" );
|
|
|
|
|
layerSize->setName( "layerSize" );
|
|
|
|
|
layerSize->uniform = true;
|
|
|
|
|
layerSize->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Grab the incoming detail coord.
|
|
|
|
|
Var *inDet = _getInDetailCoord( componentList );
|
|
|
|
|
|
|
|
|
|
// Get the detail id.
|
|
|
|
|
Var *detailInfo = _getDetailIdStrengthParallax();
|
|
|
|
|
|
|
|
|
|
// Create the detail blend var.
|
|
|
|
|
Var *detailBlend = new Var;
|
|
|
|
|
detailBlend->setType( "float" );
|
|
|
|
|
detailBlend->setName( String::ToString( "detailBlend%d", detailIndex ) );
|
|
|
|
|
|
|
|
|
|
// Calculate the blend for this detail texture.
|
|
|
|
|
meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
|
|
|
|
|
new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
|
|
|
|
|
|
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
|
|
|
// New terrain
|
|
|
|
|
|
|
|
|
|
Var *lerpBlend = (Var*)LangElement::find("lerpBlend");
|
|
|
|
|
if (!lerpBlend)
|
|
|
|
|
{
|
|
|
|
|
lerpBlend = new Var;
|
|
|
|
|
lerpBlend->setType("float");
|
|
|
|
|
lerpBlend->setName("lerpBlend");
|
|
|
|
|
lerpBlend->uniform = true;
|
|
|
|
|
lerpBlend->constSortPos = cspPrimitive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Var *blendDepth = (Var*)LangElement::find(String::ToString("blendDepth%d", detailIndex));
|
|
|
|
|
if (!blendDepth)
|
|
|
|
|
{
|
|
|
|
|
blendDepth = new Var;
|
|
|
|
|
blendDepth->setType("float");
|
|
|
|
|
blendDepth->setName(String::ToString("blendDepth%d", detailIndex));
|
|
|
|
|
blendDepth->uniform = true;
|
|
|
|
|
blendDepth->constSortPos = cspPrimitive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget;
|
|
|
|
|
|
|
|
|
|
if(fd.features.hasFeature( MFT_DeferredTerrainDetailMap ))
|
|
|
|
|
target= ShaderFeature::RenderTarget1;
|
|
|
|
|
|
|
|
|
|
Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) );
|
|
|
|
|
|
|
|
|
|
if (!outColor)
|
|
|
|
|
{
|
|
|
|
|
// create color var
|
|
|
|
|
outColor = new Var;
|
|
|
|
|
outColor->setType("float4");
|
|
|
|
|
outColor->setName("col");
|
|
|
|
|
outColor->setStructName("OUT");
|
|
|
|
|
meta->addStatement(new GenOp(" @;\r\n", outColor));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var *detailColor = (Var*)LangElement::find("detailColor");
|
|
|
|
|
if (!detailColor)
|
|
|
|
|
{
|
|
|
|
|
detailColor = new Var;
|
|
|
|
|
detailColor->setType("float4");
|
|
|
|
|
detailColor->setName("detailColor");
|
|
|
|
|
meta->addStatement(new GenOp(" @;\r\n", new DecOp(detailColor)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the detail texture.
|
|
|
|
|
Var *detailMap = new Var;
|
|
|
|
|
detailMap->setType("sampler2D");
|
|
|
|
|
detailMap->setName(String::ToString("detailMap%d", detailIndex));
|
|
|
|
|
detailMap->uniform = true;
|
|
|
|
|
detailMap->sampler = true;
|
|
|
|
|
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
|
|
|
|
// Get the normal map texture.
|
|
|
|
|
Var *normalMap = _getNormalMapTex();
|
|
|
|
|
|
|
|
|
|
// Issue happens somewhere here -----
|
|
|
|
|
|
|
|
|
|
// Sample the normal map.
|
|
|
|
|
//
|
|
|
|
|
// We take two normal samples and lerp between them for
|
|
|
|
|
// side projection layers... else a single sample.
|
|
|
|
|
LangElement *texOp;
|
|
|
|
|
|
|
|
|
|
// Note that we're doing the standard greyscale detail
|
|
|
|
|
// map technique here which can darken and lighten the
|
|
|
|
|
// diffuse texture.
|
|
|
|
|
//
|
|
|
|
|
// We take two color samples and lerp between them for
|
|
|
|
|
// side projection layers... else a single sample.
|
|
|
|
|
//
|
|
|
|
|
if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
|
|
|
|
|
{
|
|
|
|
|
meta->addStatement(new GenOp(" @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
|
|
|
|
|
detailColor, detailMap, inDet, detailMap, inDet, inTex));
|
|
|
|
|
|
|
|
|
|
texOp = new GenOp("lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
|
|
|
|
|
normalMap, inDet, normalMap, inDet, inTex);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
meta->addStatement(new GenOp(" @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
|
|
|
|
|
detailColor, detailMap, inDet));
|
|
|
|
|
|
|
|
|
|
texOp = new GenOp("tex2D(@, @.xy)", normalMap, inDet);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New terrain
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
// Get a var and accumulate the blend amount.
|
|
|
|
|
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
|
|
|
|
|
if ( !blendTotal )
|
|
|
|
|
{
|
|
|
|
|
blendTotal = new Var;
|
|
|
|
|
blendTotal->setName( "blendTotal" );
|
|
|
|
|
blendTotal->setType( "float" );
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add to the blend total.
|
2016-07-29 16:26:44 +00:00
|
|
|
meta->addStatement(new GenOp(" @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend));
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
// If we had a parallax feature... then factor in the parallax
|
|
|
|
|
// amount so that it fades out with the layer blending.
|
|
|
|
|
if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) )
|
|
|
|
|
{
|
|
|
|
|
// Get the rest of our inputs.
|
|
|
|
|
Var *normalMap = _getNormalMapTex();
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// Call the library function to do the rest.
|
2015-08-28 05:27:08 +00:00
|
|
|
if (fd.features.hasFeature(MFT_IsDXTnm, detailIndex))
|
|
|
|
|
{
|
|
|
|
|
meta->addStatement(new GenOp(" @.xy += parallaxOffsetDxtnm( @, @.xy, @, @.z * @ );\r\n",
|
|
|
|
|
inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
meta->addStatement(new GenOp(" @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n",
|
|
|
|
|
inDet, normalMap, inDet, negViewTS, detailInfo, detailBlend));
|
|
|
|
|
}
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
// If we're using SM 3.0 then take advantage of
|
|
|
|
|
// dynamic branching to skip layers per-pixel.
|
2014-12-03 20:54:57 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
if ( GFX->getPixelShaderVersion() >= 3.0f )
|
|
|
|
|
meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " {\r\n" ) );
|
|
|
|
|
|
2014-12-03 20:54:57 +00:00
|
|
|
// Note that we're doing the standard greyscale detail
|
|
|
|
|
// map technique here which can darken and lighten the
|
|
|
|
|
// diffuse texture.
|
|
|
|
|
//
|
|
|
|
|
// We take two color samples and lerp between them for
|
|
|
|
|
// side projection layers... else a single sample.
|
|
|
|
|
//
|
|
|
|
|
if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
|
|
|
|
|
{
|
|
|
|
|
meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
|
|
|
|
|
detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
|
|
|
|
|
detailColor, detailMap, inDet ) );
|
|
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
|
|
|
|
|
detailColor, detailInfo, inDet ) );
|
|
|
|
|
|
2016-03-04 21:51:09 +00:00
|
|
|
meta->addStatement( new GenOp( " @ += @ * @;\r\n",
|
|
|
|
|
outColor, detailColor, detailBlend));
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " }\r\n" ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources TerrainDetailMapFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
if ( getProcessIndex() == 0 )
|
|
|
|
|
{
|
|
|
|
|
// If this is the first detail pass then we
|
|
|
|
|
// samples from the layer tex.
|
|
|
|
|
res.numTex += 1;
|
|
|
|
|
|
|
|
|
|
// If this material also does parallax then it
|
|
|
|
|
// will generate the negative view vector and the
|
|
|
|
|
// worldToTanget transform.
|
|
|
|
|
if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) )
|
|
|
|
|
res.numTexReg += 4;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
// sample from the detail texture for diffuse coloring.
|
2014-04-17 15:44:49 +00:00
|
|
|
res.numTex += 1;
|
|
|
|
|
|
|
|
|
|
// If we have parallax for this layer then we'll also
|
|
|
|
|
// be sampling the normal map for the parallax heightmap.
|
|
|
|
|
if ( fd.features.hasFeature( MFT_TerrainParallaxMap, getProcessIndex() ) )
|
|
|
|
|
res.numTex += 1;
|
|
|
|
|
|
|
|
|
|
// Finally we always send the detail texture
|
|
|
|
|
// coord to the pixel shader.
|
|
|
|
|
res.numTexReg += 1;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
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 TerrainDetailMapFeatGLSL::getOutputTargets( const MaterialFeatureData &fd ) const
|
|
|
|
|
{
|
|
|
|
|
return fd.features[MFT_DeferredTerrainDetailMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL()
|
2017-02-24 08:40:56 +00:00
|
|
|
: mTorqueDep(String(Con::getVariable("$Core::CommonShaderPath")) + String("/gl/torque.glsl" )),
|
|
|
|
|
mTerrainDep(String(Con::getVariable("$Core::CommonShaderPath")) + String("/terrain/terrain.glsl" ))
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
addDependency( &mTorqueDep );
|
|
|
|
|
addDependency( &mTerrainDep );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TerrainMacroMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
2016-02-21 12:24:05 +00:00
|
|
|
const S32 detailIndex = getProcessIndex();
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
// Grab incoming texture coords... the base map feature
|
|
|
|
|
// made sure this was created.
|
|
|
|
|
Var *inTex = (Var*)LangElement::find( "texCoord" );
|
|
|
|
|
AssertFatal( inTex, "The texture coord is missing!" );
|
|
|
|
|
|
|
|
|
|
// Grab the input position.
|
|
|
|
|
Var *inPos = (Var*)LangElement::find( "inPosition" );
|
|
|
|
|
if ( !inPos )
|
|
|
|
|
inPos = (Var*)LangElement::find( "position" );
|
|
|
|
|
|
|
|
|
|
// Get the object space eye position.
|
|
|
|
|
Var *eyePos = _getUniformVar( "eyePos", "vec3", cspPotentialPrimitive );
|
|
|
|
|
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
|
|
|
|
// Get the distance from the eye to this vertex.
|
|
|
|
|
Var *dist = (Var*)LangElement::find( "macroDist" );
|
|
|
|
|
if ( !dist )
|
|
|
|
|
{
|
|
|
|
|
dist = new Var;
|
|
|
|
|
dist->setType( "float" );
|
|
|
|
|
dist->setName( "macroDist" );
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
|
|
|
|
|
new DecOp( dist ), inPos, eyePos ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// grab connector texcoord register
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
Var *outTex = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
outTex->setName( String::ToString( "macroCoord%d", detailIndex ) );
|
|
|
|
|
outTex->setStructName( "OUT" );
|
|
|
|
|
outTex->setType( "vec4" );
|
|
|
|
|
|
|
|
|
|
// Get the detail scale and fade info.
|
|
|
|
|
Var *detScaleAndFade = new Var;
|
|
|
|
|
detScaleAndFade->setType( "vec4" );
|
|
|
|
|
detScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) );
|
|
|
|
|
detScaleAndFade->uniform = true;
|
|
|
|
|
detScaleAndFade->constSortPos = cspPotentialPrimitive;
|
|
|
|
|
|
|
|
|
|
// Setup the detail coord.
|
|
|
|
|
meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade ) );
|
|
|
|
|
|
|
|
|
|
// And sneak the detail fade thru the w detailCoord.
|
|
|
|
|
meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
|
|
|
|
|
outTex, detScaleAndFade, dist, detScaleAndFade ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TerrainMacroMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
2016-02-21 12:24:05 +00:00
|
|
|
const S32 detailIndex = getProcessIndex();
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *inTex = getVertTexCoord( "texCoord" );
|
|
|
|
|
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
|
|
|
|
// We need the negative tangent space view vector
|
|
|
|
|
// as in parallax mapping we step towards the camera.
|
|
|
|
|
Var *negViewTS = (Var*)LangElement::find( "negViewTS" );
|
|
|
|
|
if ( !negViewTS &&
|
|
|
|
|
fd.features.hasFeature( MFT_TerrainParallaxMap ) )
|
|
|
|
|
{
|
|
|
|
|
Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" );
|
|
|
|
|
if ( !inNegViewTS )
|
|
|
|
|
{
|
|
|
|
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
|
|
|
|
inNegViewTS = connectComp->getElement( RT_TEXCOORD );
|
|
|
|
|
inNegViewTS->setName( "outNegViewTS" );
|
|
|
|
|
inNegViewTS->setStructName( "IN" );
|
|
|
|
|
inNegViewTS->setType( "vec3" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
negViewTS = new Var( "negViewTS", "vec3" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the layer samples.
|
|
|
|
|
Var *layerSample = (Var*)LangElement::find( "layerSample" );
|
|
|
|
|
if ( !layerSample )
|
|
|
|
|
{
|
|
|
|
|
layerSample = new Var;
|
|
|
|
|
layerSample->setType( "vec4" );
|
|
|
|
|
layerSample->setName( "layerSample" );
|
|
|
|
|
|
|
|
|
|
// Get the layer texture var
|
|
|
|
|
Var *layerTex = new Var;
|
|
|
|
|
layerTex->setType( "sampler2D" );
|
|
|
|
|
layerTex->setName( "macrolayerTex" );
|
|
|
|
|
layerTex->uniform = true;
|
|
|
|
|
layerTex->sampler = true;
|
|
|
|
|
layerTex->constNum = Var::getTexUnitNum();
|
|
|
|
|
|
|
|
|
|
// Read the layer texture to get the samples.
|
|
|
|
|
meta->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
|
|
|
|
|
new DecOp( layerSample ), layerTex, inTex ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Var *layerSize = (Var*)LangElement::find( "layerSize" );
|
|
|
|
|
if ( !layerSize )
|
|
|
|
|
{
|
|
|
|
|
layerSize = new Var;
|
|
|
|
|
layerSize->setType( "float" );
|
|
|
|
|
layerSize->setName( "layerSize" );
|
|
|
|
|
layerSize->uniform = true;
|
|
|
|
|
layerSize->constSortPos = cspPass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Grab the incoming detail coord.
|
|
|
|
|
Var *inDet = _getInMacroCoord( componentList );
|
|
|
|
|
|
|
|
|
|
// Get the detail id.
|
|
|
|
|
Var *detailInfo = _getMacroIdStrengthParallax();
|
|
|
|
|
|
|
|
|
|
// Create the detail blend var.
|
|
|
|
|
Var *detailBlend = new Var;
|
|
|
|
|
detailBlend->setType( "float" );
|
|
|
|
|
detailBlend->setName( String::ToString( "macroBlend%d", detailIndex ) );
|
|
|
|
|
|
|
|
|
|
// Calculate the blend for this detail texture.
|
|
|
|
|
meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
|
|
|
|
|
new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );
|
|
|
|
|
|
|
|
|
|
// Get a var and accumulate the blend amount.
|
|
|
|
|
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
|
|
|
|
|
if ( !blendTotal )
|
|
|
|
|
{
|
|
|
|
|
blendTotal = new Var;
|
|
|
|
|
//blendTotal->setName( "blendTotal" );
|
|
|
|
|
blendTotal->setName( "blendTotal" );
|
|
|
|
|
blendTotal->setType( "float" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal ) ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add to the blend total.
|
2016-07-29 16:26:44 +00:00
|
|
|
meta->addStatement(new GenOp(" @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend));
|
2014-04-17 15:44:49 +00:00
|
|
|
|
|
|
|
|
Var *detailColor = (Var*)LangElement::find( "macroColor" );
|
|
|
|
|
if ( !detailColor )
|
|
|
|
|
{
|
|
|
|
|
detailColor = new Var;
|
|
|
|
|
detailColor->setType( "vec4" );
|
|
|
|
|
detailColor->setName( "macroColor" );
|
|
|
|
|
meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the detail texture.
|
|
|
|
|
Var *detailMap = new Var;
|
|
|
|
|
detailMap->setType( "sampler2D" );
|
|
|
|
|
detailMap->setName( String::ToString( "macroMap%d", detailIndex ) );
|
|
|
|
|
detailMap->uniform = true;
|
|
|
|
|
detailMap->sampler = true;
|
|
|
|
|
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
|
|
|
|
|
|
|
|
|
// If we're using SM 3.0 then take advantage of
|
|
|
|
|
// dynamic branching to skip layers per-pixel.
|
|
|
|
|
if ( GFX->getPixelShaderVersion() >= 3.0f )
|
|
|
|
|
meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " {\r\n" ) );
|
|
|
|
|
|
|
|
|
|
// Note that we're doing the standard greyscale detail
|
|
|
|
|
// map technique here which can darken and lighten the
|
|
|
|
|
// diffuse texture.
|
|
|
|
|
//
|
|
|
|
|
// We take two color samples and lerp between them for
|
|
|
|
|
// side projection layers... else a single sample.
|
|
|
|
|
//
|
|
|
|
|
if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
|
|
|
|
|
{
|
|
|
|
|
meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
|
|
|
|
|
detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
|
|
|
|
|
detailColor, detailMap, inDet ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
|
|
|
|
|
detailColor, detailInfo, inDet ) );
|
engine:
defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout)
script:
removes dead material features (ie: those that never functioned to begin with)
shader:
bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly)
purpose:
_A)_ Small primer on how material features function:
When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features.
Relevant execution of this is as follows:
DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name
ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order
FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code
alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance)
class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition
{
getName -embeded in the proceedural shader as a remline both up top and before actual code insertions
processPix - pixel shader codeline insertions
getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets)
getResources - associated with the Resources struct, closely aligned with the hardware regestry
getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting)
setTexData - ???
processVert - vertex shader codeline insertions
};
_B)_
The resultant Gbuffer layout defined by the previous commit therefore is as follows:
defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting)
color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency)
color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains:
red channel comprising material flags such as metalness, emissive, ect,
green channel for translucency (light shining through, as oposed to see-through transparency), blue for
blue for specular strength (how much light influences net color)
alpha for specular power (generally how reflective/glossy an object is)
long term purpose:
further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
|
|
|
ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget;
|
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
|
|
|
if(fd.features.hasFeature(MFT_DeferredTerrainMacroMap))
|
|
|
|
|
target= ShaderFeature::RenderTarget1;
|
|
|
|
|
|
|
|
|
|
Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) );
|
2014-04-17 15:44:49 +00:00
|
|
|
|
2016-03-04 21:51:09 +00:00
|
|
|
meta->addStatement(new GenOp(" @ += @ * @;\r\n",
|
|
|
|
|
outColor, detailColor, detailBlend));
|
2014-12-03 20:54:57 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " }\r\n" ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources TerrainMacroMapFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
|
|
|
|
|
if ( getProcessIndex() == 0 )
|
|
|
|
|
{
|
|
|
|
|
// If this is the first detail pass then we
|
|
|
|
|
// samples from the layer tex.
|
2012-09-19 15:15:01 +00:00
|
|
|
res.numTex += 1;
|
2014-04-17 15:44:49 +00:00
|
|
|
}
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
res.numTex += 1;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// Finally we always send the detail texture
|
|
|
|
|
// coord to the pixel shader.
|
2012-09-19 15:15:01 +00:00
|
|
|
res.numTexReg += 1;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
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 TerrainMacroMapFeatGLSL::getOutputTargets( const MaterialFeatureData &fd ) const
|
|
|
|
|
{
|
|
|
|
|
return fd.features[MFT_DeferredTerrainMacroMap] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
void TerrainNormalMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
2017-04-11 05:23:14 +00:00
|
|
|
// We only need to process normals during the deferred.
|
|
|
|
|
if ( !fd.features.hasFeature( MFT_DeferredConditioner ) )
|
2012-09-19 15:15:01 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
|
|
|
|
// Make sure the world to tangent transform
|
|
|
|
|
// is created and available for the pixel shader.
|
|
|
|
|
getOutViewToTangent( componentList, meta, fd );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
|
|
|
|
Var *viewToTangent = getInViewToTangent( componentList );
|
|
|
|
|
|
|
|
|
|
// This var is read from GBufferConditionerGLSL and
|
2017-04-11 05:23:14 +00:00
|
|
|
// used in the deferred output.
|
2012-09-19 15:15:01 +00:00
|
|
|
Var *gbNormal = (Var*)LangElement::find( "gbNormal" );
|
|
|
|
|
if ( !gbNormal )
|
|
|
|
|
{
|
|
|
|
|
gbNormal = new Var;
|
|
|
|
|
gbNormal->setName( "gbNormal" );
|
|
|
|
|
gbNormal->setType( "vec3" );
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = tGetMatrix3Row(@, 2);\r\n", new DecOp( gbNormal ), viewToTangent ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-21 12:24:05 +00:00
|
|
|
const S32 normalIndex = getProcessIndex();
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) );
|
|
|
|
|
AssertFatal( detailBlend, "The detail blend is missing!" );
|
|
|
|
|
|
|
|
|
|
// If we're using SM 3.0 then take advantage of
|
|
|
|
|
// dynamic branching to skip layers per-pixel.
|
|
|
|
|
if ( GFX->getPixelShaderVersion() >= 3.0f )
|
|
|
|
|
meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " {\r\n" ) );
|
|
|
|
|
|
|
|
|
|
// Get the normal map texture.
|
|
|
|
|
Var *normalMap = _getNormalMapTex();
|
|
|
|
|
|
|
|
|
|
/// Get the texture coord.
|
|
|
|
|
Var *inDet = _getInDetailCoord( componentList );
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *inTex = getVertTexCoord( "texCoord" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// Sample the normal map.
|
|
|
|
|
//
|
|
|
|
|
// We take two normal samples and lerp between them for
|
|
|
|
|
// side projection layers... else a single sample.
|
|
|
|
|
LangElement *texOp;
|
|
|
|
|
if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) )
|
|
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
texOp = new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
|
2012-09-19 15:15:01 +00:00
|
|
|
normalMap, inDet, normalMap, inDet, inTex );
|
|
|
|
|
}
|
|
|
|
|
else
|
2014-04-17 15:44:49 +00:00
|
|
|
texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
// create bump normal
|
2014-12-03 20:54:57 +00:00
|
|
|
Var *bumpNorm = new Var;
|
|
|
|
|
bumpNorm->setName( "bumpNormal" );
|
|
|
|
|
bumpNorm->setType( "vec4" );
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-12-03 20:54:57 +00:00
|
|
|
LangElement *bumpNormDecl = new DecOp( bumpNorm );
|
2012-09-19 15:15:01 +00:00
|
|
|
meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
|
|
|
|
|
|
|
|
|
|
// Normalize is done later...
|
|
|
|
|
// Note: The reverse mul order is intentional. Affine matrix.
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n",
|
2012-09-19 15:15:01 +00:00
|
|
|
gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );
|
|
|
|
|
|
|
|
|
|
// End the conditional block.
|
|
|
|
|
meta->addStatement( new GenOp( " }\r\n" ) );
|
|
|
|
|
|
|
|
|
|
// If this is the last normal map then we
|
|
|
|
|
// can test to see the total blend value
|
|
|
|
|
// to see if we should clip the result.
|
|
|
|
|
//if ( fd.features.getNextFeatureIndex( MFT_TerrainNormalMap, normalIndex ) == -1 )
|
|
|
|
|
//meta->addStatement( new GenOp( " clip( @ - 0.0001f );\r\n", blendTotal ) );
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources TerrainNormalMapFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
|
2017-04-11 05:23:14 +00:00
|
|
|
// We only need to process normals during the deferred.
|
|
|
|
|
if ( fd.features.hasFeature( MFT_DeferredConditioner ) )
|
2012-09-19 15:15:01 +00:00
|
|
|
{
|
2014-04-17 15:44:49 +00:00
|
|
|
// If this is the first normal map and there
|
|
|
|
|
// are no parallax features then we will
|
|
|
|
|
// generate the worldToTanget transform.
|
|
|
|
|
if ( !fd.features.hasFeature( MFT_TerrainParallaxMap ) &&
|
|
|
|
|
( getProcessIndex() == 0 || !fd.features.hasFeature( MFT_TerrainNormalMap, getProcessIndex() - 1 ) ) )
|
2012-09-19 15:15:01 +00:00
|
|
|
res.numTexReg = 3;
|
|
|
|
|
|
|
|
|
|
res.numTex = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TerrainLightMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
// grab connector texcoord register
|
2014-04-17 15:44:49 +00:00
|
|
|
Var *inTex = (Var*)LangElement::find( "texCoord" );
|
2012-09-19 15:15:01 +00:00
|
|
|
if ( !inTex )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Get the lightmap texture.
|
|
|
|
|
Var *lightMap = new Var;
|
|
|
|
|
lightMap->setType( "sampler2D" );
|
|
|
|
|
lightMap->setName( "lightMapTex" );
|
|
|
|
|
lightMap->uniform = true;
|
|
|
|
|
lightMap->sampler = true;
|
|
|
|
|
lightMap->constNum = Var::getTexUnitNum();
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
MultiLine *meta = new MultiLine;
|
2012-09-19 15:15:01 +00:00
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
// Find or create the lightMask value which is read by
|
|
|
|
|
// RTLighting to mask out the lights.
|
|
|
|
|
//
|
|
|
|
|
// The first light is always the sunlight so we apply
|
|
|
|
|
// the shadow mask to only the first channel.
|
|
|
|
|
//
|
|
|
|
|
Var *lightMask = (Var*)LangElement::find( "lightMask" );
|
|
|
|
|
if ( !lightMask )
|
|
|
|
|
{
|
|
|
|
|
lightMask = new Var( "lightMask", "vec4" );
|
|
|
|
|
meta->addStatement( new GenOp( " @ = vec4(1);\r\n", new DecOp( lightMask ) ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
meta->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask, lightMap, inTex ) );
|
|
|
|
|
output = meta;
|
2012-09-19 15:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderFeature::Resources TerrainLightMapFeatGLSL::getResources( const MaterialFeatureData &fd )
|
|
|
|
|
{
|
|
|
|
|
Resources res;
|
|
|
|
|
res.numTex = 1;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TerrainAdditiveFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd )
|
|
|
|
|
{
|
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 = NULL;
|
2016-09-14 20:35:35 +00:00
|
|
|
Var *normal = NULL;
|
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_DeferredTerrainDetailMap])
|
2016-09-14 20:35:35 +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
|
|
|
color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1) );
|
2016-09-14 20:35:35 +00:00
|
|
|
normal = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget) );
|
|
|
|
|
}
|
engine:
defines and alters a series of material features for deferred shading in order to define a fully fleshed out multiple render target gbuffer patterned after the general principles outlined http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/ (though I cannot stress enough *not* using the identical layout)
script:
removes dead material features (ie: those that never functioned to begin with)
shader:
bool getFlag(float flags, int num) definition for retreiving data from the 3rd (matinfo) gbuffer slot's red channel (more on that shortly)
purpose:
_A)_ Small primer on how material features function:
When a https://github.com/GarageGames/Torque3D/search?utf8=%E2%9C%93&q=_determineFeatures call is executed, certain conditions trigger a given .addFeature(MFT_SOMEFEATURE) call based upon material definition entries, be it a value, a texture reference, or even the presence or lack thereof for another feature. In general terms, the first to be executed is ProcessedShaderMaterial::_determineFeatures followed by ProcessedPrePassMaterial::_determineFeatures. The next commit will provide the bindings there. For now it's enough to understand that one of those two will trigger the shadergen subsystem, when rendering a material, to check it's associated list of features and spit out a shader if one is not already defined, or reference a pre-existing one that includes codelines determined by that list of features.
Relevant execution of this is as follows:
DeclareFeatureType( MFT_DeferredDiffuseMap ); - Name
ImplementFeatureType( MFT_DeferredDiffuseMap, MFG_Texture, 2.0f, false ); - Codeline Insertion Order
FEATUREMGR->registerFeature( MFT_DeferredDiffuseMap, new DeferredDiffuseMapHLSL ); - Hook to class which actually generates code
alternately FEATUREMGR->registerFeature( MFT_Imposter, new NamedFeatureHLSL( "Imposter" ) ); - a simple feature that serves no purpose further than as a test of it's existence (to modify other features for instance)
class DeferredDiffuseMapHLSL : public ShaderFeatureHLSL - Class definition
{
getName -embeded in the proceedural shader as a remline both up top and before actual code insertions
processPix - pixel shader codeline insertions
getOutputTargets - used to determine which buffer is written to (assumes only one. depending on branched logic, older features that may be run for either forward or deferred rendering depending on circumstance may have a logical switch based on additional feature flags. as an example: TerrainBaseMapFeatHLSL::getOutputTargets)
getResources - associated with the Resources struct, closely aligned with the hardware regestry
getBlendOp - used to determine what blend operation to use if a material requires a second pass (defaults to overwriting)
setTexData - ???
processVert - vertex shader codeline insertions
};
_B)_
The resultant Gbuffer layout defined by the previous commit therefore is as follows:
defaultrendertarget (referred to in shaders as out.col or col depending on GFX plugin) contains either lighting and normal data, or color data depending on if it is used in a deferred or forward lit manner (note for forward lit, this data is replaced as a second step with color. why custommaterials have traditionally had problems with lighting)
color1 (referred to in shaders as out.col1 or col1 depending on GFX plugin) RGB color data and an A for blending operations (including transparency)
color2 (referred to in shaders as out.col2 or col2 depending on GFX plugin) contains:
red channel comprising material flags such as metalness, emissive, ect,
green channel for translucency (light shining through, as oposed to see-through transparency), blue for
blue for specular strength (how much light influences net color)
alpha for specular power (generally how reflective/glossy an object is)
long term purpose:
further down the line, these will be used to condition data for use with a PBR subsystem, with further corrections to the underlying mathematics, strength being replaced by roughness, and power by metalness
2016-02-16 08:23:23 +00:00
|
|
|
else
|
|
|
|
|
color = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget) );
|
|
|
|
|
|
2012-09-19 15:15:01 +00:00
|
|
|
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
|
|
|
|
|
if ( !color || !blendTotal )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
MultiLine *meta = new MultiLine;
|
|
|
|
|
|
2014-04-17 15:44:49 +00:00
|
|
|
meta->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal ) );
|
2012-09-19 15:15:01 +00:00
|
|
|
meta->addStatement( new GenOp( " @.a = @;\r\n", color, blendTotal ) );
|
2016-09-14 20:35:35 +00:00
|
|
|
if (normal)
|
|
|
|
|
meta->addStatement(new GenOp(" @.a = @;\r\n", normal, blendTotal));
|
2012-09-19 15:15:01 +00:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
|
|
|
|
|
//.b = specular strength, a= spec power.
|
|
|
|
|
//here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled.
|
|
|
|
|
//we'll most likely revisit that later. possibly several ways...
|
|
|
|
|
|
|
|
|
|
U32 TerrainBlankInfoMapFeatGLSL::getOutputTargets(const MaterialFeatureData &fd) const
|
|
|
|
|
{
|
|
|
|
|
return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget2 : ShaderFeature::RenderTarget1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TerrainBlankInfoMapFeatGLSL::processPix(Vector<ShaderComponent*> &componentList,
|
|
|
|
|
const MaterialFeatureData &fd)
|
|
|
|
|
{
|
|
|
|
|
// search for material var
|
|
|
|
|
Var *material;
|
|
|
|
|
OutputTarget targ = RenderTarget1;
|
|
|
|
|
if (fd.features[MFT_isDeferred])
|
|
|
|
|
{
|
|
|
|
|
targ = RenderTarget2;
|
|
|
|
|
}
|
|
|
|
|
material = (Var*)LangElement::find(getOutputTargetVarName(targ));
|
|
|
|
|
|
|
|
|
|
MultiLine * meta = new MultiLine;
|
|
|
|
|
if (!material)
|
|
|
|
|
{
|
|
|
|
|
// create color var
|
|
|
|
|
material = new Var;
|
|
|
|
|
material->setType("vec4");
|
|
|
|
|
material->setName(getOutputTargetVarName(targ));
|
|
|
|
|
material->setStructName("OUT");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
meta->addStatement(new GenOp(" @ = float4(0.0,0.0,0.0,0.0001);\r\n", material));
|
|
|
|
|
|
|
|
|
|
output = meta;
|
|
|
|
|
}
|