The Surface Shader is Black

I was using an Unlit Shader on a grass.

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'

Shader "Unlit/GrassUnlitShader"
{
    Properties
    {
        _TopColor("Top Color", Color) = (1,1,1,1)
        _BottomColor("Color", Color) = (0,0,0,0)
        _SSSColor("SSS Color", Color) = (0,0,0,0)
        _SSSValue("SSS", float) = 0
        //_LightDir("Light Direction", float3)
    }
    SubShader
    {
        LOD 100
        Cull Off

        Pass
        {
            Tags
            {
                "RenderType" = "Opaque"
                "LightMode" = "ForwardBase"
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
          
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
            #include "AutoLight.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                SHADOW_COORDS(1)
                float4 pos : SV_POSITION;
            };

            fixed4 _TopColor;
            fixed4 _BottomColor;
            fixed4 _SSSColor;
            float _SSSValue;

           // float3 _LightDir;

            v2f vert (appdata v)
            {
                v2f o;
                //o.pos = v.vertex.pos;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;

              

                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_SHADOW(o);

                //float time = _Time.y;
              
                //if(o.uv.y > 1){
                //o.pos.x = sin(time*o.pos.y);
                //}

            return o;
            }
          
            fixed4 frag (v2f i) : SV_Target
            {
                fixed shadow = SHADOW_ATTENUATION(i);
                fixed4 col = lerp(_BottomColor, _TopColor, i.uv.y*_SSSValue);// * .7 + shadow * .3;// + lerp(_SSSColor, _BottomColor, i.uv.x);

                UNITY_APPLY_FOG(i.fogCoord, col);

                return col;
            }
            ENDCG
        }

    }

 
   

}

I tried to move to a Surface Shader but the material was all black and now the triangles are also visible.

