Shader Compile Errors

Hello everyone, I am trying to compile a shader but it seems that it is not going to cooperate with me. Currently these are the errors I am getting;

Compiled shader code uses too many instruction slots (2439). Max. allowed by the target (ps_2_x) is 512.
Compiling Fragment program
Platform defines: UNITY_NO_SCREENSPACE_SHADOWS UNITY_ENABLE_REFLECTION_BUFFERS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING SHADER_API_MOBILE UNITY_COLORSPACE_GAMMA

and

Compiled shader code uses too many arithmetic instruction slots (2439). Max. allowed by the target (ps_2_x) is 512. Consider increasing optimization level to reduce instruction count.
Compiling Fragment program
Platform defines: UNITY_NO_SCREENSPACE_SHADOWS UNITY_ENABLE_REFLECTION_BUFFERS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING SHADER_API_MOBILE UNITY_COLORSPACE_GAMMA

This is the shader in question:

Shader "RainbowThree" {
    Properties{
        _Saturation("Saturation", Range(0.0, 1.0)) = 0.8
        _Luminosity("Luminosity", Range(0.0, 1.0)) = 0.5
        _Spread("Spread", Range(0.5, 10.0)) = 3.8
        _Speed("Speed", Range(-10.0, 10.0)) = 2.4
        _TimeOffset("TimeOffset", Range(0.0, 6.28318531)) = 0.0
    }
        SubShader{
        Pass{
        CGPROGRAM

#pragma vertex vert
#pragma fragment frag

//#include "UnityCG.cginc"

inline fixed4 RGBtoHSL(fixed4 rgb) {
        fixed4 hsl = fixed4(0.0, 0.0, 0.0, rgb.w);

        fixed vMin = min(min(rgb.x, rgb.y), rgb.z);
        fixed vMax = max(max(rgb.x, rgb.y), rgb.z);
        fixed vDelta = vMax - vMin;

        hsl.z = (vMax + vMin) / 2.0;

        if (vDelta == 0.0) {
            hsl.x = hsl.y = 0.0;
        }
        else {
            if (hsl.z < 0.5) hsl.y = vDelta / (vMax + vMin);
            else hsl.y = vDelta / (2.0 - vMax - vMin);

            float rDelta = (((vMax - rgb.x) / 6.0) + (vDelta / 2.0)) / vDelta;
            float gDelta = (((vMax - rgb.y) / 6.0) + (vDelta / 2.0)) / vDelta;
            float bDelta = (((vMax - rgb.z) / 6.0) + (vDelta / 2.0)) / vDelta;

            if (rgb.x == vMax) hsl.x = bDelta - gDelta;
            else if (rgb.y == vMax) hsl.x = (1.0 / 3.0) + rDelta - bDelta;
            else if (rgb.z == vMax) hsl.x = (2.0 / 3.0) + gDelta - rDelta;

            if (hsl.x < 0.0) hsl.x += 1.0;
            if (hsl.x > 1.0) hsl.x -= 1.0;
        }

        return hsl;
    }

    inline fixed hueToRGB(float v1, float v2, float vH) {
        if (vH < 0.0) vH += 1.0;
        if (vH > 1.0) vH -= 1.0;
        if ((6.0 * vH) < 1.0) return (v1 + (v2 - v1) * 6.0 * vH);
        if ((2.0 * vH) < 1.0) return (v2);
        if ((3.0 * vH) < 2.0) return (v1 + (v2 - v1) * ((2.0 / 3.0) - vH) * 6.0);
        return v1;
    }

    inline fixed4 HSLtoRGB(fixed4 hsl) {
        fixed4 rgb = fixed4(0.0, 0.0, 0.0, hsl.w);

        if (hsl.y == 0) {
            rgb.xyz = hsl.zzz;
        }
        else {
            float v1;
            float v2;

            if (hsl.z < 0.5) v2 = hsl.z * (1 + hsl.y);
            else v2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);

            v1 = 2.0 * hsl.z - v2;

            rgb.x = hueToRGB(v1, v2, hsl.x + (1.0 / 3.0));
            rgb.y = hueToRGB(v1, v2, hsl.x);
            rgb.z = hueToRGB(v1, v2, hsl.x - (1.0 / 3.0));
        }

        return rgb;
    }

        fixed _Saturation;
    fixed _Luminosity;
    half _Spread;
    half _Speed;
    half _TimeOffset;

    struct vertexInput {
        float4 vertex : POSITION;
        float4 texcoord0 : TEXCOORD0;
    };

    struct fragmentInput {
        float4 position : SV_POSITION;
        float4 texcoord0 : TEXCOORD0;
        fixed3 localPosition : TEXCOORD1;
    };

    fragmentInput vert(vertexInput i) {
        fragmentInput o;
        o.position = mul(UNITY_MATRIX_MVP, i.vertex);
        o.texcoord0 = i.texcoord0;
        o.localPosition = i.vertex.xyz; +fixed3(0.5, 0.5, 0.5);
        return o;
    }

    fixed4 frag(fragmentInput i) : SV_TARGET{
        fixed2 lPos = i.localPosition / _Spread;
    half time = _Time.y * _Speed / _Spread;
    half timeWithOffset = time + _TimeOffset;
    fixed sine = sin(timeWithOffset);
    fixed cosine = cos(timeWithOffset);
    //fixed hue = (lPos.x * sine + lPos.y * cosine) / 2.0;
    //fixed hue = (lPos.x * 0 - lPos.y) / 2.0;
    fixed hue = (-lPos.y) / 2.0;
    hue += time;
    [unroll(357)]
    while (hue < 0.0) hue += 1.0;
    [unroll(328)]
    while (hue > 1.0) hue -= 1.0;
    fixed4 hsl = fixed4(hue, _Saturation, _Luminosity, 1.0);
    return HSLtoRGB(hsl);
    }

        ENDCG
    }
    }
        FallBack "Diffuse"
}

