Skip to main content
minor fix
Source Link
Serg
  • 383
  • 5
  • 17
Shader "Test/UnlitTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _TopColor ("TopColor", Color) = (1, 0, 0, 1)
        _BottomColor ("_BottomColor", Color) = (0, 0, 1, 1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        ZTest Off
        ZWrite Off
        Lighting On
        Cull Off
        Fog { Mode Off }

        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _MainTex_TexelSize;
            fixed4 _TopColor, _BottomColor;            

            struct vertData
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct fragData
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 up : NORMAL;
            };

            fragData vert (vertData v)
            {
                fragData f;
                f.vertex = UnityObjectToClipPos(v.vertex);
                f.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                f.up = mul(unity_ObjectToWorld, v.normal);
                return f;
            }

            fixed isTransparentPixel(fixed2 uv)
            {
                return step(tex2D(_MainTex, uv).a, 0.0);
            }

            fixed isEdgePixel(fixed2 uv)
            {
                return isTransparentPixel(uv);
            }

            fixed4 frag (fragData f) : SV_Target
            {
                float2 borderSize = float2(3, 3); // border size in tex pixels
                float dx = borderSize.x * _MainTex_TexelSize.x;
                float dy = borderSize.y * _MainTex_TexelSize.y;
                fixed3 borderColor = fixed3(0, 0, 0);
                float borderColorsCount = 0;
                fixed2 uv = f.uv;

                // Top edge:
                float2 dTop = float2(-f.up.x * dydx, f.up.y * dy);
                fixed isEdge = isEdgePixel(uv + dTop);
                borderColor += isEdge * _TopColor;
                borderColorsCount += isEdge;

                // Bottom edge:
                float2 dDown = dTop * -1;
                isEdge = isEdgePixel(uv + dDown);
                borderColor += isEdge * _BottomColor;
                borderColorsCount += isEdge;

                fixed noBorderColor = step(length(borderColor), 0);
                fixed hasBorderColor = 1 - noBorderColor;
                fixed4 c = tex2D(_MainTex, uv);
                c.rgb = c.rgb * noBorderColor + hasBorderColor * borderColor / max(borderColorsCount, 1);
                return c;
            }
            ENDCG
        }
    }
}
Shader "Test/UnlitTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _TopColor ("TopColor", Color) = (1, 0, 0, 1)
        _BottomColor ("_BottomColor", Color) = (0, 0, 1, 1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        ZTest Off
        ZWrite Off
        Lighting On
        Cull Off
        Fog { Mode Off }

        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _MainTex_TexelSize;
            fixed4 _TopColor, _BottomColor;            

            struct vertData
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct fragData
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 up : NORMAL;
            };

            fragData vert (vertData v)
            {
                fragData f;
                f.vertex = UnityObjectToClipPos(v.vertex);
                f.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                f.up = mul(unity_ObjectToWorld, v.normal);
                return f;
            }

            fixed isTransparentPixel(fixed2 uv)
            {
                return step(tex2D(_MainTex, uv).a, 0.0);
            }

            fixed isEdgePixel(fixed2 uv)
            {
                return isTransparentPixel(uv);
            }

            fixed4 frag (fragData f) : SV_Target
            {
                float2 borderSize = float2(3, 3); // border size in tex pixels
                float dy = borderSize.y * _MainTex_TexelSize.y;
                fixed3 borderColor = fixed3(0, 0, 0);
                float borderColorsCount = 0;
                fixed2 uv = f.uv;

                // Top edge:
                float2 dTop = float2(-f.up.x * dy, f.up.y * dy);
                fixed isEdge = isEdgePixel(uv + dTop);
                borderColor += isEdge * _TopColor;
                borderColorsCount += isEdge;

                // Bottom edge:
                float2 dDown = dTop * -1;
                isEdge = isEdgePixel(uv + dDown);
                borderColor += isEdge * _BottomColor;
                borderColorsCount += isEdge;

                fixed noBorderColor = step(length(borderColor), 0);
                fixed hasBorderColor = 1 - noBorderColor;
                fixed4 c = tex2D(_MainTex, uv);
                c.rgb = c.rgb * noBorderColor + hasBorderColor * borderColor / max(borderColorsCount, 1);
                return c;
            }
            ENDCG
        }
    }
}
Shader "Test/UnlitTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _TopColor ("TopColor", Color) = (1, 0, 0, 1)
        _BottomColor ("_BottomColor", Color) = (0, 0, 1, 1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        ZTest Off
        ZWrite Off
        Lighting On
        Cull Off
        Fog { Mode Off }

        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _MainTex_TexelSize;
            fixed4 _TopColor, _BottomColor;            

            struct vertData
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct fragData
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 up : NORMAL;
            };

            fragData vert (vertData v)
            {
                fragData f;
                f.vertex = UnityObjectToClipPos(v.vertex);
                f.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                f.up = mul(unity_ObjectToWorld, v.normal);
                return f;
            }

            fixed isTransparentPixel(fixed2 uv)
            {
                return step(tex2D(_MainTex, uv).a, 0.0);
            }

            fixed isEdgePixel(fixed2 uv)
            {
                return isTransparentPixel(uv);
            }

            fixed4 frag (fragData f) : SV_Target
            {
                float2 borderSize = float2(3, 3); // border size in tex pixels
                float dx = borderSize.x * _MainTex_TexelSize.x;
                float dy = borderSize.y * _MainTex_TexelSize.y;
                fixed3 borderColor = fixed3(0, 0, 0);
                float borderColorsCount = 0;
                fixed2 uv = f.uv;

                // Top edge:
                float2 dTop = float2(-f.up.x * dx, f.up.y * dy);
                fixed isEdge = isEdgePixel(uv + dTop);
                borderColor += isEdge * _TopColor;
                borderColorsCount += isEdge;

                // Bottom edge:
                float2 dDown = dTop * -1;
                isEdge = isEdgePixel(uv + dDown);
                borderColor += isEdge * _BottomColor;
                borderColorsCount += isEdge;

                fixed noBorderColor = step(length(borderColor), 0);
                fixed hasBorderColor = 1 - noBorderColor;
                fixed4 c = tex2D(_MainTex, uv);
                c.rgb = c.rgb * noBorderColor + hasBorderColor * borderColor / max(borderColorsCount, 1);
                return c;
            }
            ENDCG
        }
    }
}
Source Link
Serg
  • 383
  • 5
  • 17

