Replacing and stacking shaders for some objects


I'm mostly new to shaders, and this will likely show in this question.

I've got several objects in my scene whose rendering I wish to alter depending on how far they are from a character. I'd like to highlight reachable objects, darken unreachable ones, and highlight those the player can attack in a specific overlay.

These can be combined - for instance, we may have an object that's just too far away for "walking" distance, but that can be attacked with a ranged attack.

So far I've read Blurst's article on Replacement shaders and sat through and experimented with Unite '08's Shader programming course. I've also reviewed the shader's getting started and cg docs, which seem to cover the same topic as the Unite talk.

The latter gave me a good idea as to how to go about writing a specific shader, but I'm still at a loss as to how to stack the various operations. I can think of several options:

  • Creating various materials and swapping them.
  • Having a shader written in Cg that behaves differently based on material properties.
  • Using RenderWithShader to overlay a new shader on top of the existing one based on distance.

What would be the best approach here? Any pointers to basic tutorials as to how to perform this sort of operation? I have the distinct feeling that I'm missing a piece of the puzzle.

If an object is supposed to have the same basic shader (e.g. diffuse, toon, bumped specular) in all cases (short/long distance, ability to be attacked in a specific way) and you would only want it to be highlighted/darkened, the easiest way to go is just to alter the 'Main Color' of the material from the script:

if(withinWalkingDistance && canBeShot)
    renderer.material.color = withinWalkingDistanceColor * canBeShotColor;

Alternatively you can write your own shader with some custom properties, that would control the look of the material and update those properties from your scripts depending on the state of the object every time it changes.

If you'd like to completely change the looks of an object (no shading at all when immune to the attacks, toon shading otherwise), you can swap their materials just as easy:

	renderer.material = toonShadingMaterial;

(Or, again, write a custom shader that would be altering the shading style depending on the value of some property you set from your scripts, but you should go with the simple material swapping first.)

Unless you're looking for some very fancy effects, there's primarily no need to use replacement shaders in the scenario you described.