using StgSharp; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; namespace StgSharp.Graphics { public partial class Form { /// /// Create an instance of program /// /// New instance of instance. [MethodImpl(MethodImplOptions.AggressiveInlining)] protected Shader CreateShader() { return new Shader(GL); } public class Shader { /// /// A value represent this shader. /// public readonly uint programID; internal uint vertexShaderID; internal uint fragmentShaderID; private IglFunc GL; /// /// Inti a shader with no program attached. /// internal unsafe Shader(IglFunc glFunc) { GL = glFunc; programID = GL.CreateProgram(); } /// /// Compile the vertex shader to be attached to this shader. /// /// GLSL code of vertex shader. public unsafe void CompileVertexShader(string shaderCode) { vertexShaderID = GL.CompileShader(shaderCode, ShaderType.VERTEX); GL.AttachShader(programID, vertexShaderID); } /// /// Compile the fragment shader to be attached to this shader. /// /// GLSL code of fragment shader. public unsafe void CompileFragmentShader(string shaderCode) { fragmentShaderID = GL.CompileShader(shaderCode, ShaderType.FRAGMENT); GL.AttachShader(programID, fragmentShaderID); } /// /// Link the shader to current context. /// public void Link() { if (InternalIO.InternalLinkShaderProgram(programID) == 0) { IntPtr logPtr = InternalIO.InternalReadLog(); try { byte[] logByte = new byte[512]; Marshal.Copy(logPtr, logByte, 0, 512); string log = Encoding.UTF8.GetString(logByte); log = log.Replace("\0", ""); InternalIO.InternalWriteLog(log, LogType.Error); } catch (Exception ex) { InternalIO.InternalWriteLog(ex.Message, LogType.Error); } } } /// /// Get a uniform form current shader, /// the value type of the uniform should be provided. /// /// /// public unsafe Uniform GetUniform(string name) where T : struct { byte[] bytes = Encoding.ASCII.GetBytes(name); int uniform; fixed (byte* ptr = bytes) { uniform = GL.GetUniformLocation(programID, ptr); } if (uniform != -1) { return new Uniform(uniform); } else { throw new Exception($"Cannot find the uniform {name} in shader {programID}"); } } /// /// Let the current context use this shader. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void Use() { GL.UseProgram(programID); } } } }