Discoveries - kajupe/FFGear GitHub Wiki
Tile Textures
Tile Textures are a type of Array texture that come in two variants, norm(als) and orb. Different tiles are mapped over different parts of the material to add extra detail such as fabric texturing or chain-links or scales.
There are 64 possible tile textures though not all are in use. The norm and orb variants always pair up, so if you have norm tile 3 you also have orb tile 3.
Mapping
Tile Textures are affected by four values: Scale U, Scale V, Rotation and Shear.
Scale U and V is, much like with the normal Mapping node in blender, inverse scale. So larger values mean the texture tiles more times resulting in smaller details.
Rotation rotates them all together (shocking I know). This happens around the 0,1 UV coordinate.
Shear shears them all together (also shocking). The base of this is where V is 1, so the top of the UV coordinates do not move.
I believe the order of these doesn't matter, but just in case it does I did Shear > Rotation > Scaling, which looks identical to in-game.
An important thing to note is that the values in the .mtrl file are not presented in this format, but are instead in a transformation matrix that you need to decompose. I stole all the math on how to do that from Penumbra, and I barely understand it, but it works. Go look there, or just steal FFGear's function if you want a python version.
Shear is by far the trickiest of these:
- If your data is coming directly from the .mtrl file, you need to invert the shear values by -1 since the game does it backwards compared to Blender.
- Convert degrees to radians by multiplying them by pi and dividing by 180. Or use the built in math operation.
- Subtract the UV's V channel from 1, then multiply that by the tangent of the shear radians.
- Add that to the UV's U channel, then use that as the new U and leave V as-is, use the original input.
Rotation isn't as bad:
- Convert the rotation degrees to radians and invert them by multiplying by -1.
- Use that as the Angle in a Vector Rotate node. Its type should be Axis Angle and the Center should be set to (0,1,0) with the Axis at (0,0,1).
- Since its possible to get negative values (which we don't want) Add 2 then Modulo 1, for safety.
You'll notice that at the start of both of these I subtract 1000. This is because since I'm getting the rotation and sheer values (which can be negative) through color ramps (which can't be negative) I add 1000 in the code before putting it in Blender, knowing I can later subtract 1000 in the material to get my negative values back.
Scale is very straightforward:
- Scale the vectors using a Mapping node, the scale values are the Scale U and V values as X and Y with no adjustments needed.
- Add some large number to avoid negative values, I used 18000.
- Modulo by 1
Doing this will give you correctly positioned UV "squares" with regular 0-1 coordinates. I have all the Tile Textures in a one-texture grid, and map those 0-1 coordinates to a smaller slice of that texture depending on which tile I want.
You can look at the node groups yourself to gain a better understanding if needed!
Channel Use
How are the norm and orb textures used in the shader?
To be quite honest, I don't fully know, but with some trial and error (and some educated guessing) I got something working that at least functions similarly enough to be acceptable in my opinion.
If you are unfamiliar with using textures as data, a texture has the channels Red, Green, Blue and Alpha (RGBA), and each is just a value between 0 and 1.
NORM
The R and G channels here are just the normal map, as expected. Just be sure to set the B channel to a constant 1 before using it as such. This is combined with the regular normal map for the material? With what formula? I don't know, but a really simple way to combine normal maps is using the Overlay blend mode. FFGear uses a more complicated setup that essentially does the same thing but lets you control the strength of both normal maps, based on this tutorial.
The B and A channels have some sort of data in them but I don't know what it's used for, and FFGear just leaves them unused.
ORB
The name "ORB" is a bit of a clue since it's similar to "ORM", which is commonly used in 3D graphics and stands for "Occlusion, Roughness, Metallic". So "ORB" is likely "Occlusion, Roughness..." and what seems to be "Blackness". FFGear leaves R (the Occlusion) unused since I couldn't get it looking very good and didn't find it necessary for a good-looking material.
G is used as a roughness-mult, with some kinda formula I cooked up and don't remember why it works anymore. You can see it in the shader if you're curious.
B and A both have similar-ish looks and A is noticeably higher resolution than B. FFGear uses both for darkening, as does the game (I think). B seems to be darkening that happens always. A seems to be darkening that only happens on metallic areas, so no wonder this shit was so hard to figure out when it's that obscure. FFGear uses the metallic value as a factor to blend between A if it is metallic and 1 if it's not, then multiplies that with B. That is then used as Ambient Occlusion, either on the Diffuse color or after everything else as just a mixed in pitch-black shader, which seems to be how the game does it.
Sphere Textures
Sphere Textures are round textures used to add cheap fake reflections, and other effects like iridescence.
Mapping
If you look at one of these spherical images on just a sphere-model in-game, you'll notice that they try to aim themselves slightly away from the center of the screen, and it always faces the camera. So it's very much a screen-space effect that depends on the facing of the geometry, so it's probably using screen-space normals as UVs somehow.
To get these in Blender you can just plug your normal vectors into a Vector Transform node converting vectors from World to Camera-space. That places 0,0 in the middle of the object though which won't work for UVs, it's in the range -1 to 1 along both axis now. So just add 1 and divide by 2 to make it usable UV coordinates. That's it!
Material Use
If you turn off all lights in-game you'll still see the sphere textures bright as day, so the game likely just adds them over everything else with no shading (except for accounting for the alpha). Doing the same is really easy in Blender, just using an Add Shader node. And mix in transparency afterwards. FFGear also has the option to add it onto the diffuse coloring instead, if you're making a dark scene and the sphere textures look odd.