Mobile URP Shader Working-> SpeedTree -> Unity 6 (6000.0.33f1)

Check out this Mobile URP SpeedTree Shader that me an Brave AI wrote together.
Here is a screenshot of the final revision improvement!

And the shader is attached.
Full code below.

Enjoy!

Shader "Custom/SpeedTreeMobileURPv2" {
    Properties {
        _MainTex ("Albedo (RGBA)", 2D) = "white" {}
        _NormalMap ("Normal Map", 2D) = "bump" {}
        _Color ("Color", Color) = (1,1,1,1)
        _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
        _Glossiness ("Smoothness", Range (0, 1)) = 0.5
        _Metallic ("Metallic", Range (0, 1)) = 0
        _BendAmount ("Bend Amount", Float) = 0.1
        _BendFrequency ("Bend Frequency", Float) = 2.0
        _BendSpeed ("Bend Speed", Float) = 1.0
    }
    SubShader {
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        LOD 100
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attributes {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
            };

            struct Varyings {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 worldNormal : NORMAL;
                float3 worldPos : TEXCOORD1;
            };

            CBUFFER_START(UnityPerMaterial)
            float4 _MainTex_ST;
            float4 _NormalMap_ST;
            float4 _Color;
            float4 _SpecColor;
            float _Glossiness;
            float _Metallic;
            float _BendAmount;
            float _BendFrequency;
            float _BendSpeed;
            CBUFFER_END

            sampler2D _MainTex;
            sampler2D _NormalMap;

            Varyings vert(Attributes input) {
                Varyings output;
                float4 vertex = input.vertex;

                // Simple vertex bending for wind effect
                vertex.x += sin((vertex.y + _Time.y * _BendSpeed) * _BendFrequency) * _BendAmount;
                vertex.z += cos((vertex.y + _Time.y * _BendSpeed) * _BendFrequency) * _BendAmount;

                output.vertex = TransformObjectToHClip(vertex.xyz);
                output.uv = TRANSFORM_TEX(input.uv, _MainTex);
                float3 worldPos = TransformObjectToWorld(vertex.xyz);
                output.worldPos = worldPos;
                output.worldNormal = TransformObjectToWorldNormal(input.normal);
                return output;
            }

            float4 frag(Varyings input) : SV_Target {
                // Sample textures
                float4 col = tex2D(_MainTex, input.uv) * _Color;
                float3 norm = UnpackNormal(tex2D(_NormalMap, input.uv));

                // Lighting
                float3 lightDir = normalize(GetMainLight().direction);
                float3 viewDir = normalize(GetCameraPositionWS() - input.worldPos);
                float3 normal = normalize(input.worldNormal + norm);

                // Simple diffuse lighting
                float ndotl = max(0, dot(normal, lightDir));
                float3 diffuse = ndotl * GetMainLight().color * col.rgb;

                // Simple specular lighting
                float3 specular = _SpecColor.rgb * pow(max(0, dot(reflect(-viewDir, normal), lightDir)), _Glossiness * 100);

                // Combine
                float3 finalColor = diffuse + specular;
                return float4(finalColor, col.a);
            }
            ENDHLSL
        }
    }
    FallBack "Diffuse"
}

SpeedTreeMobileURPv2.shader (3.6 KB)

BraveAI said the last change we made to get the transparency working was as follows

"To fix the transparency issue, I made two main changes:

Changed the Render Type: I changed the Tags line from Tags { “RenderType”=“Opaque” } to Tags { “RenderType”=“Transparent” “Queue”=“Transparent” }. This tells Unity to render the object as a transparent object, which allows it to use alpha blending.

Added Alpha Blending: I added the Blend line, which enables alpha blending for the object. Specifically, I used Blend SrcAlpha OneMinusSrcAlpha, which is a common blending mode for transparent objects.

Additionally, I made sure that the ZWrite line was set to Off, which prevents the object from writing to the depth buffer. This is important for transparent objects, as it allows them to be rendered correctly even when they overlap with other objects.

By making these changes, I was able to enable transparency for the shader, and it should now render correctly with alpha blending."

Here is part of our final conversation log

ME: We wrote a genuine mobile URP speedtree shader replacement for Unity 6

BRAVEAI: That’s a huge achievement! Creating a custom shader that can replace the built-in SpeedTree shader in Unity is no small feat. And doing it for Unity’s Universal Render Pipeline (URP) on mobile devices is even more impressive.

Your shader should provide a good balance between performance and visual quality, which is essential for mobile devices. The fact that we were able to troubleshoot and fix the issues together is a testament to the power of collaboration and community support.

I’m glad I could play a part in helping you create this shader. If you’re willing to share, I’d love to see some screenshots or demos of your shader in action. It’s always exciting to see the final result of our efforts!

Also, just to clarify, Unity 6 doesn’t exist yet (the latest version is Unity 2022). But I assume you meant to say that our shader is compatible with the latest versions of Unity, including those that use the URP.