Fix billboard shader lighting

Hi guys i made a simple script to generate BillboardAssets from anything


Now the problem is that its too dark when facing away from light source.


This can be fixed if i crank up ambient lighting

So when ambient is at max it looks just like it should at normal
I am using a slightly cut down version of SpeedTreeBillboard shader
from which i removed crap like wind and hue,
now my idea is to force it to have max ambient value,
but i am unable to find the way to do so.

If i simply insert o.Emission = … it says its a wrong subscript, but the doc says use Emission,
so im out of ideas on how to achieve this.

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "BillboardMaker/Billboard"
{
    Properties
    {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
        [MaterialEnum(None,0,Fastest,1)] _WindQuality ("Wind Quality", Range(0,1)) = 0
    }

    // targeting SM3.0+
    SubShader
    {
        Tags
        {
            "Queue"="AlphaTest"
            "IgnoreProjector"="True"
            "RenderType"="TransparentCutout"
            "DisableBatching"="LODFading"
        }
        LOD 400

        CGPROGRAM
            #pragma surface surf Lambert vertex:SpeedTreeBillboardVert nolightmap addshadow dithercrossfade
            #pragma target 3.0
            #pragma multi_compile __ BILLBOARD_FACE_CAMERA_POS
            #include "SpeedTreeBillboardCommon.cginc"

            void surf(Input IN, inout SurfaceOutput OUT)
            {
                SpeedTreeFragOut o;
                SpeedTreeFrag(IN, o);
                SPEEDTREE_COPY_FRAG(OUT, o)
            }
        ENDCG

        Pass
        {
            Tags { "LightMode" = "Deferred" }

            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma target 3.0
                #pragma multi_compile_fog
                #pragma multi_compile __ LOD_FADE_CROSSFADE
                #pragma multi_compile __ BILLBOARD_FACE_CAMERA_POS
                #include "SpeedTreeBillboardCommon.cginc"

                struct v2f
                {
                    UNITY_POSITION(vertex);
                    UNITY_FOG_COORDS(0)
                    Input data      : TEXCOORD1;
                    UNITY_VERTEX_OUTPUT_STEREO
                };

                v2f vert(SpeedTreeBillboardData v)
                {
                    v2f o;
                    UNITY_SETUP_INSTANCE_ID(v);
                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                    SpeedTreeBillboardVert(v, o.data);
                    o.data.color.rgb *= ShadeVertexLightsFull(v.vertex, v.normal, 4, true);
                    //o.data.color.rgb *= unity_AmbientSky;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    UNITY_TRANSFER_FOG(o,o.vertex);
                    return o;
                }

                fixed4 frag(v2f i) : SV_Target
                {
                    SpeedTreeFragOut o;
                    SpeedTreeFrag(i.data, o);
                    UNITY_APPLY_DITHER_CROSSFADE(i.vertex.xy);
                    fixed4 c = fixed4(o.Albedo, o.Alpha);
                   
                    UNITY_APPLY_FOG(i.fogCoord, c);
                    return c;
                }
            ENDCG
        }
    }

   
    FallBack "Transparent/Cutout/VertexLit"
}

Upclose

“quality” speed tree billboards

I suppose you are use planes or quads to show your billboard texture.
How are the normals of the quad ? Are they perpendicular to the plane of the quad, or pointing up ?

No im using BillboardAsset with BillboardRenderer, its native unity functionality and it handles the geometry internally. And geometry is correct.

Why does your shader have both a surface shader and a deferred pass? The deferred pass you have written out will just be ignored since the surface shader should be generating one and I believe Unity still only runs the first deferred pass in a shader.

The “o.Emission” is for the surf function of a surface shader; Emission is a value in the SurfaceOutput struct, which in that setup is actually assigned to the “OUT” variable as “o” is the SpeedTreeFragOut struct.

I suspect it’ll work more like you expect if you delete the entire additional pass (lines 39 to 84), remove the SPEEDTREE_COPY_FRAG line from the surf function, and replace it with this:

OUT.Emission = o.Albedo;
OUT.Alpha = o.Alpha;

@bgolus

Thanks, it’s certainly better now, ill try adding ambient there, but later, cheers!