Tutorial Using Custom Materials to apply a normal map to Cloth - PrismaticFlower/shaderpatch GitHub Wiki

Intro

This tutorial assumes you have already followed the integration instructions for Shader Patch's tools. And also that you have preexisting modding knowledge, if you don't know how to create a custom side for a map go and learn how to do that first.

So I thought about what would be a neat example of how Shader Patch's materials can let you do things you can't normally do is to use them apply a normal map and specular lighting to cloth. So that's exactly what we're going to. I'm going to use rep_inf_clonecommander.msh and it's cloth but you can use any model that has cloth on it.

We'll be using this texture later on in the tutorial so if you're wanting to follow it word for word download this. Also make a custom rep side ready to munge, as that is what we'll be editing.

Sample cloth normal map.

How Shader Patch's materials work

So first I want to quickly explain some terminology.

Game Texture

This is any normal texture that the game has and uses to draw things. This is what any texture you've normally been using will end up as. Shader Patch can see these textures but has no knowledge of their name.

Shader Patch Texture

Or just "Patch Texture" for shorthand. This a texture that the game can not see but Shader Patch can and unlike Game Textures Shader Patch knows the name of Patch Textures.

Custom Material

A user supplied configuration that selects the material type to use when drawing something, configures it and defines what Patch Textures to use as well.


Now that's a very basic high level overview of those concepts but it should be all you need to have fun playing around with Shader Patch's materials.

But we must sadly drop that nice high level abstraction of how things work for a bit. So Shader Patch's Custom Materials are actually built completely on top of Game Textures.

When Shader Patch's tools munge a material file it's actually just turning it into a special Game Texture. And when it sees the game go to use this Game Texture it steps in and setups everything needed to draw the user's Custom Material. The inverse also applies when it sees that the special Game Texture is no longer being used to draw objects, it restores the normal render state of the game.

What this means is that Custom Materials are applied using the names of Game Textures. This may not make much sense now but it will later.

Structuring our Stuff

Now when dealing with Custom Materials the number of files making up our side or world can grow by a lot. So before we do anything else we're going to help ourselves out and adjust the folder structure for our side a little bit. I found the making the following directories and using the accompanying pattern helpful in the past.

  • textures/ - Patch Textures used by Custom Materials go in here. Game Textures may also go in here provided the same image file is used by a Patch Textures.
  • materials/ - All Custom Materials go in here.
  • stock_textures/ - In cases where we have to modify the Patch Texture such that it is no longer usable as the original Game Texture (for the non-Shader Patch copy of the side/map) we place the original Game Texture in here.

Setting up our Textures

Onto to the fun part now. First let's move rep_inf_clonecommander_cape.tga (and it's .option file) from msh/ to textures/. Next each texture we want to expose to Shader Patch, thus turning it into a Patch Texture, needs a .tex file. .tex files are similar in a way to .option files in that they control how a texture will be munged (it's format, type, etc) they are also not optional.

So let's start by making a new file in textures/ called rep_inf_clonecommander_cape.tga.tex. Then we want to copy this into it.

Type: image

sRGB: no
PremultiplyAlpha: no
CompressionFormat: BC7

You can learn more about texture definitions over here but there are two important things we're doing here.

First because this is a diffuse texture and we're not going to use it with Shader Patch's HDR rendering we set sRGB to no so that we get "correct" sampling. If we were going to use it with HDR rendering (once again because it is a diffuse texture) we would set it to yes.

Then because we don't have an alpha channel we set PremultiplyAlpha to false and we set CompressionFormat to "BC1". Patch Textures recieve better compression than Game Textures and have access to more compression formats, see the documentation for a complete listing.

Now remember the normal map from the top of the post? Download it, put it in textures/ and make sure it is called rep_inf_clonecommander_cape_normalmap.png. Then once again make a new file in textures/ named rep_inf_clonecommander_cape_normalmap.png.tex and put the following in it.

Type: normalmap

sRGB: no
PremultiplyAlpha: no
CompressionFormat: BC7_ALPHA

Again there are some things I want to draw attention to here. First sRGB is once again set to no because normal maps are never sRGB encoded. Next PremultiplyAlpha is set to no because although our normal map has an alpha channel it contains the specular gloss map and premultiplying that would be an error. (And premultiplying alpha with a normal map would be a significant error in any event.) The CompressionFormat we've chosen is "BC3" as it let's us have a high quality alpha channel in our image. If this normal map didn't have a gloss map we would likely want to choose BC5 as our CompressionFormat as it would let us get a bit more quality out of our compression at no increase in storage costs over BC7_ALPHA.

And we're done setting up our textures. Hopefully that was fairly easy to understand and follow.

Defining our Material

One last step before we can get to testing our material. In materials/ make a file called rep_inf_clonecommander_cape.mtrl and fill it with this.

Type: normal_ext

Material:
   UseSpecularLighting: yes
   IsDynamic: yes

   DiffuseColor:  [1.0, 1.0, 1.0]
   SpecularColor: [1.0, 1.0, 1.0]

   SpecularExponent: 64.0
   GlossMapWeight: 1.0
   
Textures:
   DiffuseMap: rep_inf_clonecommander_cape
   NormalMap: rep_inf_clonecommander_cape_normalmap

There are a few things to break down here. First we set the Type, we're going to be using the normal_ext material type.

Next we define the Material properties, most of these should be self explanatory. And you can check out descriptions of them over here.

Textures should also be self explanatory we reference the textures the Type needs. As we learn from here we need to specify DiffuseMap and NormalMap so that is exactly what we do. Note that we leave both the image file extension out and the .tex file extension out.

Lua Changes

Finally before we test we just need to edit our map's Lua script to load the Shader Patch version of the lvl when Shader Patch is installed and load the normal lvl when it isn't.

First at the top of our mission script we want to add the following code snippet.

-- Load the Shader Patch API
ReadDataFile("shader_patch_api.script")
ScriptCB_DoFile("shader_patch_api")

-- Check if Shader Patch is installed and if it is test the version.
local useShaderPatch = gSP_Installed and SP_TestVersion(1, 7, 0)

So say in the case of our example we had the following line in our map's script to load up our custom clone commander.

ReadDataFile("dc:SIDE\\rep.lvl;rep_inf_ep3_officer")

We would want to change it to this.

-- First we test to se if Shader Patch is installed.
if useShaderPatch then
   -- If it is we load the Shader Patch version of our side.
   -- Note the addition of 'SP\\'.
   ReadDataFile("dc:SIDE\\SP\\rep.lvl;rep_inf_ep3_officer")
else 
   -- Otherwise we load the normal version of our side.
   ReadDataFile("dc:SIDE\\rep.lvl;rep_inf_ep3_officer")
end

That code should be simple enough to understand. In a large mod project you may want to invest some time to create some abstractions around it but that is an exercise for the reader. This should suffice to hit the ground running with Shader Patch's Custom Materials.

Testing Our Material

Finally we get to do the exciting thing and test the material! In our case I would say it's fine demonstration of Custom Materials, it may not convince you to run out and apply specular to the clone commander in your mod but it gets the point across.

The result of our work.