Clear outer most edge around alpha of textures.

I’ve pretty sure I’ve seen this asked before, but I can’t seem to find it. I’m having problems with the outer edge of alpha on a texture rendering clear. Any ideas of where to look?

void surf (Input IN, inout SurfaceOutput o)
{
	half4 firstTex = tex2D (_Texture1, IN.uv_Texture1) * _Texture1_color;
	half4 secondTex = tex2D (_Texture2, IN.uv_Texture2) * _Texture2_color;
	half4 thirdTex = tex2D (_Texture3, IN.uv_Texture3) * _Texture3_color;


	//sets the alpha to zero when the color is black
	firstTex.a = (firstTex.r * firstTex.a) + (firstTex.g * firstTex.a) + (firstTex.b * firstTex.a);
	secondTex.a = (secondTex.r * secondTex.a) + (secondTex.g * secondTex.a) + (secondTex.b * secondTex.a);
	thirdTex.a = (thirdTex.r * thirdTex.a) + (thirdTex.g * thirdTex.a) + (thirdTex.b * thirdTex.a);
			
	float3 firstColor = firstTex.rgb * firstTex.a;
	float3 secondColor = secondTex.rgb * secondTex.a;
	float3 thirdColor = thirdTex.rgb * thirdTex.a;
			
	float4 finalColor = float4(firstColor.rgb + secondColor.rgb + thirdColor.rgb, firstTex.a + secondTex.a + thirdTex.a);
	o.Emission = finalColor.rgb;
	o.Alpha = finalColor.a;
}

1483058--82224--$clear.png

I think you want to use the screen blend mode, whereas right now you’re using sort of additive. I’m not sure how to do this without premultiplied alpha blending, though, which isn’t supported by surface shaders.

Here’s an example with a vertex/fragment shader. You’ll need texture with premultiplied alpha for it to work properly.

Shader "Three texture screen" {
	Properties {
		_TexA ("Base (RGB)", 2D) = "white" {}
		_TexB ("Base (RGB)", 2D) = "white" {}
		_TexC ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Transparent" "Queue"="Transparent" "IgnoreProjector"="True" }
		LOD 200
		Blend One OneMinusSrcAlpha
		ColorMask RGB
		ZWrite Off
		
		Pass {
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "UnityCG.cginc"
			
				struct v2f {
					float4 pos : SV_POSITION;
					float2 uv_TexA : TEXCOORD0;
					float2 uv_TexB : TEXCOORD1;
					float2 uv_TexC : TEXCOORD2;
				};
			
				float4 _TexA_ST;
				float4 _TexB_ST;
				float4 _TexC_ST;
			
				v2f vert(appdata_base v) {
					v2f o;
					o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
					o.uv_TexA = TRANSFORM_TEX(v.texcoord, _TexA);
					o.uv_TexB = TRANSFORM_TEX(v.texcoord, _TexB);
					o.uv_TexC = TRANSFORM_TEX(v.texcoord, _TexC);
					return o;
				}
			
				sampler2D _TexA;
				sampler2D _TexB;
				sampler2D _TexC;
			
				float4 frag(v2f IN) : COLOR {
					half4 tA = tex2D (_TexA, IN.uv_TexA);
					half4 tB = tex2D (_TexB, IN.uv_TexB);
					half4 tC = tex2D (_TexC, IN.uv_TexC);
					return 1 - (1 - tA)*(1 - tB)*(1 - tC);
				}
			ENDCG
		}
	}
}

Thanks Daniel. I ended up using a JPEG which got rid of the weird clear lines around the outer edge of the texture. Apparently when the texture is created it can pick up background colors at the very edge. I’m sure I’m not saying anything you didn’t already know. Thanks for the sample, I’m going to check it out for sure. I added a functions to UnityCG.cginc that just returns the greatest RGB channal value. This is what I came up with:

Shader "BlendShaderTestSurfaceShader" 
{
	Properties 
	{
		_MainTex ("Base Texture", 2D) = "white" {}
		_Texture1_color ("Texture 1 color", Color) = (1,1,1,1)
		_Texture1 ("1st Light Texture", 2D) = "white" {}
		_Texture2_color ("Texture 2 color", Color) = (1,1,1,1)
		_Texture2 ("2nd Light Texture", 2D) = "white" {}
		_Texture3_color ("Texture 3 color", Color) = (1,1,1,1)
		_Texture3 ("3rd Light Texture", 2D) = "white" {}
	}
	SubShader 
	{
		//main texture
		Pass
		{
			Tags{"Queue" = "Geometry"}
		
			CGPROGRAM
			
			#pragma fragmentoption ARB_precision_fastest
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			
			uniform sampler2D _MainTex;
			
			struct vertexInput
			{
				float4 vertex : POSITION;
				half2 texcoord : TEXCOORD0;
			};
			
			struct fragmentInput
			{
				float4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
			};
			
			fragmentInput vert(vertexInput i)
			{
				fragmentInput o;
				o.pos = mul(UNITY_MATRIX_MVP, i.vertex);
				o.uv = i.texcoord;
				return o;
			}
			
			half4 frag(fragmentInput i) : COLOR
			{
				half4 col = tex2D(_MainTex, i.uv); 
				return col;
			}
			
			ENDCG
		
		}//pass end
	
	
		Tags {"RenderType" = "Transparent" "Queue" = "Transparent"}
		LOD 200
		
		//Blend SrcAlpha OneMinusSrcAlpha
		//BlendOp Add
		ZWrite Off
		
		CGPROGRAM
		#pragma surface surf Lambert alpha
		#include "UnityCG.cginc"

		float4 _Texture1_color;
		sampler2D _Texture1;
		float4 _Texture2_color;
		sampler2D _Texture2;
		float4 _Texture3_color;
		sampler2D _Texture3;

		struct Input 
		{
			float2 uv_Texture1 : TEXCOORD0;
		};

		void surf (Input IN, inout SurfaceOutput o)
		{
			half4 tex_1 = tex2D (_Texture1, IN.uv_Texture1) * _Texture1_color;
			half4 tex_2 = tex2D (_Texture2, IN.uv_Texture1) * _Texture2_color;
			half4 tex_3 = tex2D (_Texture3, IN.uv_Texture1) * _Texture3_color;

            //Gets the greatest RGB channel
			tex_1.a = GreatestColorValue(tex_1.rgb);
			tex_2.a = GreatestColorValue(tex_2.rgb);
			tex_3.a = GreatestColorValue(tex_3.rgb);
			
			float3 finalColor = tex_1.rgb + 
								tex_2.rgb + 
								tex_3.rgb + 
								
			float3 finalAlpha = tex_1.a +
								tex_2.a +
								tex_3.a +
						
			float4 finalTotal = float4(finalColor, finalAlpha);

			o.Emission = finalTotal.rgb;
			o.Alpha = finalTotal.a;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

I’m not sure what you’re trying to accomplish with GreatestColorValue(). It looks like that will mess up your opacity, especially with darker colours. What happens if you want opaque black, for instance?

Sorry about that. I was going for a light type effect. So when the color started fading to black, I needed the alpha to also begin fading. Good catch though.