- Home /
How to make a light only emit speculars ?
Hello !
I'm trying to find a way to make so that my 3d mesh is lit only by specular light, and reflects no diffuse light at all. I know there is an option in Maya lights to separate diffuse and specular emmision, and to disable independently one or the other one. Is there a method to do the same in Unity ? Or maybe someone knows how to solve my problem in other way ?
This is almost certainly going to be a situation where you need custom shaders
What color will appear in the diffuse area? Black? Transparent?
Hey ! Thanks for these fast answers !
@ blueLED : I have a specular map in the alpha channel of a specular shader, which is applied to my 3D mesh. I want that black areas of this specular texture appears black on the 3D mesh, like it is no lighted at all.
@ VesuvianPrime : I'm begining on Unity, and I know nothing about custom shaders. Can you explain to me a more precise method with a custom shader ?
See my reply below which constains an example of such a shader.
Answer by CHPedersen · Dec 15, 2014 at 02:11 PM
I found this interesting, so I wrote a custom shader that does it:
Shader "Custom/SpecularOnly" {
Properties {
_SpecColor ("Specular Color", Color) = (1,1,1,1)
_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf SpecularOnly
uniform half _Shininess;
inline fixed4 LightingSpecularOnly (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
half3 h = normalize (lightDir + viewDir);
float nh = max (0, dot (s.Normal, h));
float spec = pow (nh, s.Specular*128.0) * s.Gloss;
fixed4 c;
c.rgb = (_LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);
c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;
return c;
}
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
o.Albedo = float4(0,0,0,1);
o.Gloss = 1;
o.Specular = _Shininess;
}
ENDCG
}
FallBack "Diffuse"
}
A shader that displays only specular highlights is simply a shader where all other lighting contributions have been omitted, i.e. it has no diffuse contribution, no emissive and no ambient. So I went to the file Lighting.cginc in the Unity install dir and copied the default BlinnPhong Lighting function, then simply removed the diffuse component from it and used that instead as a custom Lighting function in the above shader.
Setting the Albedo to black removes the ambient component, which would've otherwise typically rendered the rest of the object dark gray.
This shader renders full black except where the specular highlight is. That gets whatever color you set on the material.
Notice, by the way, that the above shader displays the same visual result as using the standard, built-in specular shader, and then just setting the $$anonymous$$ain Color to 0,0,0. That's the same as disabling the diffuse component, since the Specular color has its own color picker in that $$anonymous$$aterial.
Thanks a lot CHPedersen for your interest !
Your message asks me for specify a little the effect I'm trying to obtain : I'm working to get a painterly CG render in Unity. So, I created a painterly color texture for my 3D mesh. To get as closer as possible to a painting, I painted directly the diffusion and occlusion shadows on this texture, to not use these CG render shadows. So I choosed to use the "Self-Illu$$anonymous$$" shader with this texture, 'cause it generates no diffusion shadows at all (the mesh appears at his full color, whatever its angle with the camera or the ambient-light). Then I created a black&white map with brushes strokes, and I want that a 3D light lights the mesh only in the white areas, and let the black areas unlit. So I thought that use this map as a specular map would be a good solution, by turning off the diffuse light. But maybe someone knows a better way ?
Well CHPedersen, I created a new shader, and copied-pasted your script in it. I applied this custom shader to the material connected to my 3D mesh (this material has the color texture, with specular map in alpha channel, connected to it). But so far, I didn't manage to get the result that you described. I obtained only a full black mesh, which appears when it is lit by the light, like in diffuse mode. But none of my textures of color or specular seem to be used.
I know nothing about custom shader/material, so it is likely that I made a bad manipulation. Can you explain to me how to use your custom shader ?
That description represents a whole slew of additional functionality your initial question text did not include. $$anonymous$$y shader doesn't do any of that. It uses no textures whatsoever, because I didn't know that was a requirement. It does purely what you asked for: displays specular highlights, and nothing else at all. Your above description is a rather complex shader.
I guess you could add a texture for the specular map with the strokes, and multiply the highlight with the value read from this texture, and then texture the rest of the object with a normal texture map, with the painting in it. That would get close.
I'm sorry for this lack of precision in my first message. $$anonymous$$y bad.
In your last answer, do you talking about manipulation on the custom shader you send me ? Or on the "Self-Illu$$anonymous$$" shader ? Or is it quite a different manipulation ? As I sayed, I know nothing about scripting custom shader or anything else in Unity. So I don't really see how to "multiply the highlight with the value read from the specular map". Could you specify a little ?
Your answer
Follow this Question
Related Questions
Some textures not affected by light? (With screenshots) 5 Answers
Rim Light shader problem 0 Answers
How to make sprite to react to light? 1 Answer
Specular & alpha mapping 1 Answer
Directional Light seems to have no effect on MeshRenderer. 1 Answer