Error in Heightshader

Hi everybody,

I found a shader by forum-member Efge which colors a mesh based on the y-position of the vertices on UnityAnswers ( shader RGB colour based on y-value vertex - Questions & Answers - Unity Discussions ) but get this error: not enough temporary registers, needs 9 (compiling for flash). This is the code (by Efge)

    Shader "Global-Mapper" {
    Properties {
    _PeakColor ("PeakColor", Color) = (0.8,0.9,0.9,1)
    _PeakLevel ("PeakLevel", Float) = 300
    _Level3Color ("Level3Color", Color) = (0.75,0.53,0,1)
    _Level3 ("Level3", Float) = 200
    _Level2Color ("Level2Color", Color) = (0.69,0.63,0.31,1)
    _Level2 ("Level2", Float) = 100
    _Level1Color ("Level1Color", Color) = (0.65,0.86,0.63,1)
    _WaterLevel ("WaterLevel", Float) = 0
    _WaterColor ("WaterColor", Color) = (0.37,0.78,0.92,1)
    _Slope ("Slope Fader", Range (0,1)) = 0
    }
    SubShader {
    Tags { "RenderType" = "Opaque" }
    Fog { Mode Off }
    Tags { "LightMode" = "Always" }
    CGPROGRAM
    #pragma surface surf Lambert vertex:vert
    struct Input {
    float3 customColor;
    float3 worldPos;
    };
    void vert (inout appdata_full v, out Input o) {
    o.customColor = abs(v.normal.y);
    }
    float _PeakLevel;
    float4 _PeakColor;
    float _Level3;
    float4 _Level3Color;
    float _Level2;
    float4 _Level2Color;
    float _Level1;
    float4 _Level1Color;
    float _Slope;
    float _WaterLevel;
    float4 _WaterColor;
    void surf (Input IN, inout SurfaceOutput o) {
    if (IN.worldPos.y >= _PeakLevel)
    o.Albedo = _PeakColor;
    if (IN.worldPos.y <= _PeakLevel)
    o.Albedo = lerp(_Level3Color, _PeakColor, (IN.worldPos.y - _Level3)/(_PeakLevel - _Level3));
    if (IN.worldPos.y <= _Level3)
    o.Albedo = lerp(_Level2Color, _Level3Color, (IN.worldPos.y - _Level2)/(_Level3 - _Level2));
    if (IN.worldPos.y <= _Level2)
    o.Albedo = lerp(_Level1Color, _Level2Color, (IN.worldPos.y - _WaterLevel)/(_Level2 - _WaterLevel));
    if (IN.worldPos.y <= _WaterLevel)
    o.Albedo = _WaterColor;
    o.Albedo *= saturate(IN.customColor + _Slope);
    }
    ENDCG
    }
    Fallback "Diffuse"
    }

I hope someone help me solve this, thanks!

This problem has appeared on the forum a ton of times in the past few months.

There’s nothing specifically wrong, except the shader uses 9 registers, while flash supports a maximum of 8.
Thus your shader won’t compile, nor will it be available, for the flash platform.
nothing more, nothing less.

you can safely ignore this warning as long as you dont plan to use the flash platform :slight_smile:

Hi Annihlator,

Thanks! I’m changing the code so it can layer more colors than the original 5. Adding one extra color goes without problems, adding the the 7th color gets errors again. This is the code:

Shader "Custom/HeightShader3" {
    Properties {
    _PeakColor ("PeakColor", Color) = (0.8,0.9,0.9,1)
    _PeakLevel ("PeakLevel", Float) = 500
    _Level5Color ("Level5Color", Color) = (0.75,0.33,0,1)
    _Level5 ("Level5", Float) = 400
    _Level4Color ("Level4Color", Color) = (0.75,0.43,0,1)
    _Level4 ("Level4", Float) = 300
    _Level3Color ("Level3Color", Color) = (0.75,0.53,0,1)
    _Level3 ("Level3", Float) = 200
    _Level2Color ("Level2Color", Color) = (0.69,0.63,0.31,1)
    _Level2 ("Level2", Float) = 100
    _Level1Color ("Level1Color", Color) = (0.65,0.86,0.63,1)
    _WaterLevel ("WaterLevel", Float) = 0
    _WaterColor ("WaterColor", Color) = (0.37,0.78,0.92,1)
    _Slope ("Slope Fader", Range (0,1)) = 0
    }
    SubShader {
    Tags { "RenderType" = "Opaque" }
    Fog { Mode Off }
    
    CGPROGRAM
    #pragma surface surf Lambert vertex:vert
    struct Input {
    float3 customColor;
    float3 worldPos;
    };
    void vert (inout appdata_full v, out Input o) {
    o.customColor = abs(v.normal.y);
    }
    float _PeakLevel;
    float4 _PeakColor;
    float _Level5;
    float4 _Level5Color;
    float _Level4;
    float4 _Level4Color;
    float _Level3;
    float4 _Level3Color;
    float _Level2;
    float4 _Level2Color;
    float _Level1;
    float4 _Level1Color;
    float _Slope;
    float _WaterLevel;
    float4 _WaterColor;
    void surf (Input IN, inout SurfaceOutput o) {
    if (IN.worldPos.y >= _PeakLevel)
    o.Albedo = _PeakColor;
    if (IN.worldPos.y <= _PeakLevel)
    o.Albedo = lerp(_Level5Color, _PeakColor, (IN.worldPos.y - _Level5)/(_PeakLevel - _Level5));
    if (IN.worldPos.y <= _Level5)
    o.Albedo = lerp(_Level4Color, _Level5Color, (IN.worldPos.y - _Level4)/(_Level5 - _Level4));
    if (IN.worldPos.y <= _Level4)
    o.Albedo = lerp(_Level3Color, _Level4Color, (IN.worldPos.y - _Level3)/(_Level4 - _Level3));
    if (IN.worldPos.y <= _Level3)
    o.Albedo = lerp(_Level2Color, _Level3Color, (IN.worldPos.y - _Level2)/(_Level3 - _Level2));
    if (IN.worldPos.y <= _Level2)
    o.Albedo = lerp(_Level1Color, _Level2Color, (IN.worldPos.y - _WaterLevel)/(_Level2 - _WaterLevel));
    if (IN.worldPos.y <= _WaterLevel)
    o.Albedo = _WaterColor;
    o.Albedo *= saturate(IN.customColor + _Slope);
    }
    ENDCG
    }
    Fallback "Diffuse"
    }

