Color specular shader

Hello Unity community…heh that rimes well:smile:

I am wondering if there is any colored specular shader out there for Unity (specular map as colored specular texture in RGB mode not grayscale). If so i would be happy if someone could give me link for it. Also if anyone is using it i would like to know if this shader is optimised and it does not ruin performance too much, considering that it will be used on every model.

Also is Strumpy Shader Editor able to use colored specular maps? Is this shader editor optimised comparing to original Unity shaders? If not of what performance drop are we talking about?

Thank you for all answers in advance.

Colored specular for Unity 3.x, here. Works both in forward deferred rendering:

Shader "Surface/Colored Specular" {
Properties {
  _MainTex ("Texture", 2D) = "white" {}
  _SpecMap ("SpecMap", 2D) = "white" {}
}
SubShader {
	Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf ColoredSpecular

struct MySurfaceOutput {
	half3 Albedo;
	half3 Normal;
	half3 Emission;
	half Specular;
	half3 GlossColor;
	half Alpha;
};


inline half4 LightingColoredSpecular (MySurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
{
  half3 h = normalize (lightDir + viewDir);

  half diff = max (0, dot (s.Normal, lightDir));

  float nh = max (0, dot (s.Normal, h));
  float spec = pow (nh, 32.0);
  half3 specCol = spec * s.GlossColor;

  half4 c;
  c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * specCol) * (atten * 2);
  c.a = s.Alpha;
  return c;
}

inline half4 LightingColoredSpecular_PrePass (MySurfaceOutput s, half4 light)
{
	half3 spec = light.a * s.GlossColor;
	
	half4 c;
	c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
	c.a = s.Alpha + spec * _SpecColor.a;
	return c;
}


struct Input {
  float2 uv_MainTex;
  float2 uv_SpecMap;
};
sampler2D _MainTex;
sampler2D _SpecMap;
void surf (Input IN, inout MySurfaceOutput o)
{
  o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * 0.3;
  half4 spec = tex2D (_SpecMap, IN.uv_SpecMap);
  o.GlossColor = spec.rgb;
  o.Specular = 32.0/128.0;
}
ENDCG
}
Fallback "Diffuse"
}

This has some things simplified (i.e. specular power is hardcoded). Should be easy to add full capabilities of built-in specular shader, just with a colored gloss map.

1 Like

Thanks for help Arash, however i am not a programmer and i have no idea where do i need to put shader code to get it work or how to create shader in Unity.

Copy / paste into a new text file,
then save as “ColoredSpecular.shader”
then drag and drop the file into your project explorer.(unity)
then create newMaterial and , into the inspector select your shader (./Surface/Colored Specular)

here you are… enjoy.

1 Like

Isn’t it simpler to take a built-in specular surface shader and override _SpecColor for each pixel?

The built-in BlinnPhong lighting model declares _SpecColor outside the SurfaceOutput structure, as a uniform value. This means that you have to re-write the lighting model as Aras did in order to use a texture.

1 Like

This works pretty well. Am I still incorrect? :slight_smile:

