- Home /
My shader doesn't work if I use the same material for multiple objects with the same texture.
Hey, everyone!
I am very new to shaders and I tried making a billboard shader. I used the code from this video
The shader works fine if there is only one object with a material from this shader. It stays in the same position and looks at the camera as the camera rotates , it is the effect I wanted. But:
If I create another object with the same sprite and the same material, in certain camera angles sprites get rendered at very far positions out of the cameras view range.
If I create another object with the same sprite and use another material I created from this shader, It also works fine.
I tried using material property block and used that for different objects with the same sprite and the same material, it only works if the property values different from each other, if they are the same it doesn't work either.
I am using Sprite renderer, when I tried using mesh renderer it didn't have this problem and worked fine, but I want to use Sprite renderer and really wondering what is the issue here?
Also the sprites I am using has transparent parts, but I am not sure it has anything to do with this problem. I come across this thread about alpha blended tree billboards and I am not sure if it is a " alpha blended materials don't sort properly problem"
Any help greatly appreciated.
Here is the shader code :
Shader "Shaders/UnlitBillBoard"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
[PerRendererData]_ScaleFactor("Scale Factor" , Range(0,1)) = 0
[PerRendererData]_ReferenceDistance("Referance Distance", Float) = 10
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue" = "Transparent+500" }
LOD 100
Pass
{
ZTest Off
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _ScaleFactor;
float _ReferenceDistance;
v2f vert (appdata v)
{
v2f o;
//o.vertex = UnityObjectToClipPos(v.vertex);
float4 world_origin = mul(UNITY_MATRIX_M ,float4(0,0,0,1));
float4 view_origin = float4(UnityObjectToViewPos(float3(0,0,0)),1);
float scale = (_ScaleFactor * (length(view_origin) / _ReferenceDistance)) + ((1 - _ScaleFactor));
float4 world_pos = mul(UNITY_MATRIX_M , float4(scale,scale,scale,1) * v.vertex);
float4 flipped_world_pos= float4(-1,1,-1,1) * world_pos - world_origin + view_origin;
//float4 view_pos = mul(UNITY_MATRIX_V,world_pos);
float4 view_pos = world_pos - world_origin + view_origin;
float4 clip_pos = mul(UNITY_MATRIX_P,view_pos);
o.vertex = clip_pos;
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 = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
Answer by Eno-Khaon · Jun 30, 2021 at 11:19 PM
If I create another object with the same sprite and the same material, in certain camera angles sprites get rendered at very far positions out of the cameras view range.
This sounds like a problem involving dynamic batching. In short, the world positions of the vertices become their local positions, so there is only a single origin point at (0, 0, 0) for all the billboard-shader-rendered objects.
For reference, in your line:
float4 world_origin = mul(UNITY_MATRIX_M ,float4(0,0,0,1));
float4(0,0,0,1) represents the object's origin point when multiplied by the Model Matrix (UNITY_MATRIX_M), where vertex positions (float4 [name]: POSITION) are the local positions of the vertices.
(Multiplying by the Model Matrix is simply one of the key steps in preparing the mesh to be rendered to the screen)
For this particular shader, you probably just want to disable the dynamic batching, by adding "DisableBatching" = "True"
to your tags.
Tags { "RenderType"="Transparent" "Queue" = "Transparent+500" "DisableBatching" = "True"}
Edit: Added more details
Thank you very much, this solved my problem and thanks to your explanation I did understand the cause of it. I did have bigger objects on the scene that didn't have this problem but I didn't think much of it, turns out "batching is applied only to Meshes containing no more than 900 vertex attributes, and no more than 300 vertices." so that explains why only my little objects have this problem. For everyone who wants to read the unity manual about Draw call batching
Your answer
Follow this Question
Related Questions
Distort shader not showing sprites 2 Answers
Allow 2D sprite to receive light from any direction and show on both sides 0 Answers
How do I write a cutout sprite shader to depth depthtexture ? 0 Answers
How to access SpriteRenderer Color from a shader? 1 Answer
Doom-style billard/sprite skybox without perspective warping? 1 Answer