Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Shaderlab "Dependency" property?

Discussion in 'Shaders' started by tanoshimi, Dec 4, 2013.

  1. tanoshimi

    tanoshimi

    Joined:
    May 21, 2013
    Posts:
    297
    Can anyone give me the exact usage and syntax of a "Dependency" shader as specified in lines 80-81 of the default terrain shader: Nature/Terrain/Diffuse. ?

    Unless I'm being blind, I couldn't find it mentioned anywhere in the Shaderlab reference at
    http://docs.unity3d.com/Documentation/Components/SL-Reference.html

    thanks in advance!
     
  2. tanoshimi

    tanoshimi

    Joined:
    May 21, 2013
    Posts:
    297
    Ok, I'll fill in some of the gaps I've found out so far myself, and try to be a bit more specific on the bits I'm still stuck on... ;)

    So it seems that "Dependency" shaders are only used to control the somewhat arcane terrain shading system. I understand this to be determined by three shaders, as follows:

    FirstPassShader (i.e. the "main" shader used by a custom material attached to the terrain)
    The FirstPassShader is used for accurate rendering of near-terrain, and is applied to terrain that lies closer to camera than "Base Map Dist." specified in the terrain inspector. It has properties for the control texture (_Control), and four textures (_Splat0 - _Splat3), which are automatically populated by the terrain engine with the first four terrain textures. It specifies additional "Dependency" shaders such as the BaseMapShader and AddPassShader described here.

    BaseMapShader
    All textures assigned to a terrain are combined (based on the control texture) into a single combined base texture, with resolution specified by the "Base Texture Resolution" parameter in the terrain inspector. This base texture is used as a fallback by old graphics cards that can't use the FirstPassShader, and also for any terrain that is further away than "Base Map Dist." (also specified in the inspector). This single texture is rendered using the Dependency "BaseMapShader" specified in the firstpassshader assigned to the terrain material.

    AddPassShader
    The FirstPassShader only handles four texture slots (whose weights are controlled by the RGBA channels of the control texture). Therefore, if you have greater than four terrain textures, the Dependency "AddMapShader" specified in the firstpassshader is called for each subsequent batch of 4 textures, and its output additively blended with the output of the previous shader. It's basically exactly the same as FirstPassShader, but with blendmode set by decal:add

    What I still don't understand...
    It is easy to verify that the AddPassShader gets called only when there are greater than four textures (by, e.g. deliberately introducing an error in the AddPassShader - everything will be fine until you add the fifth texture at which point the whole terrain turns magenta). What I don't understand is that, if I don't specify Dependency "AddPassShader" in my custom shader (and set Base Map Dist. to max to ensure that I'm not seeing the base map instead), I still see all my terrain textures being blended. I had expected to not see the effects of textures 5+, or perhaps get an error. Is there an additional default AddPassShader that kicks in?

    Also, what about replacing the shader used for, say the trees? I've tried making use of the following Dependency shader settings found in the supplied terrain shader, replacing with my own, but they seem to have no effect?

    Dependency "Details0"
    Dependency "Details1"
    Dependency "Details2"
    Dependency "Tree0"
     
    Kevlis, Usmith and zwcloud like this.
  3. fenderrex

    fenderrex

    Joined:
    Sep 9, 2015
    Posts:
    4
    I only just started shader programming a few days ago
    but this reminded me of what i read here https://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html that makes me look at #pragma multi_compile to explain whats going on...
    hope this helps:)
     
  4. fox3fire

    fox3fire

    Joined:
    Aug 20, 2017
    Posts:
    3
    My guess is the same as yours. The terrain engine must added some code to the currently attached surface shader so that there will always be a line like Dependency "AddPassShader" = "THE DEFAULT ONE". However, if you write this line by yourself, it will check whether it's valid. If it's not, Unity will still add this line. But if it is valid, then it will use that. In my case, I was doing some procedural virtual texture on unity terrain, so I have to change the terrain material on the fly. I tried both vertex/fragment shader and surface shader and it seems this mechanism only works when I'm using surface shaders. I wanted the simple surface shader with all the shadows and lightings done for me, so I'm sticking with surface shader. I found a way around which is not so efficient. I created a dummy surface shader to be the "AddPassShader"(it seems only a surface shader will work). In that shader, I used decals:blend instead of decals:add and set the ouput color and alpha to zero, which basically render nothing to the screen. This solution works but it will create at least one extra draw call as I understand it. Considering there are tons of triangles in a terrain, this solution is not good at all.