- Home /
2.5D billboard shader and frustum culling problem
Hello! I'm using a custom shader to do billboarding for me in a 2.5D game with sprites (don't starvesque): I get this problem (only on bottom edge of the screen).
What I've figured out is that frustum culling is to blame - the object disappears exactly when a non-facing sprite in the same position would.
What can I do? Can I add something to my shader?
Shader "Feral" {
Properties{
_Color("Color", Color) = (1,1,1,1)
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_MainTex("Albedo Map", 2D) = "white" {}
_BumpMap("Normal Map", 2D) = "bump" {}
_EmissionMap("Emission Map", 2D) = "white" {}
_EmissionColor("Emission Color", Color) = (0,0,0)
_UpVector("Up Vector (XYZ)", Vector) = (0,1,0,0)
}
SubShader
{
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "DisableBatching" = "True"}
Name "FrontPass"
LOD 500
Cull Off
CGPROGRAM
#pragma target 3.0
#pragma surface surf SimpleLambert alphatest:_Cutoff vertex:vert addshadow
half4 _Color;
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _EmissionMap;
half4 _EmissionColor;
float3 _UpVector;
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
float2 uv_EmissionMap;
};
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
// get the camera basis vectors
float3 forward = -normalize(UNITY_MATRIX_V._m20_m21_m22);
float3 up = normalize(UNITY_MATRIX_V._m10_m11_m12);
float3 right = normalize(UNITY_MATRIX_V._m00_m01_m02);
// rotate to face camera
float4x4 rotationMatrix = float4x4(right, 0,
up, 0,
forward, 0,
0, 0, 0, 1);
//float offset = _Object2World._m22 / 2;
float offset = 0;
v.vertex = mul(v.vertex + float4(0, offset, 0, 0), rotationMatrix) + float4(0, -offset, 0, 0);
v.normal = mul(v.normal, rotationMatrix);
}
half4 LightingSimpleLambert(SurfaceOutput s, half3 lightDir, half atten) {
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (atten);
c.a = s.Alpha;
return c;
}
void surf(Input IN, inout SurfaceOutput o)
{
half4 albedo = tex2D(_MainTex, IN.uv_MainTex) * _Color;
half3 emission = tex2D(_EmissionMap, IN.uv_EmissionMap).rgb * _EmissionColor;
o.Albedo = albedo.rgb - emission; // Emission cancels out other lights
o.Alpha = albedo.a;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
o.Emission = emission;
//o.Metallic = 0;
}
ENDCG
}
FallBack "Standard"
}`
Answer by Syganek · Nov 09, 2017 at 02:03 PM
Hi. I've got the same problem. I've found a solution by Andy-Korth (can't mark him because of the '-' sign) in this thread about disabling frustum culling.
Basically Unity allows to add callbacks before culling and rendering. It allows to set the FOV of the camera to catch the bounds of the original sprite on culling stage and then reset it to the original value before rendering.
Answer by Bunny83 · Jun 15, 2017 at 09:23 PM
Well, every rendered object has a local bounds as well as a worldspace bounds. The worldspace bounds is calculated by rotating the local bounds with the objects localToWorld matrix and creating a new axis aligned bounding box that encloses the rotated local bounds. If the worldspace bounds is outside of the camera frustum, Unity won't draw the object. Since your shader does unexpected transformations to the object, your worldspace bounds are most likely wrong.
One solution is to manually enlarge the mesh.bounds to ensure that, after the normal object transformation, the bounds is still large enough to enclose your modified mesh.
However i don't quite understand why you use a shader for that. Your game seems to be an orthographic game as you don't use any projection matrix in your shader. Also your objects has to be defined in worldspace coordinates since you don't use any model matrix.
If the angle of the camera barely or never changes it would be much better to adjust the actual mesh.
The game is not orthograpic, I use perspective camera to get parallax and depth. On the same time the angle of each sprite has to be updated to face camera or they look really weird. Hence the shader.
I've read about the mesh.bounds solution - but SpriteRenderer.bounds is read only. Do you know how to get the meshes sprite and change its bounds?
I've had this problem as well. How do you solve this for a 2D game? Thanks
Your answer
Follow this Question
Related Questions
Problem with flipping ! 0 Answers
Frustum culling not working? 0 Answers
one shader for multiple sprites 0 Answers
Greyscale shading 0 Answers
¿UsePass overrides Render State? 0 Answers