QB8EdN.png

While working on your shaders you inevitably will need to connect your shaders/shader effects/code to the Sandbox Editor.

There are a number of features that you may want to add to the material editor, so you can adjust your shader parameters using sliders in Sandbox, or create a checkbox to turn on and off a shader feature that you have defined in your code. The following are all the known features you have at your disposal.


Material Editor: New Shader Feature

This topic covers everything you need to know in order to add a shader feature to the material editor, and how to hook it up to your shader code.
-
*Files you need to have open:
EngineVer/engine/shaders/Illum.ext
-

NOTE: engine ver represents the folder of your current build, i.e. 5.4.0, 5.2.1 etc

Step 1:

Go to the end of the Illum.ext file, and copy one of the properties that exist already(helps to avoid common typo's). And paste it at the bottom of the file. See example below for a proper new shader feature:

Property
{
    Name = %NEW_FEATURE
    Mask = 0x200
    Property (New Feature)
    Description (Does a really cool thing!)
    DependencyReset = $TEX_Normals
 
}

If you don't understand what this code does, see the code breakdown I make HERE

Step 2:

Now save the Illum.ext file, close and restart Sandbox if you had it open. Now you should see your custom shader feature checkbox inside of the material editor.

Troubleshooting:
-

1:

If your checkbox unchecks itself instantly when you clicked it, either you set a DependancyReset in your feature as in the example in this article, or your bitmask is already used/invalid. These are the two issues I have run into while trying this out myself.

2:
If your checkbox is permanently turned on, as with the above issue this appears to be caused by a bitmask that is already taken, or an invalid one.

3:
Here are all known shader flags




Material Editor: Exposing Parameters

This topic covers what you will need to not only create the variables that you want to expose to the material editor, but also how to expose and use them in the engine.

-
*Files you need to have open:
EngineVer/engine/shaders/HWScripts/CryFX/Illum.cfx
EngineVer/engine/shaders/HWScripts/CryFX/CommonZpass.cfi
-
NOTE: engine ver represents the folder of your current build, i.e. 5.4.0, 5.2.1 etc

Step 1:

In the Illum.cfx file search for "Tweakables", and you should see groups of code that all look something like this:

#if %OFFSET_BUMP_MAPPING
half ObmDisplacement
<
  register = REG_PM_PARAM_0.y;
  string UIWidget = "slider";
  string UIName = "OBM Displacement";
  float UIMin = 0.0;
  float UIMax = 0.025;
  float UIStep = 0.001;
> = 0.004;
#endif

-
If you don't know what parts, or all of this code actually does check out the code breakdown I created for it:
EXAMPLE CODE BREAKDOWN
-
This code is defining a PARAMETER, basically it is a variable that you want to use inside of your shader code, that needs to also be tweakable by your artists. These will show up in the material editor "Shader Params" section.
-
pMd5bv.jpg

-

Step 2:

The second thing you will need to do if you are creating your own Parameters and exposing them, is you will need to create a new REG_PM_PARAM register. Please read the EXAMPLE CODE BREAKDOWN for the example code shown above. The process is detailed near the bottom of the breakdown page.

Step 3:

Now that you have created a new REG_PM_PARAM register, you can now use it in your custom parameter code. See example below of a custom Parameter set:

#if %FUZZY_SURFACE
 
    half FuzzyPower
    <
      register = REG_PM_PARAM_8.x;
      stringUIHelp = "Sets the power of the effect as a whole";
      string UIName = "Fuzzy Power";
      string UIWidget = "slider";
      float UIMin = 0.0;
      float UIMax = 5.0;
      float UIStep = 0.01;
    > = 1.5;
 
    half FuzzyEdgeBrightness
    <
      register = REG_PM_PARAM_8.y;
      stringUIHelp = "Sets the power of the Edge Brightness Effect";
      string UIName = "Fuzzy Edge Brightness";
      string UIWidget = "slider";
      float UIMin = 0.0;
      float UIMax = 10.0;
      float UIStep = 0.01;
    > = 5.0;
 
    half FuzzyCenterDarkness
    <
      register = REG_PM_PARAM_8.z;
      stringUIHelp = "Sets the amount of fresnel AO effect";
      string UIName = "Fresnel AO";
      string UIWidget = "slider";
      float UIMin = 0.0;
      float UIMax = 3.0;
      float UIStep = 0.01;
    > = 1.0;
 
#endif

Notice that each of these custom parameters is using the .x, .y, .z suffix on the REG_PM_PARAM_8 register. That is because each register has four "channels": ".xyzw." So you can have up to four parameters hooked into a single RE_GPM_PARAM register.

Once again, if you are confused at all by the above example code, please look at the code breakdown for answers.

Step 4:

In your shader code, inside of the CommonZPass.cfi file for example, you can construct a half3 or half4 (depending on the number of parameters your exposing from the REG_PM_PARAM) that includes all of your parameters which you just defined in the Illum.cfx.

using the previous example, this is what that would look like:

//Constructs the vector which has the PARAMS defined in the Illum.cfx
half3 fuzzyParams = half3(FuzzyPower, FuzzyEdgeBrightness, FuzzyCenterDarkness);

-
Here is where I hook these into my shader code (notice the .xyz component selections):
// Power the results by parameter to be able to adjust the power of the effect
half3 fresnelPower = pow(fresnelEffectInverted.xyz, fuzzyParams.x);
 
// Multiply by EdgeBrightness parameter, allows control over how bright the edge effect is
half3 fresnelEdgeBrightness = mul(fresnelPower.xyz, fuzzyParams.y);
 
    // Multiply by Darkening Effect Power, and then invert it to ensure its always on the interior of shape
half3 fresnelDirectionalDarken = mul(fresnelEffect.xyz, fuzzyParams.z);
half3 fresnelDirectionalDarkenInverted = 1 - fresnelDirectionalDarken.xyz;



Material Editor: Custom Texture Slot

This article assumes that you have already created a custom shader feature checkbox in the Illum.ext file. See THIS to learn how to set those up.

  • Files you will need to open:

EngineVer/engine/shaders/HWScripts/CryFX/Illum.cfx
EngineVer/engine/shaders/HWScripts/CryFX/CommonZpass.cfi
EngineVer/engine/shaders/HWScripts/CryFX/FXSamplerDefs.cfi
-
NOTE: engine ver represents the folder of your current build, i.e. 5.4.0, 5.2.1 etc

Step 1:

Open all three files in your IDE of choice (I use VS2015, and/or Notepad ++ with a dark theme)

Step 2:


Go to Illum.cfx around line: 428, or use CTRL + F and search for "Samplers"

Example of a proper CUSTOM sampler:

#if %FUZZY_SURFACE && !%BLENDLAYER || !%DIRTLAYER
Texture2D fuzzyTex : register(t9)
<
  UIName = "Fuzzy Mask Map";
  UIDescription = "Fuzzy mask map for fuzzy surface feature";
> = TM_Custom;
#else
    #undefine %FUZZY_SURFACE
 
#endif

If you don't know what parts, or all of this code actually does check out the code breakdown I created for it:
EXAMPLE CODE BREAKDOWN
-

Step 3:


Save your work, and reload the Editor just in case.
-
Congratulations you should now have a custom slot in the material editor to load your textures into your shader! If you followed this code exactly (including the naming) your material editor should have your custom sampler showing when you tick your shader feature box:
0HSMgP.jpg

Here is some example code as to how you would then bring that texture into your custom shader code:

half4 fuzzyMap = GetCustomTex(fuzzyTex, IN.baseTC.xy);

The GetCustomTex() function is defined in engineVer/engine/shaders/HWScripts/CryFX/Common.cfi line 170. Basically it returns your custom texture sampler (by variable name In this case "fuzzyTex) and requires that you give it the texture coordinates in .xy format as the second variable.

It is then stored in the half4 for use in your shader code.

Troubleshooting:
-

1:

if you are changing a primary texture slot (height, albedo, normals, opacity) there is a very good chance that it will refuse to rename. It appears this is a safety precaution, but im not sure. If that is the case you need to go into FXSamplerDefs.cfi and change that slots #define like the following I did for my Macrotexture slots:

#if %MACROTEXTURES
    #define SPECULARMAP           Texture2D   macro_normal         : register(t2)       <UIName = "Macro Normal 2">     = TM_Specular;
#else
    #define SPECULARMAP           Texture2D   specularTex         : register(t2)                                    = TM_Specular;
#endif