- Home /
Can I make this world reveal shader have more than 1 source of reveal ?
Hey,
I'm currently making a level where objets appear around you.
There's the shader that takes care of this : I think it's not too costly. And i also think it doesn't need lighting.
Shader "Reveal/Diffuse" {
Properties{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
// Dissolve properties
_DissolveTexture("Dissolve Texture", 2D) = "white" {}
_Progression("Progression", Range(0,100)) = 0.0
}
SubShader{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
fixed4 _Color;
sampler2D _MainTex;
//Dissolve properties
float3 _PlayerPos;
float _Progression;
sampler2D _DissolveTexture;
struct Input {
float2 uv_MainTex;
float3 worldPos;
};
void surf(Input IN, inout SurfaceOutputStandard o) {
// Dissolve function
half dissolve_value = tex2D(_DissolveTexture, IN.uv_MainTex).x;
float dist = distance(_PlayerPos, IN.worldPos);
//clip(dissolve_value - dist / _Progression);
// Basic shader function
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
}
ENDCG
}
FallBack "Diffuse"
}
The thing is, this shader only can handle one position "source". That means that if for example i want an objets to be revealed by both the player and a bullet for example, this shader wouldn't work.
The system I need was, that when a second source hits the renderer, I duplicate it, and give a second source to that renderer.
It's very dirty, and costly. Am I making my self clear, and is there a way to give this shader multiple sources of revelation.
Thanks,
gabriel
Answer by Namey5 · Mar 09, 2020 at 02:05 AM
You can pass in an array of positions instead, and loop through those to find the closest distance to use;
Shader "Reveal/Diffuse" {
Properties{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
// Dissolve properties
_DissolveTexture("Dissolve Texture", 2D) = "white" {}
_Progression("Progression", Range(0,100)) = 0.0
}
SubShader{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
fixed4 _Color;
sampler2D _MainTex;
//Dissolve properties
#define MAX_POSITIONS 30
float3 _DissolvePositions[MAX_POSITIONS];
int _TotalPositions;
float _Progression;
sampler2D _DissolveTexture;
struct Input {
float2 uv_MainTex;
float3 worldPos;
};
void surf(Input IN, inout SurfaceOutputStandard o) {
// Dissolve function
half dissolve_value = tex2D(_DissolveTexture, IN.uv_MainTex).x;
float dist = distance (_DissolvePositions[0], IN.worldPos);
for (int i = 1; i < min (MAX_POSITIONS, _TotalPositions); i++)
dist = min (distance (_DissolvePositions[i], IN.worldPos), dist);
//clip(dissolve_value - dist / _Progression);
// Basic shader function
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
}
ENDCG
}
FallBack "Diffuse"
}
In the above, rather than passing a single position, we pass an array of positions. The MAX_POSITIONS macro defines the maximum number of positions you could have at one time. You can change this number, but it has to be there because arrays in shaders must be of a constant length (known at compile time). However, if we have less positions than that, we only want to perform operations on the values we have, so we also have to pass in the number of positions we actually want to use. In your script, this can be done like so;
//Let's say there are 10 objects you wish to have an effect on this shader;
Vector3[] positions = new Vector3[10];
...
//Code to fill the above array
...
//Then, instead of passing a single vector to the shader, we pass the whole array;
mat.SetVectorArray ("_DissolvePositions", positions);
//Also pass the length of the array;
mat.SetInt ("_TotalPositions", positions.Length);