/// <summary>
        /// The render loop to draw the material
        /// </summary>
        public override void Render(GLContext control, ShaderProgram shader, GenericPickableMesh mesh)
        {
            var bfresMaterial = (FMAT)this.MaterialData;
            var bfresMesh     = (BfresMeshAsset)mesh;

            //Set the SRGB setting
            control.UseSRBFrameBuffer = UseSRGB;

            var programID = shader.program;

            //Set constants saved from shader code to the first uniform block of each stage
            if (IsSwitch)
            {
                LoadVertexShaderConstantBlock(programID);
                LoadPixelShaderConstantBlock(programID);
            }

            if (!IsSwitch)
            {
                CafeShaderDecoder.SetShaderConstants(shader, programID, bfresMaterial);
            }

            //Set in tool selection coloring
            shader.SetVector4("extraBlock.selectionColor", new Vector4(0));
            if (bfresMesh.IsSelected)
            {
                shader.SetVector4("extraBlock.selectionColor", new Vector4(1, 1, 0.5f, 0.010f));
            }

            //Set material raster state and texture samplers
            SetBlendState(bfresMaterial);
            SetTextureUniforms(control, shader, MaterialData);
            SetRenderState(bfresMaterial);

            int binding = IsSwitch ? 2 : 0;

            for (int i = 0; i < ShaderModel.UniformBlocks.Count; i++)
            {
                string name         = ShaderModel.UniformBlocks.GetKey(i);
                var    uniformBlock = ShaderModel.UniformBlocks[i];

                var locationInfo = ProgramPasses[this.ShaderIndex].UniformBlockLocations[i];
                int fragLocation = locationInfo.FragmentLocation;
                int vertLocation = locationInfo.VertexLocation;

                //Block unused for this program so skip it
                if (fragLocation == -1 && vertLocation == -1)
                {
                    continue;
                }

                var shaderBlock = GetBlock(name + "vs", false);

                //If a block is not cached, update it in the render loop.
                if (!BlocksToCache.Contains(name))
                {
                    shaderBlock.Buffer.Clear();
                    LoadUniformBlock(control, shader, i, shaderBlock, name, mesh);
                }

                RenderBlock(shaderBlock, programID, vertLocation, fragLocation, binding++);
            }
        }
        public override void LoadUniformBlock(GLContext control, ShaderProgram shader, int index, UniformBlock block, string name, GenericPickableMesh mesh)
        {
            var bfresMaterial = (FMAT)this.MaterialData;
            var bfresMesh     = (BfresMeshAsset)mesh;
            var meshBone      = ParentModel.Skeleton.Bones[bfresMesh.BoneIndex];

            switch (name)
            {
            case "cMdlEnvView":
                SetViewportUniforms(control.Camera, block);
                break;

            case "cEchoBlockUniform":
                break;

            case "cHdrTranslate":
                SetHdrUniforms(block);
                break;

            case "cModelAdditionalInfo":
                SetModelUniforms(block);
                break;

            case "cMat":
                SetMaterialBlock(bfresMaterial, block);
                break;

            case "cWater":
                break;

            case "cShaderOption":
                SetMaterialOptionsBlock(bfresMaterial, block);
                break;

            case "skel":
                SetBoneMatrixBlock(this.ParentModel.Skeleton, bfresMesh.SkinCount > 1, block, 170);
                break;

            case "shape":
                SetShapeUniforms(bfresMesh, meshBone.Transform, block);
                break;
            }
        }
 public virtual void LoadUniformBlock(GLContext control, ShaderProgram shader, int index, UniformBlock block, string name, GenericPickableMesh mesh)
 {
 }
        public override void LoadUniformBlock(GLContext control, ShaderProgram shader, int index, UniformBlock block, string name, GenericPickableMesh mesh)
        {
            var bfresMaterial = (FMAT)this.MaterialData;
            var bfresMesh     = (BfresMeshAsset)mesh;
            var meshBone      = ParentModel.Skeleton.Bones[bfresMesh.BoneIndex];

            switch (name)
            {
            case "gsys_context":
                SetViewportUniforms(control.Camera, block);
                break;

            case "gsys_material":
                SetMaterialBlock(bfresMaterial, block);
                break;

            case "gsys_shape":
                SetShapeBlock(bfresMesh, meshBone.Transform, block);
                break;

            case "gsys_skeleton":
                SetBoneMatrixBlock(this.ParentModel.Skeleton, bfresMesh.SkinCount > 1, block, 200);
                break;

            case "gsys_environment":
                SetEnvUniforms(block);
                break;

            case "gsys_scene_material":
                SetSceneMatUniforms(block);
                break;

            case "gsys_res_material":
                SetResMatUniforms(block);
                break;

            case "gsys_shader_option":
                SetMaterialOptionsBlock(bfresMaterial, block);
                break;
            }
        }
        public override void LoadUniformBlock(GLContext control, ShaderProgram shader, int index, UniformBlock block, string name, GenericPickableMesh mesh)
        {
            var bfresMaterial = (FMAT)this.MaterialData;
            var bfresMesh     = (BfresMeshAsset)mesh;
            var meshBone      = ParentModel.Skeleton.Bones[bfresMesh.BoneIndex];
            var sharcBlock    = ShaderModel.UniformBlocks.symbols[index];

            switch (name)
            {
            case "MdlEnvView":
                SetViewportUniforms(control.Camera, block);
                break;

            case "Mat":
                SetMaterialBlock(bfresMaterial, block);
                break;

            case "Shp":
                SetShapeBlock(bfresMesh, meshBone.Transform, block, sharcBlock.DefaultValue?.Length >= 48);
                break;

            case "MdlMtx":
                SetBoneMatrixBlock(this.ParentModel.Skeleton, bfresMesh.SkinCount > 1, block, 64);
                break;
            }
        }