Untitled

Anonymous
plain_text
02/19/2026 11:52 AM
6.6 KB
11
Indexable
Shader "Custom/test"
{
    Properties
    {
        [MainTexture] _BaseMap("Base Map", 2D) = "white"
    }

    SubShader
    {
        Tags
        {
            "RenderPipeline" = "UniversalPipeline"
            "RenderType" = "Opaque"
            "Queue" = "AlphaTest"
        }

Pass
{
    Cull Off

    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 positionOS : POSITION;
        float3 normal : NORMAL;
        float3 tangent : TANGENT;
        float2 uv : TEXCOORD0;
    };

    struct Varyings
    {
        float4 vertex : SV_POSITION;
        float2 uv : TEXCOORD0;
        float3 normal : TEXCOORD1;
        float3 tangent : TANGENT;
        float3 binormal : BINORMAL;
        float3 worldPos : TEXCOORD2;
    };

    TEXTURE2D(_BaseMap);
    SAMPLER(sampler_BaseMap);
    float4 _MainTex_TexelSize;

    CBUFFER_START(UnityPerMaterial)
        float4 _BaseMap_ST;
        matrix worldMatrix;
        matrix viewMatrix;
        matrix projectionMatrix;
    CBUFFER_END

    float3 ComputeSpriteRimNormal(float2 UV)
    {
        float3 defaultOut = float3(0.0, 0.5, 1.0); // Receive lighting from slightly upwards
        
        float2 offset = float2(_MainTex_TexelSize.x, _MainTex_TexelSize.y);

        float sample_current = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, UV).a;
        
        float sample_up = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, UV + float2(0.0, offset.y)).a;
        float sample_left = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, UV + float2(-offset.x, 0.0)).a;
        float sample_right = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, UV + float2(offset.x, 0.0)).a;

        if (sample_left < 0.01 && sample_up < 0.01) {
            return float3(-0.95, 0.95, 1.0); // OpenGL normal up-left vector.
        }

        if (sample_right < 0.01 && sample_up < 0.01) {
            return float3(0.95, 0.95, 1.0); // OpenGL normal up-right vector.
        }

        if (sample_left < 0.01) {
            return float3(-0.95, 0.0, 1.0); // OpenGL normal left vector.
        }

        if (sample_right < 0.01) {
            return float3(0.95, 0.0, 1.0); // OpenGL normal right vector.
        }

        if (sample_up < 0.01) {
            return float3(0.0, 0.95, 1.0); // OpenGL normal up vector.
        }

        return defaultOut;
    }

    Varyings vert(Attributes IN)
    {
        Varyings OUT;
        OUT.vertex = TransformObjectToHClip(IN.positionOS.xyz);
        OUT.normal = TransformObjectToWorldNormal(IN.normal);
        OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
        OUT.worldPos = TransformObjectToWorld(IN.positionOS.xyz);

        OUT.tangent = mul(IN.tangent, (float3x3)worldMatrix);
        OUT.tangent = normalize(OUT.tangent);

        OUT.binormal = cross(OUT.normal, OUT.tangent);
        OUT.binormal = normalize(OUT.binormal);

        return OUT;
    }

    half4 frag(Varyings IN) : SV_Target
    {
        IN.normal = normalize(IN.normal);
        half4 color = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
        
        // Alpha clip
        if (color.a < 0.5){
            discard;
        }

        // Normal map
        float3 tangentNormal = ComputeSpriteRimNormal(IN.uv.xy);

        float3x3 tangentTransform = float3x3(IN.tangent, IN.binormal, IN.normal);
        // half3 unpackedNormal = UnpackNormal(float4(tangentNormal, 0.0));
        float3 worldNormal = TransformTangentToWorld(tangentNormal, tangentTransform, true);

        // Lighting
        Light main_light = GetMainLight();

        float3 light = LightingLambert(main_light.color, main_light.direction, IN.normal);
        for (int i = 0; i <= GetAdditionalLightsCount(); i++) {
            Light additional_light = GetAdditionalLight(i, IN.worldPos);
            light += LightingLambert(additional_light.color, additional_light.direction, IN.normal) * additional_light.distanceAttenuation * additional_light.shadowAttenuation;
        }



        // Rim lighting
        if (tangentNormal.x != 0.0 || tangentNormal.y != 0.5){
            float3 rim_light = LightingLambert(main_light.color, main_light.direction, worldNormal);
            for (int i = 0; i <= GetAdditionalLightsCount(); i++) {
                Light additional_light = GetAdditionalLight(i, IN.worldPos);
                rim_light += LightingLambert(additional_light.color, additional_light.direction, worldNormal) * additional_light.distanceAttenuation * additional_light.shadowAttenuation;
            }
            if (length(light) < length(rim_light)){
                light = rim_light * 5.0;
            }
        }
        light *= 10.0;

        return color * float4(light, 1.0);
    }

    
    ENDHLSL
}
    }
}
Editor is loading...
Leave a Comment