+4
Under review

Support for Terrain dependency shaders

Arda Güneş 11 years ago updated by Conor O'Kane 7 years ago 12
Currently, if you use a shader with Shader Forge, terrain patches will turn black when it switches to the low resolution basemap (maximum range 2k). This is most likely due to undefined dependency shaders inside the shader.

As seen here (blog post), adding these lines to the shader:

Dependency "AddPassShader" = "Custom/ToonTerrainAddPass"
Dependency "BaseMapShader" = "Toon/Lighted Outline"

Defines those shaders (AddPassShader may or may not be required). Adding some kind of support for these, would make Shader Forge fully compatible with the current terrain system. Pretty much everything works except for this.
Hi there is a way for use Shaderforge with terrains, look at this images:

Yes, that much it works, and here's an easier way for it: http://www.acegikmo.com/shaderforge/nodes/images/s...

Just use channel blend node and put the splat map on as the mask texture.

This post isn't about that however. If you read my first post, you'll see that I've mentioned Unity Terrain uses another shader for the low res basemap that it displays after a certain range. That range is called basemap distance, and only goes up to 2000 units max. Once you reach that range, if you don't have a dependency shader setup, terrain goes black.

This idea is about giving the ShaderForge the necessary tools, so that we can define our own dependency shaders somehow.
I have finally figured out the definite way of using SF with terrains. Link here, copy pasted the post below:

After getting frustrated with ready made terrain shader options, once again I tried to figure out how to do it with shader forge. This time, I think I succeeded.

TL;DR
You need to use the naming convention seen in the default shaders, you need to add a Dependency line at the end of the shader for correctly shading BaseMap, and you need to setup a SplatCount tag.

Long version:

You need to setup 2 shaders. FirstPass, and BaseMap. FirstPass is the normal shader you'll see and use. BaseMap is specifically for the low res version of the terrain. Basically, terrain fades to BaseMap after a certain distance for performance reasons. This distance is setup from terrain script inspector.

Textures and normal maps need to be named through Splat0...Splat3 and Normal0...Normal3, your masking texture must be named Control, you also need another texture slot called MainTex, and a color property called, Color.

Finally, you'll need to add SplatCount tag and the dependency line to the Firstpass shader, with a text editor.

Here's screenshots of my basic setup.

FirstPass diffuse chain
http://i.imgur.com/NIvzsUw.png

FirstPass normal chain
http://i.imgur.com/WUBzNCU.png

BaseMap shader basic setup
http://i.imgur.com/yDzicT3.png

Shader tags
http://i.imgur.com/P7VHe7f.png

Dependency setup
http://imgur.com/iR6zllv

The gotcha here is, the dependency shader name is the one you set from Shader Forge. First few times I've tried, I always thought it was a folder path. You can also access the Unity properties like Splat1, Control and so on from BaseMap shader.

I haven't tried more complex shaders with these, but this setup is basically all you need for using terrains with 4 textures. If you need more than 4, you need to create an AddPass shader, which is basically the same as the FirstPass shaders, but you don't need to edit it by hand, you just need to define it as a dependency shader, exactly the same way as BaseMap shader is defined.

Basically, Shader Forge just needs to add:

1) A way to define a BaseMap shader. This is literally just a string of the shader name.
2) A way to add SplatCount tag.

After that, there won't be any need to edit the shaders by hand to just add 2 lines.

Edit: Just realized I haven't added a working pic of it all. Here's a pic:
http://i.imgur.com/7ly8C4z.png

After doing all of the above, you just need to plug in an empty material of your shader, and that is it. As you can see, BaseMap shader is working, no black terrain tiles, even though BaseMap distance is at 0.
I can't seem to get normal maps working with terrain. The splats work great, but the terrain doesn't seem to be applying the normals. The shader preview in Shader Forge shows the normals taking effect, so I'm pretty confused. What did I forget to do?

Here's my chain: http://i.imgur.com/pBPdeMA.jpg
And here's the terrain: http://i.imgur.com/KCJIjqJ.png

No normals. :(
Figured out a temporary solution for getting normal maps to work with terrain. Replace this line (note that this line is in 2 places, so replace both):
float3 normalDirection = normalize(mul( normalLocal, tangentTransform )); // Perturbed normals
With:
float3 normalDirection = normalize( normalLocal )); // Perturbed normals
And the normal maps should work.
Oh, looks like you also have to get the UVs from the Splat input rather than the normals for the splat tile scale parameter to work for the normals.

i.e., replace
tex2D(_Normal0,TRANSFORM_TEX(node_#.rg, _Normal0))).rgb
with
tex2D(_Normal0,TRANSFORM_TEX(node_#.rg, _Splat0))).rgb
Would it be possible for you to share that shader with working normal maps? I've changed those lines you mentioned and it still doesn't work =/
Under review
It could be because he accidentally left in two parentheses in the first edit, where it should have been one, after nornalLocal
Unfortunately it isn't that, I fixed that error immediately =)
Alright. Not sure what error you're getting, nor what could be the fault, given that I haven't looked into the terrain shaders yet
+1
Nice one :)
Could you put up a tutorial on the Wiki, so others can find out how to do it?
Sure, I'll put up one tomorrow.