Thank you.

Okay, there’s two ways to do this. One is just fixing the error, which is to add:

#pragma target 4.0

However that limits the shader to requiring DX11 or OpenGL 3.2, and I suspect does not actual make the shader do what you want.

Looking at the shader this makes me think you have a significant misunderstanding of how shaders work. This section specifically:

That is what is generating most of those 2500 instructions, and is functionally equivalent to the following single line (at least for values between -327 and 328):

hue = frac(hue);

So what exactly are you trying to do?

Currently I am trying to make a gradient rainbow effect that horizontally moves across models. The reason I used the [unroll(n)] there is because previously it wouldn’t let me compile due to the fact that I wanted the effect of the rainbow to last forever.

Adding in hue = frac(hue); and #pragma target 4.0 seems to have made it so I don’t get any errors when I compile in Unity. The only other question I have is how exactly does the entire compilation process work? I thought it was pretty straight forward until I looked into the file which I thought was the compiled shader and inside it said

NOTE: This is *not* a valid shader file, the contents are provided just for information and for debugging purposes only.

Trying to load this file also gave me the errors of Parse error: syntax error, unexpected TVAL_ID, expecting TOK_SETTEXTURE or '}' and Shader is not supported on this GPU (none of subshaders/fallbacks are suitable) Thanks again.

#pragma target 4.0 was only necessary with your original shader since had such a high instruction count. Nearly 2500 instructions is a huge number for any shader, and target 4.0 allows for a nearly unlimited instruction count, but going over 1000 instructions in a single shader is kind of insane even for a modern high end PC game.

Just adding the frac() line should have been enough to drop the instruction count to 40~60 or so (and really a scrolling rainbow could be done in maybe 15 instructions).

The “compile” button in the Unity editor is, just as that message states, just for debugging. Unity automatically compiles the shader when the editor loads or the file is changed on disk. It’ll compile it again when building your application as it’ll compile specifically for the platform your building for. Basically you should be leaving the .shader file looking like what you had in your original post and likely ignoring the compile button and it’s output entirely until you understand shaders more thoroughly.

I find this to be a great resource for first time Unity shader devs.

3 Likes

Thank you for clearing that up.

So, the way that this project needs to work is that I am not actually building it but it is being compiled into an asset bundle which doesn’t seem to build the shader. Is there a way I can now compile it? I have only been seeing things about HLSL shaders and such and I didn’t know if it was the same thing.

By “not building the shader” I assume you mean it’s showing pink? Sounds like the shader isn’t being included with the asset bundle. Search the forums for that, you should find the solution.

Well actually, it seems it is showing up white as though it is there but not loading in-game (AKA: Idk but not pink). The developer of the game wrote his own C# script for making asset bundles for the game so people like me can mod it. He hasn’t released a lot of documentation on how more advanced things like shaders are to be set-up correctly so I have been assuming it must be something you should be able to do with Unity experience alone.