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 { internal readonly glHandle Handle; public readonly ShaderType type; private IglFunc GL; /// /// Inti a shader with no program attached. /// internal unsafe Shader(IglFunc gl, ShaderType t, int count) { GL = gl; type = t; if (type == ShaderType.Program) { Handle = GL.CreateProgram(); } } internal void ChangeEnvironment(IglFunc gl) { GL = gl; } /// /// Compile the vertex shader to be attached to this shader. /// /// GLSL code of vertex shader. public unsafe void CompileShader(string shaderCode) { vertexHandle = GL.CompileShader(shaderCode, type); GL.AttachShader(programHandle, vertexHandle); } /// /// Compile the fragment shader to be attached to this shader. /// /// GLSL code of fragment shader. public unsafe void CompileFragmentShader(string shaderCode) { fragmentHandle = GL.CompileShader(shaderCode, ShaderType.FRAGMENT); GL.AttachShader(programHandle, fragmentHandle); } /// /// Link the shader to current context. /// public void Link() { if (InternalIO.InternalLinkShaderProgram(programHandle) == 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. /// /// Name of the Uniform in shader code /// public unsafe Uniform GetUniform(string name) where T : struct { byte[] bytes = Encoding.ASCII.GetBytes(name); int uniform; fixed (byte* ptr = bytes) { uniform = GL.GetUniformLocation(programHandle, ptr); } if (uniform != -1) { return new Uniform(uniform); } else { throw new Exception($"Cannot find the uniform {name} in shader {programHandle}"); } } /// /// Get a uniform form current shader, /// the value type of the uniform should be provided. /// /// Name of the Uniform in shader code /// public unsafe Uniform GetUniform(string name) where T : struct where U : struct { byte[] bytes = Encoding.ASCII.GetBytes(name); int uniform; fixed (byte* ptr = bytes) { uniform = GL.GetUniformLocation(programHandle, ptr); } if (uniform != -1) { return new Uniform(uniform); } else { throw new Exception($"Cannot find the uniform {name} in shader {programHandle}"); } } /// /// Get a uniform form current shader, /// the value type of the uniform should be provided. /// /// Name of the Uniform in shader code /// public unsafe Uniform GetUniform(string name) where T : struct where U : struct where V : struct { byte[] bytes = Encoding.ASCII.GetBytes(name); int uniform; fixed (byte* ptr = bytes) { uniform = GL.GetUniformLocation(programHandle, ptr); } if (uniform != -1) { return new Uniform(uniform); } else { throw new Exception($"Cannot find the uniform {name} in shader {programHandle}"); } } /// /// Let the current context use this shader. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void Use() { GL.UseProgram(programHandle); } } }