uani
September 16, 2013, 11:40pm
1
Hello,
may I draw your attention towards a post I put in Scripting bc I wasn’t aware of this forum and which hasn’t received an answer:
http://forum.unity3d.com/threads/200628-custom-surface-shader-neither-receives-nor-casts-shadows-despite-fallback
Here’s the content:
Hello,
my custom surface shader doesn’t cast or receive shadows. Changing the used shader from my custom to a built-in such as “Specular” immediately shows shadows. The environment is thus probably set up correctly and the cause is my shader.
From http://forum.unity3d.com/threads/108612-Adding-shadows-to-custom-shader-(vert-frag) , http://forum.unity3d.com/threads/100084-No-Shadow-on-my-custom-shader and http://forum.unity3d.com/threads/175128-Info-request-Shadow-Caster-Collector-defaults I gathered that a “Fallback” is needed as a fallback contains the shadow collector and caster passes.
I added a fallback “Specular” yet still no shadows cast from or received on surfaces with my custom shader.
How can I get shadows to work with a custom surface shader?
Here’s the shader code:
Shader "Custom/myShader" {
Properties {
_Color ("Inherent Color", Color) = (0.5,0.5,0.5,1)
_Intensity ("Light Intensity", Range(-8,8)) = 8
_SpecularSharpness ("Specular Sharpness", Range(1,8)) = 2
_LightnessSoftness ("Lightness Softness", Range(1,8)) = 4
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 100
CGPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11 d3d9
#pragma surface surf Scatter
#include "UnityCG.cginc"
half4 _Color;
half _Intensity;
half _SpecularSharpness;
half _LightnessSoftness;
half3 worldPos;
half4 LightingScatter (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
// convert input color to HSL
half M = max(s.Albedo.r, max(s.Albedo.g, s.Albedo.b));
half m = min(s.Albedo.r, min(s.Albedo.g, s.Albedo.b));
half C = M - m;
half H = 0;
half S = 0;
half L = (M + m) / 2;
if(C != 0)
{
if(M == s.Albedo.r) H = ((s.Albedo.g - s.Albedo.b) / C);
else if(M == s.Albedo.g) H = (s.Albedo.b - s.Albedo.r) / C + 2;
else H = (s.Albedo.r - s.Albedo.g) / C + 4;
if(H < 0) H += 6;
S = C / (1 - abs(M + m - 1));
}
// change L component
half ndotl = dot(s.Normal,lightDir);
if(ndotl > 0) L = L + (1 - L) * pow(1 - acos(dot(normalize(reflect(-lightDir,s.Normal)), viewDir)) / 3.14, _SpecularSharpness);
else L = L + ndotl * L;
L = pow((_Intensity / 16 + 0.5) * L, _LightnessSoftness);
// modify S component (negligible effect)
S *= (1 - length(worldPos - _WorldSpaceCameraPos) / 1000);
if(S < 0) S = 0;
// convert new HSL back to RGB
C = (1 - abs(2 * L - 1)) * S;
m = L - C / 2;
half4 c = m;
c.a = s.Alpha;
half X = C * (1 - abs(fmod(H,2) - 1));
if(H < 1)
{
c.r += C;
c.g += X;
}
else if(H < 2)
{
c.r += X;
c.g += C;
}
else if(H < 3)
{
c.g += C;
c.b += X;
}
else if(H < 4)
{
c.g += X;
c.b += C;
}
else if(H < 5)
{
c.r += X;
c.b += C;
}
else
{
c.r += C;
c.b += X;
}
// return the computed color
return c;
}
struct Input {
float4 color : COLOR;
float3 worldPos;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = _Color.rgb;
o.Alpha = _Color.a;
worldPos = IN.worldPos;
}
ENDCG
}
Fallback "Specular"
}
Kragh
September 17, 2013, 9:26am
2
The “atten” parameter of the lightning function is what will have the shadow data normally. Multiplying this on your “c” output, before returning should give you a received shadow. This parameter also contains data for point and spot lights, so you really need to implement it, if you want this to work with other types of light than directional.
But as you don’t have a cast shadow as well, something may be wrong in other parts also. Something I don’t see right now. But Unity do all sorts of things behind the scene when compiling a shader, so it may even be the very fact you don’t use the “atten” parameter, disables the shadow system. I know I have had all sorts of problems from stuff like that, though not specifically with that parameter.
uani
September 17, 2013, 2:08pm
3
This did it for receiving and casting! Thank you!