Shader "Custom/SurfaceShader"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _TopColor("Top Color", Color) = (1,1,1,1)
        _BottomColor("Color", Color) = (0,0,0,0)
        _SSSColor("SSS Color", Color) = (0,0,0,0)
        _SSSValue("SSS", float) = 0
    }
    SubShader
    {
           Tags
            {
                "RenderType" = "Opaque"
                "LightMode" = "ForwardBase"
            }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

            #pragma multi_compile_fog
          
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
            #include "AutoLight.cginc"

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _TopColor;
        fixed4 _BottomColor;
        fixed4 _SSSColor;
        float _SSSValue;
        fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            c *= lerp(_BottomColor, _TopColor, IN.uv_MainTex.y*_SSSValue);// * .7 + shadow * .3;// + lerp(_SSSColor, _BottomColor, i.uv.x);
            //o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

Can someone help me solve this

_BottomColor is currently default to black, _SSSValue is currently default to 0. IN.uv_MainTex.y * _SSSValue will always = 0 with those default values. Thus it will result in that lerp() always returning _BottomColor, which is black. Does it still remain black after you set _SSSValue to 1?

Also it seems the surface normals are messed up on your grass, some triangles facing forward while others not. By default, Surface shaders will have backface culling on, so those triangle backfaces aren’t being rendered. You’ll want to add Cull Off below the LOD 200 line you have there, but I would recommend against doing this for performance reasons, especially with grass…

What you really want to do is fix the per-triangle switching of backfaces there, which means that all the vertices in your mesh are split even though they don’t appear to have any reason to be… I would open that model up in your modeling program, do a merge of very close distance vertices and do a soften surface normals (may have to do a unify face normals first, google how to do this stuff in your modeling program of your choice).

Also I’d recommend removing the novertexlight from your #pragma section

Thanks for the answer.

The value of _SSSValue is 1 and the BottomColor is green.
I’m not using a modeling program, this mesh was generated by a C # script

Alright then, well first you need to check the winding order in your mesh generation. It looks like every second triangle has the wrong winding order, resulting in it becoming a backface. Also are you making sure to share connected vertices in your mesh generation or are you just lazy creating vert by vert for each triangle?

Are you also generating the appropriate Normals for your mesh alongside the triangles as you create them?

Did removing that #pragma option I mentioned help at all? And first comes first, try simply having the shader output a hard-coded color value in the surf function instead of from a lerp or property just in case there’s some material shenanigans going on here…

I removed the #pragma and didn’t see much difference I think it’s because I didn’t test it with
more than one grass.

The code to generate the mesh is this one:

    Mesh createMesh()
    {
        Mesh mesh = new Mesh();
        int[] triangles = new int[0];
        Vector3[] fixedVertices = new Vector3[0];
        Vector3[] vertices = new Vector3[0];
        Vector2[] uvs = new Vector2[0];

        int nGrass = (int)grassAmount;//(int)Mathf.Floor(grassDensity/Mathf.PI * grassRadius * grassRadius);
        int nVertex = 2 * nVertical + 1;//Numero de divisoes * 2 (2 vertices por divisao)
        int nTris = 2 * nVertical - 1;

        float nInverse = 1.0f / nVertical;
        //Debug.Log("Generate grass: " + nGrass);

        vertices = new Vector3[nVertex * nGrass];
        triangles = new int[nTris * 3 * nGrass];
        uvs = new Vector2[vertices.Length];

        float indexHeight = Random.Range(maxHeight*VariableHeight, maxHeight);

        for (int n = 0; n < nGrass; ++n)
        {
            //List<List<Vector3>> verletComponents = new List<List<Vector3>>();

            float height = Random.Range((indexHeight/nVertical)*0.3f, indexHeight/nVertical);

            int grassIdx = nVertex * n;

            float stime = (float)n / nGrass;
            //float multiply = AmountFormat.Evaluate(stime) * AmountFormatMultiply;
            //multiply = Mathf.Lerp(width, 0, AmountFormat.Evaluate(stime));

            for (int i = 0; i <= nVertical; ++i)
            {
                //if (i > verletComponents.Count)
                //verletComponents.Add(new List<Vector3>());

                float s = (float)i / nVertical;
                float w = Mathf.Lerp(width, 0, VerticesRightWidth.Evaluate(s));
                float z = Mathf.Lerp(width, 0, VerticesLeftWidth.Evaluate(s));
                //Debug.Log("Animation: "+ VerticesWidth.Evaluate(s));
                //Debug.Log("Log: "+i+" "+nVertical);
                //Debug.Log("w: "+ w);
                //if (i < nVertical)
                float t = Random.Range(-GrassFormat,GrassFormat);
                //else
                //vertices[grassIdx + i * 2] = new Vector3(0, height * i, 0);

                float pointAbs = AmountFormat.Evaluate(stime) * s;

                if (i != nVertical){
                vertices[grassIdx + i * 2] = new Vector3(width - w + t + Mathf.Lerp(width, 0, pointAbs), height * i, 0);
                vertices[grassIdx + i * 2 + 1] = new Vector3(width - z + t + Mathf.Lerp(width, 0, pointAbs), height * i, 0);
                }else
                vertices[grassIdx + i * 2] = new Vector3(width + Mathf.Lerp(width, 0, pointAbs), height * i, 0);
                    //verletComponents[i].Add((vertices[grassIdx + i * 2]+ vertices[grassIdx + i * 2 + 1])/2);
                //}
                //else
                //{
                //    verletComponents[i].Add(vertices[grassIdx + i * 2]);
                //}
            }

            int trisIdx = nTris * 3 * n;
            for (int i = 0; i < nTris; i++)
            {
                triangles[trisIdx + i * 3] = grassIdx + i;
                triangles[trisIdx + i * 3 + 1] = grassIdx + i + 1;
                triangles[trisIdx + i * 3 + 2] = grassIdx + i + 2;
            }

            for (int i = 0; i < uvs.Length; ++i)
            {
                Vector3 vert = vertices[i];
                uvs[i] = new Vector2(vert.x, vert.y);
            }

            Quaternion rotation = Quaternion.Euler(0, 30, 0);
            Matrix4x4 m = Matrix4x4.Rotate(rotation);

            Vector3 offset = new Vector3(Random.Range(0, grassRadius/10), 0, Random.Range(0, grassRadius/10));

            for (int i = 0; i < vertices.Length; ++i)
            {
                vertices[i] = m.MultiplyPoint3x4(vertices[i]) - offset;
            }

            fixedVertices = new Vector3[vertices.Length];
            for (int i = 0; i < vertices.Length; ++i)
            {
                fixedVertices[i] = vertices[i];
            }
        }

        mesh.name = "Grass";
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.uv = uvs;
        mesh.RecalculateNormals();

    return mesh;
}

I did it following some Mesh tutorials, so it is likely that something is wrong.


5832895--618727--xzcv.PNG