Sorry for the probably silly question again but I hope somebody can help…

If you want to just avoid warnings you can add this line:
#pragma exclude_renderers flash

If you want to run it on flash than it can be done a different way. Here, this should work in flash (and DX11, which original shader didn’t).
I offloaded some calculations to the vertex shader, which should be faster as well, unless you have more vertices than pixels. Should work the same as original, unless I screwed something.

  Shader "Global-Mapper-optimized" {
    Properties {
	    _PeakColor ("PeakColor", Color) = (0.8,0.9,0.9,1)
	    _PeakLevel ("PeakLevel", Float) = 300
	    _Level3Color ("Level3Color", Color) = (0.75,0.53,0,1)
	    _Level3 ("Level3", Float) = 200
	    _Level2Color ("Level2Color", Color) = (0.69,0.63,0.31,1)
	    _Level2 ("Level2", Float) = 100
	    _Level1Color ("Level1Color", Color) = (0.65,0.86,0.63,1)
	    _WaterLevel ("WaterLevel", Float) = 0
	    _WaterColor ("WaterColor", Color) = (0.37,0.78,0.92,1)
	    _Slope ("Slope Fader", Range (0,1)) = 0
    }

    SubShader {

    Tags { "RenderType" = "Opaque" }

    Fog { Mode Off }

    Tags { "LightMode" = "Always" }

    CGPROGRAM

    #pragma surface surf Lambert vertex:vert

    struct Input {
    	float2 customColorAndLevel;
    	float3 color3;
    	float3 color2;
    	float3 color1;
    };

    float _PeakLevel;
    float4 _PeakColor;
    float _Level3;
    float4 _Level3Color;
    float _Level2;
    float4 _Level2Color;
    float _Level1;
    float4 _Level1Color;
    float _Slope;
    float _WaterLevel;
    float4 _WaterColor;

    void vert (inout appdata_full v, out Input o) {
		UNITY_INITIALIZE_OUTPUT(Input,o);
		float3 worldPos = mul(_Object2World, v.vertex).xyz;
		
    	float customColor = abs(v.normal.y)  + _Slope;
    	float level = worldPos.y;
		
		o.color1 = lerp(_Level1Color, _Level2Color, (level - _WaterLevel)/(_Level2 - _WaterLevel));
		o.color2 = lerp(_Level2Color, _Level3Color, (level - _Level2)/(_Level3 - _Level2));
		o.color3 = lerp(_Level3Color, _PeakColor, (level - _Level3)/(_PeakLevel - _Level3));
		
	    o.customColorAndLevel.x = customColor;
	    o.customColorAndLevel.y = level;
    }

    void surf (Input IN, inout SurfaceOutput o) {
    	float customColor = IN.customColorAndLevel.x;
    	float level = IN.customColorAndLevel.y;
    	
    	o.Albedo = _PeakColor;
    	
	    if (level <= _PeakLevel)
	    	o.Albedo = IN.color3;

	    if (level <= _Level3)
	    	o.Albedo = IN.color2;
	    		    	
	    if (level <= _Level2)
	    	o.Albedo = IN.color1;
	
	    if (level <= _WaterLevel)
	    	o.Albedo = _WaterColor;
	
	    o.Albedo *= saturate(customColor);
    }

    ENDCG
    }

    Fallback "Diffuse"
    }

Now I look like, I’m really bored.

Hi Cician,

Thanks for making the code compatible with flash and dx11, it works great! I’m trying to add more colors but above 6 colors I get multiple errors again:
Material doesn’t have a float or range property ‘_Slope’
Material doesn’t have a color property ‘_WaterColor’
etc…

