Fade Material's Transparency Based on Distance
Okay, so I've been at this for hours now and still no luck. Thought I'd see if the pros here could help me out :)
So I have everything working correctly except it's opposite:
dist = Vector3.Distance(transform.position, other.position);
renderer.material.color.a = dist * .02;
It fades the material when I get closer and then unfades it as I get further away (opposite effect).
How can I fix this? I tried using -Vectot3.Distance and I get some crazy distance number. This is tough because Unity is limited with their scripting references and all they have is Vector3.Distance. Is there another way I can do this? Any help or guidance would be much appreciated and I'll be sure to give an answered question if you can help me get this working. Thanks
Answer by aldonaletto · Apr 20, 2012 at 12:52 AM
Alpha = 0 means transparent, while alpha = 1 means solid. You could use something like this:
var solidDistance: float = 5.0; // max distance to be 100% solid ... dist = Vector3.Distance(transform.position, other.position); if (dist < solidDistance) dist = solidDistance; renderer.material.color.a = solidDistance / dist;
Thank you for this! added a couple things to it to make it faded more gradual and it's almost perfect. How can I fade multiple materials if an object has more than one? So do the same but for all the materials on the object that the script is on?
I think you must do the same thing for each material - and the materials must have transparent shaders as well, or the alpha will do nothing.
Ok, thank you. Last question, I know how you have to have a transparent material, but is it possible to have one that is able to cast and receive shadows, such as transparent bumped specular? Or am I gonna have to rewrite the shader..
Would I be able to use an array to control all the materials at once, then assign the materials that will be used.
var fade$$anonymous$$aterial : $$anonymous$$aterial[];
renderer.material = fade$$anonymous$$aterial[0];
renderer.material.color.a = solidDistance / dist * 10;
How can I control an array of materials? Or is this not possible?
I don't know much about shadows, but suspect that they have nothing to do with the shader itself - it seems that they are generated in another process, and only some material properties are taken into account (but I'm not 100% sure about this).
According to the docs, when you modify any renderer.material characteristic, a local copy is created in order to not modify other objects that use the same material. I think that if you have an array of renderers and modify their materials, other objects will not be affected - but if it's an array of materials, you may modify all objects that use them.
Answer by Seyed_Morteza_Kamaly · Jan 20, 2018 at 03:52 PM
create shader and copy and paste then add this to your object
Shader "Kamaly/FarAlpha"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_MinVisDistance("MinDistance",Float) = 0
_MaxVisDistance("MaxDistance",Float) = 20
_Color("Color",Color) = (0,0,0,1)
}
SubShader
{
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Tags { "RenderType"="Transparent" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct v2f
{
half4 pos : POSITION;
fixed4 color : COLOR0;
half2 uv : TEXCOORD0;
};
sampler2D _MainTex;
half _MinVisDistance;
half _MaxVisDistance;
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul((half4x4)UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
o.color = v.color;
half3 viewDirW = _WorldSpaceCameraPos - mul((half4x4)unity_ObjectToWorld, v.vertex);
half viewDist = length(viewDirW);
half falloff = saturate((viewDist - _MinVisDistance) / (_MaxVisDistance - _MinVisDistance));
o.color.a *= (1.0f - falloff);
return o;
}
fixed4 frag(v2f i) : COLOR
{
fixed4 color = tex2D(_MainTex, i.uv) * i.color;
return color;
}
ENDCG
}
}
}
@Seyed_$$anonymous$$orteza_$$anonymous$$amaly I like your shader, thanks for sharing!
I've made two small adjustments, that you might like. First of all I added "queue=transparant" to the tags, so that it is drawn later than solid geometry (sometimes your shader pops behind a solid object).
Furthermore I also moved the code for calculating the alpha to the frag method, this causes the alpha to be deter$$anonymous$$ed on pixel level, ins$$anonymous$$d of vertex level. For instance a long cube, would be invisible at it's center, because there's no vertices there.
Again thanks for sharing this helped me out with some problems I had myself ;). Here's my version:
Shader "$$anonymous$$amaly/FarAlpha"
{
Properties
{
_$$anonymous$$ainTex ("Texture", 2D) = "white" {}
_$$anonymous$$inVisDistance("$$anonymous$$inDistance",Float) = 0
_$$anonymous$$axVisDistance("$$anonymous$$axDistance",Float) = 20
_Color("Color",Color) = (0,0,0,1)
}
SubShader
{
ZWrite Off
Blend SrcAlpha One$$anonymous$$inusSrcAlpha
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
LOD 100
Pass
{
CGPROGRA$$anonymous$$
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct v2f
{
half4 pos : POSITION;
fixed4 color : COLOR0;
half2 uv : TEXCOORD0;
half4 vert : TEXCOORD1;
};
sampler2D _$$anonymous$$ainTex;
half _$$anonymous$$inVisDistance;
half _$$anonymous$$axVisDistance;
fixed4 _Color;
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul((half4x4)UNITY_$$anonymous$$ATRIX_$$anonymous$$VP, v.vertex);
o.vert = v.vertex;
o.uv = v.texcoord.xy;
o.color = _Color;
return o;
}
fixed4 frag(v2f i) : COLOR
{
half3 viewDirW = _WorldSpaceCameraPos - mul((half4x4)unity_ObjectToWorld, i.vert);
half viewDist = length(viewDirW);
half falloff = saturate((viewDist - _$$anonymous$$inVisDistance) / (_$$anonymous$$axVisDistance - _$$anonymous$$inVisDistance));
i.color.a *= (1.0f - falloff);
fixed4 color = tex2D(_$$anonymous$$ainTex, i.uv) * i.color;
return color;
}
ENDCG
}
}
}
Answer by wolventoad · Apr 20, 2012 at 01:13 AM
I think renderer.material.color can only return a new color, and can not just set a new single alpha value. how about trying this:
renderer.material.color = new Color(renderer.material.color.r, renderer.material.color.g, renderer.material.color.b, solidDistance / dist);
No it works, I have used the same thing in different codes. What it does is just control the alpha value and nothing else.