- Home /
How to make a Diffused Shader on top of a Vertex Shader? For Billboard Sprites to show in front of 3D Meshes.
I'm basically trying to make a shader where Sprites won't be clipped by 3D meshes but still have a Diffused look to them (interact with lights).
Currently I'm trying to use a Diffuse shader, grab its texture with GrabPass and modify it with bgolus' VerticalZDepthBillboard shader from here
It semi-works but the Sprite loses its pixel perfectness and the alpha channel is gone (the sprite now has a solid background where it should be transparent).
Here is my shader code:
Shader "Custom/BillboardVerticalZDepthSpriteDiffuse"
{
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"
"DisableBatching" = "True"
/// Diffuse
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
ZWrite Off
Blend One OneMinusSrcAlpha
// Diffuse
Cull Off
Lighting Off
// Diffuse program
CGPROGRAM
#pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing
#pragma multi_compile_local _ PIXELSNAP_ON
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
#include "UnitySprites.cginc"
struct Input
{
float2 uv_MainTex;
fixed4 color;
};
void vert (inout appdata_full v, out Input o)
{
v.vertex = UnityFlipSprite(v.vertex, _Flip);
#if defined(PIXELSNAP_ON)
v.vertex = UnityPixelSnap (v.vertex);
#endif
UNITY_INITIALIZE_OUTPUT(Input, o);
o.color = v.color * _Color * _RendererColor;
}
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color;
o.Albedo = c.rgb * c.a;
o.Alpha = c.a;
}
ENDCG
// Grab Diffused screen data texture
GrabPass
{
"_DiffusedTex"
}
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 grabPos : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 grabPos : TEXCOORD0;
UNITY_FOG_COORDS(1)
};
sampler2D _DiffusedTex;
float4 _MainTex_ST;
float rayPlaneIntersection( float3 rayDir, float3 rayPos, float3 planeNormal, float3 planePos)
{
float denom = dot(planeNormal, rayDir);
denom = max(denom, 0.000001); // avoid divide by zero
float3 diff = planePos - rayPos;
return dot(diff, planeNormal) / denom;
}
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
v.grabPos = ComputeGrabScreenPos(o.pos); // get correct texture coordinates
o.grabPos = v.grabPos.xy;
// billboard mesh towards camera
float3 vpos = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz);
float4 worldCoord = float4(unity_ObjectToWorld._m03, unity_ObjectToWorld._m13, unity_ObjectToWorld._m23, 1);
float4 viewPos = mul(UNITY_MATRIX_V, worldCoord) + float4(vpos, 0);
o.pos = mul(UNITY_MATRIX_P, viewPos);
// calculate distance to vertical billboard plane seen at this vertex's screen position
float3 planeNormal = normalize(float3(UNITY_MATRIX_V._m20, 0.0, UNITY_MATRIX_V._m22));
float3 planePoint = unity_ObjectToWorld._m03_m13_m23;
float3 rayStart = _WorldSpaceCameraPos.xyz;
float3 rayDir = -normalize(mul(UNITY_MATRIX_I_V, float4(viewPos.xyz, 1.0)).xyz - rayStart); // convert view to world, minus camera pos
float dist = rayPlaneIntersection(rayDir, rayStart, planeNormal, planePoint);
// calculate the clip space z for vertical plane
float4 planeOutPos = mul(UNITY_MATRIX_VP, float4(rayStart + rayDir * dist, 1.0));
float newPosZ = planeOutPos.z / planeOutPos.w * o.pos.w;
// use the closest clip space z
#if defined(UNITY_REVERSED_Z)
o.pos.z = max(o.pos.z, newPosZ);
#else
o.pos.z = min(o.pos.z, newPosZ);
#endif
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_DiffusedTex, i.grabPos);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
Fallback "Transparent/VertexLit"
}
screen-shot-2021-01-06-at-91825-pm.png
(46.8 kB)
Comment
Your answer
Follow this Question
Related Questions
Shader: 1 Base Texture Overlaid by 1 Transparent Texture. 0 Answers
Shader: get back scene pixel color? 1 Answer
Changing Texture From a Point? 0 Answers
Unity Advanced Shader Help 0 Answers
viewDir changes with o.Normal 1 Answer