I need certain stone objects in my game to display physical damage. It’s a mobile game so I am trying to find the most efficient approach. I came up with an idea to overlay a cracked texture on top of the main texture using a shader. But the shader would include a feature similar to an alpha cutout shader… This way I could have a cracked texture file showing different levels of cracking at different opacity levels. Then as the alpha cutout value is changed, so will the degree of cracking on the object.
I was wondering if anyone could help with this? I’m not even sure if it’s possible to do.
I quite amazed myself and cooked up something that seems to be working… I appear to have lost specularity but I’m sure I can fix that. If any of the more seasoned shader experts wanted to drop in an give any feedback to this noob, that would be very appreciated.
I’ve added specular back into it, but it’s highlighting the cracking too. It’s not a huge deal but is there a way to exclude the cracking from the gloss?
// Overlays a texture on top of another (e.g. for showing cracks in a material) using the Cutoff property
// Uses optimizations from the Simplified Bumped Specular shader. Those differences (from regular Bumped Specular) are:
// - specular lighting directions are approximated per vertex
// - writes zero to alpha channel
// - Normalmap uses Tiling/Offset of the Base texture
// - no Deferred Lighting support
// - no Lightmap support
// - supports ONLY 1 directional light. Other lights are completely ignored.
Shader "Mobile/FX/Cracking Bumped Specular" {
Properties {
_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
_BumpMap ("Normalmap", 2D) = "bump" {}
_SecondTex ("Cracks (A)", 2D) = "white" {}
_CrackColor ("Cracks Color", Color) = (0.5, 0.5, 0.5, 1)
_Cutoff ("Alpha Cutoff", Range(0,1)) = 0.5
}
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;
}
half _Shininess;
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _SecondTex;
float3 _Color;
float3 _CrackColor;
half _Cutoff;
struct Input {
float2 uv_MainTex;
float2 uv_SecondTex;
float2 uv_BumpMap;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 mainTex = tex2D(_MainTex, IN.uv_MainTex);
fixed4 secondTex = tex2D(_SecondTex, IN.uv_SecondTex);
float crackVisibility = saturate((secondTex.a - _Cutoff) * 10);
o.Albedo = lerp(mainTex.rgb * _Color, secondTex.rgb * _CrackColor, crackVisibility);
o.Gloss = mainTex.a;
o.Specular = _Shininess;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}
FallBack "Mobile/VertexLit"
}
Just out of curiosity, if I was going to change the crack layer to a normal map and blended that to the current normal map, would that make the shader a lot more expensive?
Not much, but of course it’s not free…
You’d just lerp it the same way you do everything else, but you also have to normalize() the result, which is not exactly the cheapest operation (equivalent to dot + rsqrt + mul)… Well… or not, but the transition areas might get a little darker / brighter as a result of the normal not being normalized. o.Normal = normalize(lerp(modelNormal, crackNormal, crackVisibility));