Shader "Bumped ColoredSpecular" {
Properties {
	_Color ("Main Color", Color) = (1,1,1,1)
	_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
	_Shininess ("Shininess", Range (0.03, 1)) = 0.078125
	_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
	_BumpMap ("Normalmap", 2D) = "bump" {}
	
	_SpecTex ("Spec (RGB)", 2D) = "white" {}
}
SubShader { 
	Tags { "RenderType"="Opaque" }
	LOD 400
	
CGPROGRAM
#pragma surface surf BlinnPhong

sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _SpecTex;
float4 _Color;
//float4 _SpecColor;
float _Shininess;

struct Input {
	float2 uv_MainTex;
	float2 uv_BumpMap;
};

void surf (Input IN, inout SurfaceOutput o) {
	half4 tex = tex2D(_MainTex, IN.uv_MainTex);
	half4 spectex = tex2D(_SpecTex, IN.uv_MainTex);
	_SpecColor = spectex;
	
	o.Albedo = tex.rgb * _Color.rgb;
	o.Gloss = tex.a;
	o.Alpha = tex.a * _Color.a;
	o.Specular = _Shininess;
	o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}

FallBack "Specular"
}

Nobody has not answered if this given shader from Aras is optimised ,and also does it supports normal maps?

yes
no

Ah ok thanks. No normals maps is not option for me then.

Could someone writte or extend shader code that Aras wrotte for colored specular shader for/with normal too?

This should work:

Shader "Surface/Colored Specular Bumped" {
Properties {
  _MainTex ("Texture", 2D) = "white" {}
  _SpecMap ("SpecMap", 2D) = "white" {}
  _BumpMap ("Normalmap", 2D) = "bump" {}
}
SubShader {
	Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf ColoredSpecular

struct MySurfaceOutput {
	half3 Albedo;
	half3 Normal;
	half3 Emission;
	half Specular;
	half3 GlossColor;
	half Alpha;
};


inline half4 LightingColoredSpecular (MySurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
{
  half3 h = normalize (lightDir + viewDir);

  half diff = max (0, dot (s.Normal, lightDir));

  float nh = max (0, dot (s.Normal, h));
  float spec = pow (nh, 32.0);
  half3 specCol = spec * s.GlossColor;

  half4 c;
  c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * specCol) * (atten * 2);
  c.a = s.Alpha;
  return c;
}

inline half4 LightingColoredSpecular_PrePass (MySurfaceOutput s, half4 light)
{
	half3 spec = light.a * s.GlossColor;
	
	half4 c;
	c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
	c.a = s.Alpha + spec * _SpecColor.a;
	return c;
}


struct Input {
  float2 uv_MainTex;
  float2 uv_SpecMap;
  float2 uv_BumpMap;
};
sampler2D _MainTex;
sampler2D _SpecMap;
sampler2D _BumpMap;

void surf (Input IN, inout MySurfaceOutput o)
{
  o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * 0.3;
  half4 spec = tex2D (_SpecMap, IN.uv_SpecMap);
  o.GlossColor = spec.rgb;
  o.Specular = 32.0/128.0;
  o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}
Fallback "Diffuse"
}

gaustwick - you rock.

That is all.

Thanks :smile:

thanx Aras and gaustwick for this shader! and thx janpec for bring up this topic! im working on a game with alot of sci fi materials, and the default unity bump specular doesnt show the normal mapped effects well at all! this one is much better! its very similar to the Maya Blinn shader than i am used to, awesome job guys! xD

I was asked for a version of this shader that supported illumination maps, so I had a go, and added shininess and global colour parameters whilst I was there :slight_smile: The illumination map needs to be stuck in the specular map’s alpha channel.

Shader "Surface/Colored Specular Bumped with Illumination" {
Properties {
  _MainTex ("Texture", 2D) = "white" {}
  _SpecMap ("SpecMap(RGB) Illum(A)", 2D) = "white" {}
  _BumpMap ("Normalmap", 2D) = "bump" {}
  _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
  _Color ("Main Color", Color) = (1,1,1,1)
}
SubShader {
	Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf ColoredSpecular

struct MySurfaceOutput {
	half3 Albedo;
	half3 Normal;
	half3 Emission;
	half Specular;
	half3 GlossColor;
	half Alpha;
};


inline half4 LightingColoredSpecular (MySurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
{
  half3 h = normalize (lightDir + viewDir);

  half diff = max (0, dot (s.Normal, lightDir));

  float nh = max (0, dot (s.Normal, h));
  float spec = pow (nh, 32.0 * s.Specular);
  half3 specCol = spec * s.GlossColor;

  half4 c;
  c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * specCol) * (atten * 2);
  c.a = s.Alpha;
  return c;
}

inline half4 LightingColoredSpecular_PrePass (MySurfaceOutput s, half4 light)
{
	half3 spec = light.a * s.GlossColor;
	
	half4 c;
	c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
	c.a = s.Alpha + spec * _SpecColor.a;
	return c;
}


struct Input {
  float2 uv_MainTex;
  float2 uv_SpecMap;
  float2 uv_BumpMap;
};

sampler2D _MainTex;
sampler2D _SpecMap;
sampler2D _BumpMap;
half4 _Color;
half _Shininess;

void surf (Input IN, inout MySurfaceOutput o)
{
  half3 c = tex2D (_MainTex, IN.uv_MainTex).rgb * _Color.rgb;
  o.Albedo = c;
  half4 spec = tex2D (_SpecMap, IN.uv_SpecMap);
  o.GlossColor = spec.rgb;
  o.Emission = c * spec.a;
  o.Specular = _Shininess;
  o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}
Fallback "Diffuse"
}

And the same shader is in the attachments.

874072–32641–$colourspecularillumination.shader (1.7 KB)

The posted shaders are all very helpful for a school project that I am currently working on, thank you for the hard work all of you! ^^

I have one thing that is missing from these shaders that would make it perfect for me, I have another regular shader that forces two-sided rendering(turns off culling). I’ve made attempts at combining the two shaders however they just don’t seem compatable in any way(the double sided shader uses passes, while this shader doesn’t. not sure on the specifics behind each, but neither seemed to work in the other >.>).

The character I’m attempting to use this on has flat geometry that can be seen from both sides(cloak/ect.) and I would love to be able to use the colored specular shader with the double sided geometry if possible.

I have been trying for the last 2-3 hours with no success, how can I add Cutout with Cull Off to this Shader that you guys have come up with? BTW this is great and I am exited to be able to use!

This is what I am using, no Normals or Specularity do.

Shader "Transparent/Cutout/Diffuse" {
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}

SubShader {
    Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    LOD 200
    Cull Off

CGPROGRAM
#pragma surface surf Lambert alphatest:_Cutoff

sampler2D _MainTex;
fixed4 _Color;

struct Input {
    float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
    fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    o.Albedo = c.rgb;
    o.Alpha = c.a;
}
ENDCG
}

Fallback "Transparent/Cutout/VertexLit"
}

Attempting to use gaustwick’s Colored Specular Bumped shader that i pulled from this thread, but the object seems to be rendering much darker than when using other shaders. Is this normal?

A 90% white object is rendering a very dark grey color, other than that it seems to work great. When using the shader with added illumination included, the objects renders much more like it should. Any ideas as to what is causing this, or how to fix it? Should I just edit the shader w/ illumination and remove that property?

The dark effect comes from the albedo line: o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * 0.3;

Remove the “*0.3”, it doesn’t belong there.