Can`t pass extra data to shader effect

I am drawing an isometric tilemap and need to have different shading for each level, so I need to pass extra data like tile position to get level in the pixel shader and apply shading.
This is shader

#if OPENGL
	#define SV_POSITION POSITION
	#define VS_SHADERMODEL vs_3_0
	#define PS_SHADERMODEL ps_3_0
#else
	#define VS_SHADERMODEL vs_4_0_level_9_1
	#define PS_SHADERMODEL ps_4_0_level_9_1
#endif

float4x4 WorldViewProjection;

float2 MinMaxLevel;

Texture2D Texture;
sampler2D TextureSampler = sampler_state
{
    Texture = <Texture>;
};

// Daytime. 
//0     - 00:00 
//0.25  - 06:00
//0.5   - 12:00
//0.75  - 18:00
//1     - 24:00
float1 DayTime;
float4 SunRiseColor;
float4 SunSetColor;

float4 AmbientColor = float4(1, 1, 1, 1);

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 TextureCoordinates : TEXCOORD0;
    float4 Color : COLOR0;
    float3 BlockPosition : POSITION1;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TextureCoordinates : TEXCOORD0;
    float4 Diffuse : COLOR0;
    float3 BlockPosition : POSITION1;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
    
    output.Position = mul(input.Position, WorldViewProjection);
    output.TextureCoordinates = input.TextureCoordinates;
    output.Diffuse = input.Color;
    output.BlockPosition = input.BlockPosition;

    return output;
}



float4 PixelShaderFunction(VertexShaderOutput input) : SV_Target0
{
    // get pixel color
    float4 color = tex2D(TextureSampler, input.TextureCoordinates) * input.Diffuse;
    // clip pixel if too opakue
    clip((color.a < 0.1) ? -1 : 1);
    
    // calc and apply light
    float1 light = 1 - abs(DayTime * 2 - 1);
    
    // light darken
    //color.rgb = color.rgb * light;
    
    // light desaturation
    float luminance = dot(color.rgb, float3(0.2126, 0.7152, 0.0722));
    float3 grayScale = float3(luminance, luminance, luminance)/2;
    color.rgb = lerp(grayScale, color.rgb, float3(light,light,light));
    
    // level shading
    //color.rgb *= (1- (MinMaxLevel.y - input.BlockPosition.z) * 0.01);
    if (input.BlockPosition.z == 0)
        color.rgb = float3(0, 0, 0);
    return color;
}

technique MainTech
{
    pass MainPass
    {
        VertexShader = compile VS_SHADERMODEL VertexShaderFunction();
        PixelShader = compile PS_SHADERMODEL PixelShaderFunction();
    }
}

This is my custom vertex declaration

[StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct VertexPositionColorTextureBlock : IVertexType
    {
        public Vector3 Position;

        public Color Color;

        public Vector2 TextureCoordinate;

        public Vector3 BlockPosition;

        public static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration(
                new VertexElement(VertexElementByteOffset.PositionStartOffset(), VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
                new VertexElement(VertexElementByteOffset.OffsetColor(), VertexElementFormat.Color, VertexElementUsage.Color, 0),
                new VertexElement(VertexElementByteOffset.OffsetVector2(), VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
                new VertexElement(VertexElementByteOffset.OffsetVector3(), VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 0));

        VertexDeclaration IVertexType.VertexDeclaration => VertexDeclaration;

        public VertexPositionColorTextureBlock(Vector3 position, Color color, Vector2 textureCoordinate, Vector3 blockPosition)
        {
            Position = position;
            Color = color;
            TextureCoordinate = textureCoordinate;
            BlockPosition = blockPosition;
        }

        public override int GetHashCode()
        {
            throw new NotImplementedException();
            return (((Position.GetHashCode() * 397) ^ Color.GetHashCode()) * 397) ^ TextureCoordinate.GetHashCode();
        }

        public override string ToString()
        {
            string[] obj = new string[7] { "{{Position:", null, null, null, null, null, null };
            Vector3 position = Position;
            obj[1] = position.ToString();
            obj[2] = " Color:";
            Color color = Color;
            obj[3] = color.ToString();
            obj[4] = " TextureCoordinate:";
            Vector2 textureCoordinate = TextureCoordinate;
            obj[5] = textureCoordinate.ToString();
            obj[6] = "}}";
            return string.Concat(obj);
        }

        public static bool operator ==(VertexPositionColorTextureBlock left, VertexPositionColorTextureBlock right)
        {
            if (left.Position == right.Position && left.Color == right.Color)
            {
                return left.TextureCoordinate == right.TextureCoordinate;
            }

            return false;
        }

        public static bool operator !=(VertexPositionColorTextureBlock left, VertexPositionColorTextureBlock right)
        {
            return !(left == right);
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }

            if (obj.GetType() != GetType())
            {
                return false;
            }

            return this == (VertexPositionColorTextureBlock)obj;
        }

        /// <summary>
        /// This is a helper struct for tallying byte offsets
        /// </summary>
        public struct VertexElementByteOffset
        {
            public static int currentByteSize = 0;

            //[STAThread]
            public static int PositionStartOffset()
            { currentByteSize = 0; var s = sizeof(float) * 3; currentByteSize += s; return currentByteSize - s; }

            public static int Offset(int n)
            { var s = sizeof(int); currentByteSize += s; return currentByteSize - s; }

            public static int Offset(float n)
            { var s = sizeof(float); currentByteSize += s; return currentByteSize - s; }

            public static int Offset(Vector2 n)
            { var s = sizeof(float) * 2; currentByteSize += s; return currentByteSize - s; }

            public static int Offset(Color n)
            { var s = sizeof(int); currentByteSize += s; return currentByteSize - s; }

            public static int Offset(Vector3 n)
            { var s = sizeof(float) * 3; currentByteSize += s; return currentByteSize - s; }

            public static int Offset(Vector4 n)
            { var s = sizeof(float) * 4; currentByteSize += s; return currentByteSize - s; }

            public static int OffsetInt()
            { var s = sizeof(int); currentByteSize += s; return currentByteSize - s; }

            public static int OffsetFloat()
            { var s = sizeof(float); currentByteSize += s; return currentByteSize - s; }

            public static int OffsetColor()
            { var s = sizeof(int); currentByteSize += s; return currentByteSize - s; }

            public static int OffsetVector2()
            { var s = sizeof(float) * 2; currentByteSize += s; return currentByteSize - s; }

            public static int OffsetVector3()
            { var s = sizeof(float) * 3; currentByteSize += s; return currentByteSize - s; }

            public static int OffsetVector4()
            { var s = sizeof(float) * 4; currentByteSize += s; return currentByteSize - s; }
        }
    }

Now it causes the error ‘Shader Compilation Failed’. But I changed the semantics and the vertex transfer type method, but then it passed 0, that is, all pixels were painted black as if input.BlockPosition.z == 0 always worked.

I checked different lessons, guides, and docs. But didn’t find any solutions.

UPD. I know I can make level global variable and change it every level i draw, but i need BlockPosition for future light system.

Your VertexDeclaration does not fit the structure in the shader.

you send pos0, color0, tex0, tex0

the shader expects pos0, tex0, col0, pos1

try this

public Vector3 Position;
public Vector2 TextureCoordinate;
public Color Color;
public Vector3 BlockPosition;

public static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration(
        new VertexElement(<offset>, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
        new VertexElement(<offset>, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
        new VertexElement(<offset>, VertexElementFormat.Color, VertexElementUsage.Color, 0),
        new VertexElement(<offset>, VertexElementFormat.Vector3, VertexElementUsage.Position, 1));

(from memory, not checked)

Yes, you are right. Than you. Do you know any good descriptions about Semantics and another specific shader systems for dummies. I have some understanding. But I feel like it’s not enough.