private void DecodeWiiUBinary(BfshaLibrary.ResShaderProgram program)
        {
            var vertexShader = BfshaGX2ShaderHelper.CreateVertexShader(ShaderModel, program);
            var pixelShader  = BfshaGX2ShaderHelper.CreatePixelShader(ShaderModel, program);

            GLShaders[ShaderIndex] = CafeShaderDecoder.LoadShaderProgram(vertexShader, pixelShader);
            shaderProgram          = GLShaderInfo.Program;
        }
        /// <summary>
        /// Reloads the glsl shader file from the shader cache or saves a translated one if does not exist.
        /// </summary>
        public void ReloadGLSLShaderFile()
        {
            var vertexData = ShaderModel.ParentFile.Binaries[BinaryIndex];
            var pixelData  = ShaderModel.ParentFile.Binaries[BinaryIndex + 1];

            GLShaders[ShaderIndex] = CafeShaderDecoder.LoadShaderProgram(vertexData.DataBytes, pixelData.DataBytes);
            shaderProgram          = GLShaderInfo.Program;

            UpdateShader = false;
        }
        /// <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;

            CafeShaderDecoder.SetShaderConstants(shader, programID, bfresMaterial);

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

            var pixelShader  = ShaderModel.GetGX2PixelShader(this.BinaryIndex);
            var vertexShader = ShaderModel.GetGX2VertexShader(this.BinaryIndex);

            int bindings = 2;

            for (int i = 0; i < ShaderModel.UniformBlocks.symbols.Count; i++)
            {
                string name = ShaderModel.UniformBlocks.symbols[i].Name;

                //Get the gx2 uniform block and find it's offset info
                var gx2VertexUniformBlock = vertexShader.UniformBlocks.FirstOrDefault(x => x.Name == name);
                var gx2PixelUniformBlock  = pixelShader.UniformBlocks.FirstOrDefault(x => x.Name == name);

                int vertLocation = -1;
                int fragLocation = -1;

                if (gx2VertexUniformBlock != null)
                {
                    vertLocation = (int)gx2VertexUniformBlock.Offset;
                }
                if (gx2PixelUniformBlock != null)
                {
                    fragLocation = (int)gx2PixelUniformBlock.Offset;
                }

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

                var shaderBlock = GetBlock(name);
                LoadUniformBlock(control, shader, i, shaderBlock, name, mesh);
                RenderBlock(shaderBlock, programID, vertLocation, fragLocation, bindings++);
            }
        }
        public void OnLoad(GX2VertexShader vertexShader, GX2PixelShader pixelShader)
        {
            ShaderInfo = CafeShaderDecoder.LoadShaderProgram(vertexShader.DataBytes, pixelShader.DataBytes);

            VertexShaderSource = System.IO.File.ReadAllText(ShaderInfo.VertPath);
            FragShaderSource   = System.IO.File.ReadAllText(ShaderInfo.FragPath);

            if (VertexShaderSource == null)
            {
                VertexShaderSource = "";
            }
            if (FragShaderSource == null)
            {
                FragShaderSource = "";
            }
        }
        /// <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++);
            }
        }