Edge Clamp Texture Addressing for T3D Materials
by Guy Allard · 08/18/2012 (9:46 am) · 10 comments
By default, all standard T3D materials use GFXAddressWrap as their texture coordinate address mode. This is suitable for most uses, but if you try and take advantage of the rotation animation setting for a material you will get artifacts at the edges of the material that you may not like.
This resource allows you to force a material texture stage to use GFXAddressClamp for the address mode, which will remove these artifacts.
If the above explanation makes no sense, take a look at this video which shows a rotating texture using T3D's normal settings, then with the GFXAddressClamp enabled.
Engine Modifications
Luckily, there are only a few small changes to be made to the engine.
file: engine\materials\materialDefinition.h
after:
add:
file: engine\materials\materialDefinition.cpp
function: Material::Material()
after:
add:
file: engine\materials\materialDefinition.cpp
function: Material::initPersistFields()
after:
add:
file: engine\materials\processedMaterial.cpp
function: ProcessedMaterial::_initPassStateBlock( RenderPassData *rpd, GFXStateBlockDesc & result )
change:
to:
Script changes to the material editor
To add the check box for enabling edge clamp for a texture stage, we need to make a couple of small modifications to the material editor scripts.
file: game\tools\materialEditor\gui\guiMaterialPropertiesWindow.ed.gui
around line 657,
after:
add:
file: game\tools\materialEditor\scripts\materialEditor.ed.cs
add this function:
file: game\tools\materialEditor\scripts\materialEditor.ed.cs
in function: MaterialEditorGui::guiSync( %this, %material )
after:
add:
enjoy.
This resource allows you to force a material texture stage to use GFXAddressClamp for the address mode, which will remove these artifacts.
If the above explanation makes no sense, take a look at this video which shows a rotating texture using T3D's normal settings, then with the GFXAddressClamp enabled.
Engine Modifications
Luckily, there are only a few small changes to be made to the engine.
file: engine\materials\materialDefinition.h
after:
bool mUseAnisotropic[MAX_STAGES];
add:
// GUY - texture address clamping >> bool mAddressModeClamp[MAX_STAGES]; // GUY - texture address clamping <<
file: engine\materials\materialDefinition.cpp
function: Material::Material()
after:
mSeqSegSize[i] = 0.0f;
add:
// GUY - texture address clamping >> mAddressModeClamp[i] = false; // GUY - texture address clamping <<
file: engine\materials\materialDefinition.cpp
function: Material::initPersistFields()
after:
addProtectedField("colorMultiply", TypeColorF, Offset(mDiffuse, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see diffuseColor\n");add:
// GUY - texture address clamping >>
addField("edgeClamp", TypeBool, Offset(mAddressModeClamp, Material), MAX_STAGES,
"Forces the materials texture coordinates to clamp instead of wrap." );
// GUY - texture address clamping <<file: engine\materials\processedMaterial.cpp
function: ProcessedMaterial::_initPassStateBlock( RenderPassData *rpd, GFXStateBlockDesc & result )
change:
default:
{
result.samplers[i].textureColorOp = GFXTOPModulate;
result.samplers[i].addressModeU = GFXAddressWrap;
result.samplers[i].addressModeV = GFXAddressWrap;to:
default:
{
result.samplers[i].textureColorOp = GFXTOPModulate;
// GUY - texture address clamping >>
//result.samplers[i].addressModeU = GFXAddressWrap;
//result.samplers[i].addressModeV = GFXAddressWrap;
result.samplers[i].addressModeU = mMaterial->mAddressModeClamp[i] ? GFXAddressClamp : GFXAddressWrap;
result.samplers[i].addressModeV = result.samplers[i].addressModeU;
// GUY - texture address clamping <<Script changes to the material editor
To add the check box for enabling edge clamp for a texture stage, we need to make a couple of small modifications to the material editor scripts.
file: game\tools\materialEditor\gui\guiMaterialPropertiesWindow.ed.gui
around line 657,
after:
new GuiBitmapButtonCtrl() {
canSaveDynamicFields = "0";
Enabled = "1";
isContainer = "0";
Profile = "GuiDefaultProfile";
HorizSizing = "left";
VertSizing = "bottom";
position = "177 34";
Extent = "16 16";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "MaterialEditorGui.updateSpecMap(0);";
hovertime = "1000";
groupNum = "-1";
buttonType = "PushButton";
useMouseEvents = "0";
bitmap = "tools/gui/images/delete";
};
};add:
new GuiBitmapCtrl(){
position="6 0";
extent ="175 2";
HorizSizing = "width";
bitmap ="core/art/gui/images/separator-v";
};
new GuiCheckBoxCtrl() {
text = "Edge Clamp";
groupNum = "-1";
buttonType = "ToggleButton";
useMouseEvents = "0";
position = "5 5";
extent = "74 16";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "bottom";
profile = "GuiCheckBoxProfile";
visible = "1";
active = "1";
Command = "MaterialEditorGui.updateEdgeClamp($ThisControl.getValue());";
tooltipProfile = "GuiDefaultProfile";
tooltip = "Sets texture address mode to clamp.";
hovertime = "1000";
isContainer = "0";
internalName = "edgeClampCheckbox";
};file: game\tools\materialEditor\scripts\materialEditor.ed.cs
add this function:
function MaterialEditorGui::updateEdgeClamp(%this, %clamp)
{
%layer = MaterialEditorGui.currentLayer;
MaterialEditorGui.updateActiveMaterial("edgeClamp[" @ %layer @ "]", %clamp);
} file: game\tools\materialEditor\scripts\materialEditor.ed.cs
in function: MaterialEditorGui::guiSync( %this, %material )
after:
MaterialEditorPropertiesWindow-->minnaertTextEdit.setText((%material).minnaertConstant[%layer]);
add:
MaterialEditorPropertiesWindow-->edgeClampCheckbox.setValue((%material).edgeClamp[%layer]);
enjoy.
#2
08/18/2012 (10:12 am)
added missing code to the main resource.
#3
08/18/2012 (1:46 pm)
Awesome stuff! I'd had to make my textures bigger to avoid the image spinning on to the edges.
#4
You can prevent forum frustration by editing the text in a text file. Then copy from there. I know it is frustrating. Especially when I forget to do what I just said to do.
08/18/2012 (2:10 pm)
Nice work!You can prevent forum frustration by editing the text in a text file. Then copy from there. I know it is frustrating. Especially when I forget to do what I just said to do.
#5
I remember this happened in our "little project" when creating the artillery target markers.
08/18/2012 (7:27 pm)
Hey excellent work Guy!I remember this happened in our "little project" when creating the artillery target markers.
#6
08/19/2012 (4:51 am)
Great work Guy.
#7
08/19/2012 (11:31 am)
I like it! Now I wonder why it wasn't done that way in stock.
#8
@Michael, It's not really the appropriate mode for a default. If you want textures to 'tile', then it won't work. The rotating texture situation above is pretty much the only time you would want to use it.
@Marcos, indeed :) I was trawling the RTS code for decent snippets and thought this was worth mentioning.
08/20/2012 (11:48 am)
Glad it's useful.@Michael, It's not really the appropriate mode for a default. If you want textures to 'tile', then it won't work. The rotating texture situation above is pretty much the only time you would want to use it.
@Marcos, indeed :) I was trawling the RTS code for decent snippets and thought this was worth mentioning.
#9
08/21/2012 (6:36 am)
Nice work Guy - makes all the difference!
#10
09/25/2012 (3:04 pm)
This is pretty nifty. Not sure if I'll have occasion to use it, but I'll keep it in mind now that I know what to look for. 
Torque Owner Guy Allard
Default Studio Name