title: OpenGl: Vertex data doesn't get sent to the shader correctly
body: <p>I'm reading the book Game Programming in C++ from Madhav Sanjay. I did the exercises in C++ and try to migrate them to C# with the <a href="https://github.com/dotnet/Silk.NET" rel="nofollow noreferrer">Silk.Net</a> library, which is an OpenGL wrapper in .Net: <a href="https://github.com/lehmamic/GameProgrammingExercises" rel="nofollow noreferrer">https://github.com/lehmamic/GameProgrammingExercises</a></p>
  <p>I'm trying to implement skeleton animation. Until now, I had a vertex buffer containing only float values for position, normal and uv. Now I need to mix it with single bytes values. To be able to do that, I made a <code>struct</code> containing those values:</p>
  <pre class="lang-cs prettyprint-override"><code>public struct VertexPosNormTex
  {
      public const uint SizeInBytes = 8 * sizeof(float);
      public const VertexArrayObjectLayout Layout = VertexArrayObjectLayout.PosNormTex;
  
      public Vector3D&lt;float&gt; Position;
  
      public Vector3D&lt;float&gt; Normal;
  
      public Vector2D&lt;float&gt; TexCoords;
  
      public VertexPosNormTex(Vector3D&lt;float&gt; position, Vector3D&lt;float&gt; normal, Vector2D&lt;float&gt; texCoords)
      {
          Position = position;
          Normal = normal;
          TexCoords = texCoords;
      }
  }
  </code></pre>
  <p>And I create my VAO with the following code and that works. This means the old code without skeleton animation works with the new approach and it gets rendered correctly:</p>
  <pre class="lang-cs prettyprint-override"><code>        public unsafe VertexArrayObject(GL gl, ReadOnlySpan&lt;VertexPosNormTex&gt; vertices, uint[] indices)
          {
              _gl = gl;
  
              NumberOfVertices = vertices.Length;
              NumberOfIndices = indices.Length;
  
              // Create vertex array
              _vertexArray = _gl.GenVertexArray();
              _gl.BindVertexArray(_vertexArray);
  
              // Create vertex buffer
              _vertexBuffer = _gl.GenBuffer();
              _gl.BindBuffer(BufferTargetARB.ArrayBuffer, _vertexBuffer);
  
              fixed (void* d = &amp;MemoryMarshal.GetReference(vertices))
              {
                  _gl.BufferData(BufferTargetARB.ArrayBuffer, (nuint) (vertices.Length * VertexPosNormTex.SizeInBytes), d, BufferUsageARB.StaticDraw);
              }
  
              // Create index buffer
              _indexBuffer = _gl.GenBuffer();
              _gl.BindBuffer(BufferTargetARB.ElementArrayBuffer, _indexBuffer);
  
              fixed (void* d = indices)
              {
                  _gl.BufferData(BufferTargetARB.ElementArrayBuffer, (nuint) (indices.Length * sizeof(uint)), d, BufferUsageARB.StaticDraw);
              }
  
              // Specify the vertex attributes
  
              // Position is 3 floats with offset 0
              _gl.EnableVertexAttribArray(0);
              _gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, VertexPosNormTex.SizeInBytes, (void*) 0);
  
              // Normal is 3 floats with offset 3
              _gl.EnableVertexAttribArray(1);
              _gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, VertexPosNormTex.SizeInBytes, (void*) (3 * sizeof(float)));
  
              // Texture coordinates is 2 floats with offset 6
              _gl.EnableVertexAttribArray(2);
              _gl.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, VertexPosNormTex.SizeInBytes, (void*) (6 * sizeof(float)));
          }
  </code></pre>
  <p>Afterwards, I prepared the VAO and Shader for the skeleton animations. First I adjusted the shaders in variables according to the book:</p>
  <pre class="lang-c prettyprint-override"><code>layout(location = 0) in vec3 inPosition;
  layout(location = 1) in vec3 inNormal;
  layout(location = 2) in uvec4 inSkinBones;
  layout(location = 3) in vec4 inSkinWeights;
  layout(location = 4) in vec2 inTexCoord;
  </code></pre>
  <p>The book is written in C++ and uses 4D vectors of unsigned bytes for skins and bones in the buffer to save memory. The bones get transferred directly to the uvec4 variable and the weights get converted to a 4D vector of float.</p>
  <p>I prepared a new Vertex struct for that in C#:</p>
  <pre class="lang-cs prettyprint-override"><code>public struct VertexPosNormSkinTex
  {
      public const uint SizeInBytes = 8 * sizeof(float) + 8 * sizeof(byte);
      public const VertexArrayObjectLayout Layout = VertexArrayObjectLayout.PosNormSkinTex;
  
      public Vector3D&lt;float&gt; Position;
  
      public Vector3D&lt;float&gt; Normal;
  
      public Vector4D&lt;byte&gt; SkinningIndices;
  
      public Vector4D&lt;byte&gt; SkinningWeights;
  
      public Vector2D&lt;float&gt; TexCoords;
  
      public VertexPosNormSkinTex(Vector3D&lt;float&gt; position, Vector3D&lt;float&gt; normal, Vector4D&lt;byte&gt; skinningIndices,
          Vector4D&lt;byte&gt; skinningWeights, Vector2D&lt;float&gt; texCoords)
      {
          Position = position;
          Normal = normal;
          SkinningIndices = skinningIndices;
          SkinningWeights = skinningWeights;
          TexCoords = texCoords;
      }
  }
  </code></pre>
  <p>And adjusted the VOA creation code:</p>
  <pre class="lang-cs prettyprint-override"><code> public unsafe VertexArrayObject(GL gl, ReadOnlySpan&lt;VertexPosNormSkinTex&gt; vertices, uint[] indices)
          {
              _gl = gl;
  
              NumberOfVertices = vertices.Length;
              NumberOfIndices = indices.Length;
  
              // Create vertex array
              _vertexArray = _gl.GenVertexArray();
              _gl.BindVertexArray(_vertexArray);
  
              // Create vertex buffer
              _vertexBuffer = _gl.GenBuffer();
              _gl.BindBuffer(BufferTargetARB.ArrayBuffer, _vertexBuffer);
  
              fixed (void* d = vertices)
              {
                  _gl.BufferData(BufferTargetARB.ArrayBuffer, (nuint) (vertices.Length * VertexPosNormSkinTex.SizeInBytes), d, BufferUsageARB.StaticDraw);
              }
  
              // Create index buffer
              _indexBuffer = _gl.GenBuffer();
              _gl.BindBuffer(BufferTargetARB.ElementArrayBuffer, _indexBuffer);
  
              fixed (void* d = indices)
              {
                  _gl.BufferData(BufferTargetARB.ElementArrayBuffer, (nuint) (indices.Length * sizeof(uint)), d, BufferUsageARB.StaticDraw);
              }
  
              // Specify the vertex attributes
              
              // Position is 3 floats with offset 0
              _gl.EnableVertexAttribArray(0);
              _gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, VertexPosNormSkinTex.SizeInBytes, (void*) 0);
  
              // Normal is 3 floats with offset 3
              _gl.EnableVertexAttribArray(1);
              _gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, VertexPosNormSkinTex.SizeInBytes, (void*) (3 * sizeof(float)));
  
              // Skinning indices (keep as ints)
              _gl.EnableVertexAttribArray(2);
              _gl.VertexAttribIPointer(2, 4, VertexAttribIType.UnsignedByte, VertexPosNormSkinTex.SizeInBytes, (void*) (6 * sizeof(float)));
  
              // Skinning weights (convert to floats)
              _gl.EnableVertexAttribArray(3);
              _gl.VertexAttribPointer(3, 4, VertexAttribPointerType.UnsignedByte, true, VertexPosNormSkinTex.SizeInBytes, (void*) (6 * sizeof(float) + 4 * sizeof(byte)));
  
              // Texture coordinates is 2 floats
              _gl.EnableVertexAttribArray(4);
              _gl.VertexAttribPointer(4, 2, VertexAttribPointerType.Float, false, VertexPosNormSkinTex.SizeInBytes, (void*) (6 * sizeof(float) + 8 * sizeof(byte)));
          }
  </code></pre>
  <p>Notice, that I send the bone indices as ints to the shader and the bone weights as floats, event though they are byte in the vertex object. It should be according to the implementation in the book.</p>
  <p>The model gets rendered, so the position and normal variables get transferred correctly. But the texture is rendered wrong. I think, it must be something about the vertex layout in memory or I configure the vertex attribute pointers not correctly.</p>
  <p><a href="https://i.stack.imgur.com/5nhVX.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/5nhVX.jpg" alt="Rendered Model" /></a></p>
  <p>Edit:
  I check the first vertex in RenderDoc. The UV Coords seem to be transferred correctly. The shader code is complete the same except the in variables - I don't get it.</p>