Fog on a sprite
Trying to get fog to affect a 2D sprite. Another question has modifying 'ZWrite On' to the shader as a solution.
http://answers.unity3d.com/questions/1271178/sprites-are-ignoring-global-fog.html
That doesn't work for me. I'm using 5.4.1.
In the Shader I am using though there is a line;
pragma surface surf Lambert vertex:vert nofog keepalpha
And getting rid of "nofog" does make the the sprite be affected by fog, but there is an outline that follows it that looks strange.
I also add the line ;
pragma multi_compile_fog
but this doesn't seem to change anything one way or the other.
For reference I am using the Sprites-Diffuse shader from the standard shaders download.
There are a few other questions addressing this but they are either unanswered or much older and also didn't work for me.
I copy and pasted this solution and got about as far. http://answers.unity3d.com/questions/1244402/trying-to-have-sprites-affected-by-fog-without-hav.html
Any help would be appreciated. Thank you.
Answer by vikingsoulgames · Jul 13, 2019 at 06:47 PM
Although the post is from some time ago, I just had the same small problem and I want to provide the solution I found, thanks to the fact that someone charitable shared a shader just for this in the following link:
https://www.reddit.com/r/Unity3D/comments/6scjlo/a_friend_of_mine_made_a_sprite_shader_which/
The shader what Im talking about is the next: // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
Shader "Sprites/Default with Fog"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
[HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
[HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
[PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
[PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex SpriteVertFog
#pragma fragment SpriteFragFog
#pragma target 2.0
#pragma multi_compile_instancing
#pragma multi_compile _ PIXELSNAP_ON
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
#pragma multi_compile_fog
#include "UnitySprites.cginc"
struct v2f_fog
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_FOG_COORDS(1)
UNITY_VERTEX_OUTPUT_STEREO
};
v2f_fog SpriteVertFog(appdata_t IN)
{
v2f_fog OUT;
UNITY_SETUP_INSTANCE_ID (IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
#ifdef UNITY_INSTANCING_ENABLED
IN.vertex.xy *= _Flip.xy;
#endif
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color * _RendererColor;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif
UNITY_TRANSFER_FOG(OUT, OUT.vertex);
return OUT;
}
fixed4 SpriteFragFog(v2f_fog IN) : SV_Target
{
fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
// apply fog
UNITY_APPLY_FOG(IN.fogCoord, c);
c.rgb *= c.a;
return c;
}
ENDCG
}
}
}
It was enough for me to create a material, assign it to this shader and then assign it to my sprites that material.
You did it!
And I was able to set up this shader without even having to look it up. High five for both of us!
Answer by eyeballTickler · May 02, 2018 at 12:19 AM
I ran into the same issue and resolved it by:
Removing the
nofog
directiveAdding this line to the end of the
surf
function
clip(o.Albedo - _CutoutThresh);
where _CutoutThresh
is a float that I set to 0.05
Note, I didn't have to turn ZWrite on or add the multi_compile_fog
in my case but your results may vary.
EDIT: As @blargenswarg pointed out, the clip line should probably use o.Alpha
instead of o.Albedo
Thank you very much for this. I tried your solution but the line clip(o.Albedo - _CutoutThresh);
caused the shader to cut holes in some sprites where they shouldn't be. After some experimentation I found that it worked much better with clip(o.Alpha - _CutoutThresh);
with _CutoutThresh set to 1. I'm not using the most recent version of Unity though, so that might be why our results vary.
Thanks back at you! That actually fixed an issue where my sprite would disappear when the sprite color was set to a pure non-white color. I'll update my original answer.
I know this is a pretty old post, but would you $$anonymous$$d explaining how you added _CutoutThresh
as a float to the shader? I'd really appreciate it.
Here's the full shader:
Shader "Custom/Shadow Casting Sprite" {
Properties {
_Cutoff("Cutoff", Range(0,1)) = 0.5
_Color ("Tint", Color) = (1,1,1,1)
[PerRendererData]_$$anonymous$$ainTex ("Sprite Texture", 2D) = "white" {}
}
SubShader {
Tags
{
"RenderType"="Opaque"
"IgnoreProjector"="True"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
LOD 200
Cull Off
Lighting Off
//ZWrite Off
Blend One One$$anonymous$$inusSrcAlpha
CGPROGRA$$anonymous$$
// Lambert lighting model, and enable shadows on all light types
#pragma surface surf Lambert addshadow fullforwardshadows
#pragma target 2.0
#pragma multi_compile_instancing
sampler2D _$$anonymous$$ainTex;
fixed4 _Color;
fixed _Cutoff;
struct Input
{
float2 uv_$$anonymous$$ainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D (_$$anonymous$$ainTex, IN.uv_$$anonymous$$ainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
clip(o.Alpha - _Cutoff);
}
ENDCG
}
FallBack "Diffuse"
}