private void DrawModel(GLControl control, GFBMesh m, ShaderProgram shader)
        {
            foreach (var group in m.PolygonGroups)
            {
                if (group.faces.Count <= 3)
                {
                    return;
                }

                var Material = m.ParentModel.header.Materials[group.MaterialIndex];

                SetUniforms(m.GetMaterial(group), shader, m, m.DisplayId);
                SetUniformBlocks(m.GetMaterial(group), shader, m, m.DisplayId);
                SetBoneUniforms(control, shader, m);
                SetVertexAttributes(m, shader);
                SetTextureUniforms(m.GetMaterial(group), m, shader);

                if (m.IsSelected)
                {
                    DrawModelSelection(group, shader);
                }
                else
                {
                    if (Runtime.RenderModels)
                    {
                        GL.DrawElements(PrimitiveType.Triangles, group.displayFaceSize, DrawElementsType.UnsignedInt, group.Offset);
                    }
                }
            }
        }
        private static void SetUniforms(GFBMaterial mat, ShaderProgram shader, GFBMesh m, int id)
        {
            // Texture Maps

            /*  shader.SetBoolToInt("useColorTex", false);
             * shader.SetBoolToInt("EmissionMaskUse", false);
             * shader.SetBoolToInt("SwitchPriority", false);
             * shader.SetBoolToInt("Layer1Enable", false);
             * shader.SetBoolToInt("AmbientMapEnable", false);
             * shader.SetBoolToInt("NormalMapEnable", false);
             * shader.SetBoolToInt("LightTableEnable", false);
             * shader.SetBoolToInt("BaseColorAddEnable", false);
             * shader.SetBoolToInt("SphereMapEnable", false);
             * shader.SetBoolToInt("EffectVal", false);*/

            //Switch UVs
            shader.SetBoolToInt("SwitchEmissionMaskTexUV", false);
            shader.SetBoolToInt("SwitchAmbientTexUV", false);
            shader.SetBoolToInt("SwitchNormalMapUV", false);

            //UV Scale
            shader.SetFloat("ColorUVScaleU", 1);
            shader.SetFloat("ColorUVScaleV", 1);

            //UV Translate
            shader.SetFloat("ColorUVTranslateU", 0);
            shader.SetFloat("ColorUVTranslateV", 0);

            SetUniformData(mat, shader, "ColorUVScaleU");
            SetUniformData(mat, shader, "ColorUVScaleV");
            SetUniformData(mat, shader, "ColorUVTranslateU");
            SetUniformData(mat, shader, "ColorUVTranslateV");
        }
        private static void SetBoneUniforms(GLControl control, ShaderProgram shader, GFBMesh mesh)
        {
            int i = 0;

            foreach (var bone in mesh.ParentModel.header.Skeleton.bones)
            {
                Matrix4 transform = bone.invert * bone.Transform;

                GL.UniformMatrix4(GL.GetUniformLocation(shader.programs[control], String.Format("bones[{0}]", i++)), false, ref transform);
            }

            /*  foreach (var FaceGroup in fshp.Shape.FaceGroups)
             * {
             *    if (FaceGroup.BoneIndexList == null)
             *        continue;
             *
             *    for (int i = 0; i < FaceGroup.BoneIndexList.Length; i++)
             *    {
             *        GL.Uniform1(GL.GetUniformLocation(shader.programs[control], String.Format("boneIds[{0}]", i)), FaceGroup.BoneIndexList[i]);
             *
             *        Matrix4 transform = fmdl.Skeleton.Renderable.bones[(int)FaceGroup.BoneIndexList[i]].invert * fmdl.Skeleton.Renderable.bones[(int)FaceGroup.BoneIndexList[i]].Transform;
             *        GL.UniformMatrix4(GL.GetUniformLocation(shader.programs[control], String.Format("bones[{0}]", i)), false, ref transform);
             *    }
             * }*/
        }
 private void SetVertexAttributes(GFBMesh m, ShaderProgram shader)
 {
     GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
     GL.VertexAttribPointer(shader.GetAttribute("vPosition"), 3, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 0);   //+12
     GL.VertexAttribPointer(shader.GetAttribute("vNormal"), 3, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 12);    //+12
     GL.VertexAttribPointer(shader.GetAttribute("vTangent"), 3, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 24);   //+12
     GL.VertexAttribPointer(shader.GetAttribute("vUV0"), 2, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 36);       //+8
     GL.VertexAttribPointer(shader.GetAttribute("vColor"), 4, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 44);     //+16
     GL.VertexAttribIPointer(shader.GetAttribute("vBone"), 4, VertexAttribIntegerType.Int, GFBMesh.DisplayVertex.Size, new IntPtr(60));  //+16
     GL.VertexAttribPointer(shader.GetAttribute("vWeight"), 4, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 76);    //+16
     GL.VertexAttribPointer(shader.GetAttribute("vUV1"), 2, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 92);       //+8
     GL.VertexAttribPointer(shader.GetAttribute("vUV2"), 2, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 100);      //+8
     GL.VertexAttribPointer(shader.GetAttribute("vBinormal"), 3, VertexAttribPointerType.Float, false, GFBMesh.DisplayVertex.Size, 108); //+12
     GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
 }
        private void SetUniformBlocks(GFBMaterial mat, ShaderProgram shader, GFBMesh m, int id)
        {
            /*     shader.UniformBlockBinding("TexCoord1", 3);
             *   GL.GetActiveUniformBlock(shader.program,
             *                   shader.GetUniformBlockIndex("TexCoord1"),
             *                   ActiveUniformBlockParameter.UniformBlockBinding, out int binding);*/

            /*      GL.BindBuffer(BufferTarget.UniformBuffer, TexCoord1Buffer);
             *    GL.BufferData(BufferTarget.UniformBuffer,
             *    (IntPtr)MTOBWrapper.TexCoord1.Size,
             *    ref mat.TexCoord1Buffer,
             *    BufferUsageHint.StaticDraw);
             *    GL.BindBuffer(BufferTarget.UniformBuffer, 0);
             *    GL.BindBufferRange(BufferRangeTarget.UniformBuffer, 0, TexCoord1Buffer, (IntPtr)0,
             *        MTOBWrapper.TexCoord1.Size);
             *    GL.BindBuffer(BufferTarget.UniformBuffer, TexCoord1Buffer);
             *    GL.BINDBUFFER*/
        }
        private static void SetTextureUniforms(GFBMaterial mat, GFBMesh m, ShaderProgram shader)
        {
            SetDefaultTextureAttributes(mat, shader);

            GL.ActiveTexture(TextureUnit.Texture0 + 1);
            GL.BindTexture(TextureTarget.Texture2D, RenderTools.defaultTex.RenderableTex.TexID);

            GL.Uniform1(shader["debugOption"], 2);

            GL.ActiveTexture(TextureUnit.Texture11);
            GL.Uniform1(shader["weightRamp1"], 11);
            GL.BindTexture(TextureTarget.Texture2D, RenderTools.BoneWeightGradient.Id);

            GL.ActiveTexture(TextureUnit.Texture12);
            GL.Uniform1(shader["weightRamp2"], 12);
            GL.BindTexture(TextureTarget.Texture2D, RenderTools.BoneWeightGradient2.Id);


            GL.ActiveTexture(TextureUnit.Texture10);
            GL.Uniform1(shader["UVTestPattern"], 10);
            GL.BindTexture(TextureTarget.Texture2D, RenderTools.uvTestPattern.RenderableTex.TexID);

            shader.SetInt("RedChannel", 0);
            shader.SetInt("GreenChannel", 1);
            shader.SetInt("BlueChannel", 2);
            shader.SetInt("AlphaChannel", 3);

            LoadPBRMaps(shader);

            foreach (STGenericMatTexture matex in mat.TextureMaps)
            {
                if (matex.Type == STGenericMatTexture.TextureType.Diffuse)
                {
                    shader.SetBoolToInt("HasDiffuse", true);
                    TextureUniform(shader, mat, true, "DiffuseMap", matex);
                }
            }
        }