using System; using OpenTK.Graphics.OpenGL4; namespace SM.OGL.Shaders { /// /// Abstract class, that is used to create graphic shader. /// public abstract class GenericShader : GLObject { /// /// Contains the different files for the shader. /// protected ShaderFileCollection ShaderFileFiles; /// /// Contains and manage the uniforms from the shader. /// protected UniformCollection Uniforms; /// public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Program; /// protected GenericShader(ShaderFileCollection shaderFileFiles) { ShaderFileFiles = shaderFileFiles; } /// /// Loads the shader to the GPU. /// public void Load() { _id = GL.CreateProgram(); ShaderFileFiles.Append(this); GL.LinkProgram(_id); this.Name(GetType().Name); ShaderFileFiles.Detach(this); GL.GetProgram(_id, GetProgramParameterName.ActiveUniforms, out int uniformCount); if (uniformCount < 1) throw new Exception("[Critical] No uniforms has been found."); Uniforms = new UniformCollection(); Uniforms._parentShader = this; for (int i = 0; i < uniformCount; i++) { string key = GL.GetActiveUniform(_id, i, out _, out _); int loc = GL.GetUniformLocation(_id, key); if (key.EndsWith("]")) key = key.Split('[', ']')[0]; Uniforms.Add(key, loc); } } /// protected override void Compile() { Load(); } /// /// Draws the mesh. /// /// The mesh. /// The amounts for instancing. /// Binds the vertex array for the mesh. protected void DrawObject(Mesh.GenericMesh mesh, int amount, bool bindVAO = false) { if (bindVAO) GL.BindVertexArray(mesh); if (mesh.Indices != null) GL.DrawElementsInstanced(mesh.PrimitiveType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount); else GL.DrawArraysInstanced(mesh.PrimitiveType, 0, mesh.Vertex.Count, amount); } /// /// Resets the shader specific settings to ensure proper workings. /// protected void CleanUp() { Uniforms.NextTexture = 0; GL.BindTexture(TextureTarget.Texture2D, 0); GL.BindVertexArray(0); } } }