This is your code which I adjusted for the extra colors:

Shader "Custom/HeightShaderForum" {

    Properties {

        _PeakColor ("PeakColor", Color) = (0.8,0.9,0.9,1)
		_PeakLevel ("PeakLevel", Float) = 500       
        _Level5Color ("Level5Color", Color) = (0.75,0.33,0,1)
        _Level5 ("Level5", Float) = 400        
        _Level4Color ("Level4Color", Color) = (0.75,0.43,0,1)
        _Level4 ("Level4", Float) = 300
        _Level3Color ("Level3Color", Color) = (0.75,0.53,0,1)
        _Level3 ("Level3", Float) = 200
        _Level2Color ("Level2Color", Color) = (0.69,0.63,0.31,1)
        _Level2 ("Level2", Float) = 100
        _Level1Color ("Level1Color", Color) = (0.65,0.86,0.63,1)
        _WaterLevel ("WaterLevel", Float) = 0
        _WaterColor ("WaterColor", Color) = (0.37,0.78,0.92,1)
        _Slope ("Slope Fader", Range (0,1)) = 0
    } 

    SubShader { 

    Tags { "RenderType" = "Opaque" } 

    Fog { Mode Off } 

    Tags { "LightMode" = "Always" } 

    CGPROGRAM 

    #pragma surface surf Lambert vertex:vert 

    struct Input {

        float2 customColorAndLevel;        
        float3 color5;                
        float3 color4;
        float3 color3;
        float3 color2;
        float3 color1;
    }; 

    float _PeakLevel;
    float4 _PeakColor;    
    float _Level5;
    float4 _Level5Color;    
    float _Level4;
    float4 _Level4Color;
    float _Level3;
    float4 _Level3Color;
    float _Level2;
    float4 _Level2Color;
    float _Level1;
    float4 _Level1Color;
    float _Slope;
    float _WaterLevel;
    float4 _WaterColor; 

    void vert (inout appdata_full v, out Input o) {
        UNITY_INITIALIZE_OUTPUT(Input,o);
        float3 worldPos = mul(_Object2World, v.vertex).xyz;       

        float customColor = abs(v.normal.y)  + _Slope;
        float level = worldPos.y;

       

        o.color1 = lerp(_Level1Color, _Level2Color, (level - _WaterLevel)/(_Level2 - _WaterLevel));        
        o.color2 = lerp(_Level2Color, _Level3Color, (level - _Level3)/(_Level3 - _Level2));        
        o.color3 = lerp(_Level3Color, _Level4Color, (level - _Level4)/(_Level4 - _Level3));
        o.color4 = lerp(_Level4Color, _Level5Color, (level - _Level5)/(_Level5 - _Level4));
        o.color5 = lerp(_Level5Color, _PeakColor, (level - _Level5)/(_PeakLevel - _Level5));       

        o.customColorAndLevel.x = customColor;
        o.customColorAndLevel.y = level;
    } 

    void surf (Input IN, inout SurfaceOutput o) {
        float customColor = IN.customColorAndLevel.x;
        float level = IN.customColorAndLevel.y;       

        o.Albedo = _PeakColor;       

        if (level <= _PeakLevel)
            o.Albedo = IN.color5;      
                     
        if (level <= _Level5)
            o.Albedo = IN.color4;           
            
        if (level <= _Level4)
            o.Albedo = IN.color3;

        if (level <= _Level3)
            o.Albedo = IN.color2;

        if (level <= _Level2)
            o.Albedo = IN.color1;

        if (level <= _WaterLevel)
            o.Albedo = _WaterColor;   

        o.Albedo *= saturate(customColor);
    }

    ENDCG
    } 

    Fallback "Diffuse"
    }

Any idea what I’m doing wrong…? Thanks for all the help!

The problem is that Shader Model 2 is limited in number of values you can interpolate between vertex and fragment shader. That’s why i put customColor and level together.

All the <<Material doesn’t have a … property>> errors are consequence of the real error somewhere in the log. They pop up when you select an object with the material (pretty annoying).

If you really need flash you can add even more hacks to get more colors or change approach entirely.
For example you can add the fourth color in vertex shader if you put customColor and level as z values of two of the colors. But it gets messy.

Hi Cician,

Thanks for the help, I really appreciate it! Flash compatibility is not that important for me, I would prefer more colors for sure. So would using Shader Model 3 be an option? Sorry, I’m really a shader-newbie… Thanks again!

Yup, switching to SM3 simplifies things. Beware though, there are still many SM2 level gpus around (pre sandy bridge intel igps, mobile). Look up some stats on the net and choose based on your target audience.

You can add these lines at the start of CGPROGRAM:
#pragma exclude_renderers flash
#pragma target 3.0

Then you can add more colors. Note SM3 does have its limits: for example 8 texture interpolators. But your original method should work for many more colors.
Also note there are other ways to do what you want. For example lookup textures, vector arrays and such.

Hi Cician,

It works great, thanks again for all your help!!!