#include custom ".cginc" files.

Hi, im trying to #include a custom .cginc file. Kinda like you can include “UnityCG.cginc”.

I found this link: How can I make my own shader include file (.cginc or .glslinc)? - Questions & Answers - Unity Discussions

In that link they say you can use the path directory, like so:: "#include “Assets/path/to/your/shader.cginc”.
I can’t get this to work. Ive tried putting my custom “.cginc” file in the Root Assets folder and others.
No path seems to work… am I missing something??

I keep mine in the same directory as my shaders that reference it - seems to work perfectly fine. Haven’t tried it in other directories though :confused:

1 Like

Ok its not working no matter what I try. Are you on WIndows or Mac?

Im including a blank “ShaderBase.cginc” file. Does there have to be something in it? I didn’t think there did…

All shaders are in the root “Assets” folder.
Ive tried: “#include “ShaderBase.cginc””
And:: “#include “Assets/ShaderBase.cginc””
Neither work.

Here is my test shader, very basic-----------------------

Shader “Test/Diffuse”
{
Properties
{
_Diffuse (“Diffuse”, 2D) = “white” {}
}

SubShader
{
Tags { “RenderType” = “Opaque” }
CGPROGRAM
//#include “UnityCG.cginc” <<< THIS WORKS >>>
//#include “ShaderBase.cginc” <<< THIS DOES NOT WORK >>>
#pragma surface surf SimpleLambert

half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half distance)
{
half NdotL = dot (s.Normal, lightDir);
return half4(s.Albedo, s.Alpha) * _LightColor0 * NdotL * distance;
}

struct Input
{
float2 uv_MainTex;
};
sampler2D _Diffuse;

void surf (Input IN, inout SurfaceOutput o)
{
o.Albedo = tex2D (_Diffuse, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback “Diffuse”
}

I’m on Windows.

Ehr, if you’re including a blank one… there’d be no way to know if it works or not.

Try writing a function in it and then call it in your shader.

Hmmm well i’m totally confused as to why its not working if something so simple is working for you.
Would you mind posting a simple Shader and Shader #include file source that works on your end?? Maybe then I can see what i’m doing wrong…

I tried putting this method in my “ShaderBase.cginc”… still does not work::

inline float3 WorldSpaceViewDir( in float4 v )
{
return v.xyz;
}

Does anybody have a simple working example of some source I could look at to try and figure out what is going on with my shades??

Ive written HLSL for years now… I don’t understand how I could have so much troubled with such a simple issue.

I’ve got this in my include, which is called “ExplorationLighting.cginc” ;

struct SurfaceOutputCharacter {
	fixed3 Albedo;
	fixed3 Normal;
	fixed4 AnisoDir;
	fixed3 Emission;
	fixed3 Specular;
	fixed Alpha;
};

sampler2D _AnisoRamp, _RampTex;
float _Cutoff;
inline fixed4 LightingExplorationCharacter (SurfaceOutputCharacter s, fixed3 lightDir, fixed3 viewDir, fixed atten)
{
	fixed3 h = normalize(lightDir + viewDir);
	fixed NdotL = saturate(dot(s.Normal, lightDir));
	float nh = saturate(dot(s.Normal, h));
	
	fixed HdotA = dot(normalize(s.Normal + s.AnisoDir.rgb), h);
	float2 anisoUV = float2(HdotA, 0.5);
	anisoUV -= 0.2;
	fixed3 aniso = pow(tex2D(_AnisoRamp, anisoUV), s.Specular.g * 64) * s.Specular.r;
	
	float spec = pow(nh, s.Specular.g * 128) * s.Specular.r;
	spec = saturate(lerp(spec, aniso, s.AnisoDir.a));

	float3 ramp = tex2D(_RampTex, float2((NdotL * 0.5 + 0.5) * atten)).rgb * s.Specular.b;

	fixed4 c;
	c.rgb = pow((((pow(s.Albedo + ramp, 2.2) * _LightColor0.rgb * NdotL) * (_LightColor0.rgb * (1 - spec))) + (_LightColor0.rgb * spec)) * (atten * 2), 0.45);
	c.a = 1;
	clip(s.Alpha - _Cutoff);
	
	return c;
}

float _Cutoff;
inline fixed4 LightingExplorationStandard (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten)
{
	fixed3 h = normalize(lightDir + viewDir);
	
	fixed NdotL = saturate(dot(s.Normal, lightDir));
	
	float nh = saturate(dot(s.Normal, h));
	float spec = pow(nh, s.Gloss * 128) * s.Specular;

	fixed4 c;
	c.rgb = pow(((pow(s.Albedo, 2.2) * _LightColor0.rgb * NdotL) * ((1 - spec) * _LightColor0.rgb) + (_LightColor0.rgb * spec)) * (atten * 2), 0.45);
	c.a = s.Alpha;
	clip(s.Alpha - _Cutoff);
	
	return c;
}

struct SurfaceOutputAniso {
	fixed3 Albedo;
	fixed3 Normal;
	fixed4 AnisoDir;
	fixed3 Emission;
	half Specular;
	fixed Gloss;
	fixed Alpha;
};

sampler2D _AnisoRamp;
float _AnisoOffset;
inline fixed4 LightingExplorationAniso (SurfaceOutputAniso s, fixed3 lightDir, fixed3 viewDir, fixed atten)
{
	fixed3 h = normalize(lightDir + viewDir);
	float nh = saturate(dot(s.Normal, h));

	fixed NdotL = saturate(dot(s.Normal, lightDir));
	fixed HdotA = dot(normalize(s.Normal + s.AnisoDir.rgb), h);

	float2 anisoUV = float2(HdotA, 0.5);
	anisoUV.x += _AnisoOffset;
	fixed3 aniso = pow(tex2D(_AnisoRamp, anisoUV), s.Gloss * 128) * s.Specular;

	fixed3 spec = fixed3(pow(nh, s.Gloss * 128) * s.Specular);
	spec = lerp(spec, aniso, s.AnisoDir.a);

	fixed4 c;
	c.rgb = pow(((pow(s.Albedo, 2.2) * _LightColor0.rgb * NdotL) * ((1 - spec) * _LightColor0.rgb) + (_LightColor0.rgb * spec)) * (atten * 2), 0.45);
	c.a = 1;
	clip(s.Alpha - _Cutoff);
	return c;
}

struct SurfaceOutputEyes {
	fixed3 Albedo;
	fixed3 Normal;
	fixed3 Normal2;
	fixed3 Emission;
	half Specular;
	fixed Gloss;
	fixed Alpha;
};

inline fixed4 LightingExplorationEyes (SurfaceOutputEyes s, fixed3 lightDir, fixed3 viewDir, fixed atten)
{
	fixed3 h = normalize(lightDir + viewDir);
	
	fixed NdotL = saturate(dot(s.Normal, lightDir));
	
	float nh = saturate(dot(s.Normal2, h));
	float spec = pow (nh, s.Gloss * 128) * s.Specular;
	
	fixed4 c;
	c.rgb = pow(((pow(s.Albedo, 2.2) * _LightColor0.rgb * NdotL) * ((1 - spec) * _LightColor0.rgb) + (_LightColor0.rgb * spec)) * (atten * 2), 0.45);
	c.a = 1;
	return c;
}

inline fixed4 LightingExplorationRiver (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten)
{	
	fixed3 h = normalize(lightDir + viewDir);
	float nh = saturate(dot (s.Normal, h));
	float spec = pow(nh, 128);
	
	fixed4 c;
	c.rgb = _LightColor0.rgb * spec * (atten * 2);
	c.a = 1;
	return c;
}

And this in my shader;

/*
Ramp at light terminator.

Masked anisotropic highlight.

Alphatested.
*/

Shader "Exploration/Character" {
	Properties {
		_Color ("Main Color", Color) = (1,1,1,1)
		_MainTex ("Diffuse (RGB)", 2D) = "white" {}
		_SpecularTex ("Specular (R) Gloss (G) Null (B)", 2D) = "gray" {}
		_BumpMap ("Normal (Normal)", 2D) = "bump" {}
		_RampTex ("SSS Ramp (RGB)", 2D) = "black" {}
		_AnisoDirection ("Anisotropic Direction (RGB)", 2D) = "black" {}
		_AnisoRamp ("Anisotropic Ramp (RGB)", 2D) = "black" {}
		_Cutoff ("Alpha Cut-Off Threshold", Range(0,1)) = 0.5
	}

	SubShader{
		Tags {"RenderType" = "Opaque"}
		CGPROGRAM
			#include "ExplorationLighting.cginc"
			#pragma surface surf ExplorationCharacter fullforwardshadows
			#pragma target 3.0
			
			struct Input
			{
				float2 uv_MainTex;
			};
			
			sampler2D _MainTex, _SpecularTex, _NormalTex, _AnisoDirection;
				
			void surf (Input IN, inout SurfaceOutputCharacter o)
			{
				fixed4 albedo = tex2D(_MainTex, IN.uv_MainTex);
				o.Albedo = albedo.rgb;
				o.Alpha = albedo.a;
				o.AnisoDir = tex2D(_AnisoDirection, IN.uv_MainTex);
				o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
				o.Specular = tex2D(_SpecularTex, IN.uv_MainTex).rgb;
			}
		ENDCG
	}
	FallBack "Transparent/Cutout/VertexLit"
}

Both files reside in the same directory. Works perfectly.

1 Like

Tnx so much, that helped me rule out that I wasn’t going crazy…Well I did kinda go crazy trying to figure this out LOL.

Ok all my code was fine all along.
Because im using VisualStudio I had created my “ShaderBase.cginc” file I used for testing as a “.cs” file then changed its extension to “.cginc”… Somehow this added 4 extra byes onto the file that you can’t get rid of. If you create the file as “.txt” to begin with, you don’t have this issue.

Why creating “.cs” file vs a “.txt” file in visual studios are any different in size is very odd.
The error in Unity3d was “Bad characters in the source file at line 0”.

NOTE for others:: DO NOT, create your “.cginc” file as “.cs” files and change the ext, because it WILL NOT work.

Tnx again :wink:

1 Like

Haha, weird. Must be something to do with the encoding. Glad you got it sorted.

Thanks I can confirm a similar problem.

It failed for me when I created a File.New.File.Text Document in Visual Studio renaming the file extension to .cginc. Seems Visual Studio mucks it up regardless of how the file is created.

I created and pasted in the initial code externally via Windows Notepad and all is well.

I notice the file created is UTF-8 without BOM compared to UTF-8 that Visual Studio seems to be defaulting to in my environment.

1488333--82950--$Untitled.png

2 Likes

I’ve always created them via right clicking in the directory and clicking new text document, then renaming the extension :stuck_out_tongue:

Man am I glad I found this thread - saved me hours of frustration.

I can confirm that creating a .cginc file by renaming a .cs file created in VS will result in an invalid file. Beugnen nailed it by pointing out the difference in the UTF-8 formats: If the file has the BOM set, then it will be invalid for .cginc files.

Oddly enough, this seems to only apply to .cginc files - if you create an actual .shader inside Unity the BOM bytes will be set at the beginning of the file, which won’t cause any problems. If you then change the extension to .cginc, it won’t work. Creating it as a text file in Windows explorer (like Farfarer mentioned) will result in a valid file (without the BOM) - other than that, I think you could simply strip the BOM using a hex editor.

Another possible approach is to select one of the .cginc files Unity provides, duplicate it, modify it and drag it in the project.

If you need to include a .cginc file called myFile.cginc that is in folder1 in a shader file that lies in folder 2

folder1
|
–folder2

Add the following line in the file in folder 2

#include “…/myFile.cginc”

If the myFile.cginc is two folders up in the hierarchy, then you can do

#include “…/…/myFile.cginc”

Thanks! It solved my problem too.

This is a bit of a gravedigging, but I’d just like to explain why I think it doesn’t work with BOM set

Basically, BOM is adding bytes to the beginning of the file, like a header, that tells any editor that “This is a UTF-8 file”

My guess is that the #include does a binary copy of the source, before giving it to the compiler, and also include the extra BOM-bytes. However, when you do #include they get included somewhere where they’re NOT supposed to be, and thus results in invalid characters in the final text-file.

I would be grateful for explaining this:
Suppose I have one shader file and two files:

  • myFile1.cginc
  • myFile2.cginc
    both localized in the “included” subfolder.
    I include the first file in my shader with line:
    #include “included/myFile1.cginc”
    How to include myFile2.cginc inside myFile1.cginc?
    with
    #include “included/myFile2.cginc” (relative to shader file)
    or
    #include “myFile2.cginc” (relative to myFile1.cginc) ???

#include “myFile2.cginc”;
You add a “…/” as"prefix" for each folder hierarchy level that is above the current file folder level.

I tried this and I’m getting the error: “Can’t find include file.”