I followed this guy's tutorial on making a billboard shader, and it works great, except if you are billboarding things that are tall, like a tree, it looks weird, to put it simply.
When the camera's horizontal rotation is zero, it looks fine, as you can see: the trees up close are models the ones far away are billboards
But when you rotate to look up or down, the tree billboards rotate with the camera, this is particularly apparent when the up close 3D trees are pointing the correct way but the billboards in the distance are not.
So I just need to know how to get it to rotate in the way I want but not in the way I don't want:
float4 worldOrigin = mul(UNITY_MATRIX_M, float4(0, 0, 0, 1));
float4 viewOrigin = float4(UnityObjectToViewPos(float3(0, 0, 0)), 1);
float4 worldPos = mul(UNITY_MATRIX_M, v.vertex);
float4 viewPos = worldPos - worldOrigin + viewOrigin; // the tutorial's way of doing it for billboarding
//float4 viewPos = mul(UNITY_MATRIX_V, worldPos); // the normal way, basically turns it into an unlit shader
float4 clipsPos = mul(UNITY_MATRIX_P, viewPos);
o.vertex = clipsPos;
I've tried a million things, like seeing what it looks like when you multiply some of the vectors in the UNITY_MATRIX_V matrix by 0 or by another vector before using mul() on it. So is there anyway for them to behave when the camera rotates up and down as well as have them always face the player? Thank you, here is the full code just in case: thank you!
Shader "Billboard"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent+500" }
LOD 100
Pass
{
ZTest Off
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float4 color : COLOR0;
UNITY_VERTEX_INPUT_INSTANCE_ID // necessary only if you want to access instanced properties in fragment Shader.
};
sampler2D _MainTex;
float4 _MainTex_ST;
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
UNITY_INSTANCING_BUFFER_END(Props)
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o); // necessary only if you want to access instanced properties in the fragment Shader.
float4 worldOrigin = mul(UNITY_MATRIX_M, float4(0, 0, 0, 1));
float4 viewOrigin = float4(UnityObjectToViewPos(float3(0, 0, 0)), 1);
float4 worldPos = mul(UNITY_MATRIX_M, v.vertex);
float4 viewPos = worldPos - worldOrigin + viewOrigin; // the tutorial's way of doing it for billboarding
//float4 viewPos = mul(UNITY_MATRIX_V, worldPos); // the normal way, basically turns it into an unlit shader
float4 clipsPos = mul(UNITY_MATRIX_P, viewPos);
o.vertex = clipsPos;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = UNITY_ACCESS_INSTANCED_PROP(Props, _Color) * tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
UNITY_SETUP_INSTANCE_ID(i); // necessary only if any instanced properties are going to be accessed in the fragment Shader.
return col;
//return col;
}
ENDCG
}
}
}