Using custom keywords in cg shaders

I need to use custom keywords in my cg shader, but so far I can’t get them working. I looked at the Water4 shader and scripts - since it uses custom keywords - and tried to setup my files the same way, but so far I can’t get it to work.

Here’s my shader( my custom keyword is in the “surf” function ):

Shader "SRShaders/Bumped Specular (1 Directional Light)" {
Properties {
	_Shininess ("Shininess", Range (0.03, 1)) = 0.078125
	_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
	_BumpMap ("Normalmap", 2D) = "bump" {}
}
SubShader { 
	Tags { "RenderType"="Opaque" }
	LOD 250
	
CGPROGRAM
#pragma surface surf MobileBlinnPhong exclude_path:prepass nolightmap noforwardadd halfasview novertexlights


inline fixed4 LightingMobileBlinnPhong (SurfaceOutput s, fixed3 lightDir, fixed3 halfDir, fixed atten)
{
	fixed diff = max (0, dot (s.Normal, lightDir));
	fixed nh = max (0, dot (s.Normal, halfDir));
	fixed spec = pow (nh, s.Specular*128) * s.Gloss;
	
	fixed4 c;
	c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten*2);
	c.a = 0.0;
	return c;
}

sampler2D _MainTex;
sampler2D _BumpMap;
half _Shininess;


struct Input {
	float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
	fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
	o.Albedo = tex.rgb;
 
    #ifdef IS_SIMPLE  // My custom keyword
    o.Albedo *= 4;
    #endif
 
	o.Gloss = tex.a;
	o.Alpha = tex.a;
	o.Specular = _Shininess;
	o.Normal = UnpackNormal (tex2D(_BumpMap, IN.uv_MainTex));
}
ENDCG
}

FallBack "Mobile/VertexLit"
}

And here’s my script:

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class ShaderManager : MonoBehaviour {
 
    // Store the camera
    public Camera cam;
    public Texture2D tex;
    
    
    // Before the object gets rendered
    public void OnWillRenderObject ( ) {

        cam = Camera.current;
        
        if( !cam )
            return;

        Shader shader = renderer.sharedMaterial.shader;
    }
    
    void OnEnable() {
        
        Shader.EnableKeyword("IS_SIMPLE"); // My custom keyword
    }

    void OnDisable() {
        
        Shader.DisableKeyword("IS_SIMPLE"); // My custom keyword
    }
}

I should mention that the script is NOT in the same folder as the shader, and that I am not using Unity Pro. I’m using Unity 3.5 iPhone basic.

I can’t find any documentation on this issue, so I need a shader guru’s help hehe :slight_smile:

Thanks in advance!

Stephane

1 Answer

1

Hi you will notice that the water shader does this at the start:

#pragma multi_compile WATER_REFRACTIVE WATER_REFLECTIVE WATER_SIMPLE

What this is saying is that the compiler needs to generate a permutation of the shader for each of those defines. There will be 3 combinations generated. One each for WATER_REFLECTIVE, WATER_REFRACTIVE, and WATER_SIMPLE.

The shader compiler is very explicit about the permutations it generates. So if you have multiple flags that you want on / off use multiple multi_compile pragmas.

Doing:

#pragma IS_SIMPLE IS_ADVANCED
#pragma LIGHTING_ON LIGHTING_OFF

Will generate these permutations:

IS_SIMPLE LIGHTING_ON
IS_SIMPLE LIGHTING_OFF
IS_ADVANCED LIGHTING_ON
IS_ADVANCED LIGHTING_OFF

You do not need to use a given flag.

In your example you would do:

#pragma IS_SIMPLE IS_ADVANCED

This would generate two permutations, one with IS_SIMPLE set one with IS_ADVANCED set. You don’t need to use IS_ADVANCED.

Let me know if you have any further troubles.

Thanks for the answer stramit! I am not home right now so I can't give it a try, but I will tonight when I get home. Quick question: when you say "Doing: #pragma IS_SIMPLE IS_ADVANCED #pragma LIGHTING_ON LIGHTING_OFF", how come it's not "#pragma multi_compile"? Do i need to define first "#pragma multi-compile IS_SIMPLE IS_ADVANCED" and then do "#pragma IS_SIMPLE IS_ADVANCE"? Just a little confused, sorry if this seems like a stupid question!

Just ran into this problem, helping out anyone who comes along here. You need to put multi_compile on all your pragmas. So that would be: #pragma multi_compile IS_SIMPLE IS_ADVANCED #pragma multi_compile LIGHTING_ON LIGHTING_OFF