Here is an edited version of the code of the resolved question:

C#

using UnityEngine;

[DisallowMultipleComponent]
public class UnlitTest : MonoBehaviour
{
#pragma warning disable CS0649

    [SerializeField]
    private MeshFilter _meshFilter;

#pragma warning restore CS0649

    private void OnValidate()
    {
        SetNormals();
    }

    private void SetNormals()
    {
        Mesh mesh = _meshFilter.sharedMesh;
        Vector3[] normals = new Vector3[mesh.vertexCount];

        for (int i = 0; i < mesh.vertexCount; i++)
        {
            normals[i] = Vector3.up;
        }

        mesh.normals = normals;
    }
}

Shader

Shader "Test/UnlitTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _TopColor ("TopColor", Color) = (1, 0, 0, 1)
        _BottomColor ("_BottomColor", Color) = (0, 0, 1, 1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        ZTest Off
        ZWrite Off
        Lighting On
        Cull Off
        Fog { Mode Off }

        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _MainTex_TexelSize;
            fixed4 _TopColor, _BottomColor;            

            struct vertData
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct fragData
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 up : NORMAL;
            };

            fragData vert (vertData v)
            {
                fragData f;
                f.vertex = UnityObjectToClipPos(v.vertex);
                f.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                f.up = mul(unity_ObjectToWorld, v.normal);
                return f;
            }

            fixed isTransparentPixel(fixed2 uv)
            {
                return step(tex2D(_MainTex, uv).a, 0.0);
            }

            fixed isEdgePixel(fixed2 uv)
            {
                return isTransparentPixel(uv);
            }

            fixed4 frag (fragData f) : SV_Target
            {
                float2 borderSize = float2(3, 3); // border size in tex pixels
                float dy = borderSize.y * _MainTex_TexelSize.y;
                fixed3 borderColor = fixed3(0, 0, 0);
                float borderColorsCount = 0;
                fixed2 uv = f.uv;

                // Top edge:
                float2 dTop = float2(-f.up.x * dy, f.up.y * dy);
                fixed isEdge = isEdgePixel(uv + dTop);
                borderColor += isEdge * _TopColor;
                borderColorsCount += isEdge;

                // Bottom edge:
                float2 dDown = dTop * -1;
                isEdge = isEdgePixel(uv + dDown);
                borderColor += isEdge * _BottomColor;
                borderColorsCount += isEdge;

                fixed noBorderColor = step(length(borderColor), 0);
                fixed hasBorderColor = 1 - noBorderColor;
                fixed4 c = tex2D(_MainTex, uv);
                c.rgb = c.rgb * noBorderColor + hasBorderColor * borderColor / max(borderColorsCount, 1);
                return c;
            }
            ENDCG
        }
    }
}