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 ShaderProgram CreateShaderProgram(ShaderType shaderType) { return new ShaderProgram(GL, 1); } } public class Shader { internal readonly glHandle handle; public readonly ShaderType type; private readonly IglFunc GL; internal Shader(IglFunc gl, glHandle handle) { this.handle = handle; GL = gl; } /// /// Compile the vertex shader to be attached to this shader. /// /// GLSL code of vertex shader. public unsafe void Compile(string shaderCode, ShaderType usage, int index) { handle.handle[index] = GL.CompileShader(shaderCode, type).handle; } //TODO:写链接着色器的文档注释 /// /// /// /// /// public void AttachTo(ShaderProgram target, ShaderType usage) { switch (usage) { case ShaderType.Fragment: break; case ShaderType.Vertex: GL.AttachShader(target.handle,) break; default: throw new ArgumentException(); } } } public class ShaderProgram { internal readonly glHandle handle; private readonly IglFunc GL; /// /// Inti a shader with no program attached. /// internal unsafe ShaderProgram(IglFunc gl, int count) { GL = gl; handle = GL.CreateProgram(); } /// /// Link the shader to current context. /// public void Link() { if (InternalIO.InternalLinkShaderProgram(handle[0]) == 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(handle[0], ptr); } if (uniform != -1) { return new Uniform(uniform); } else { throw new Exception($"Cannot find the uniform {name} in shader {handle[0]}"); } } /// /// 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(handle[0], ptr); } if (uniform != -1) { return new Uniform(uniform); } else { throw new Exception($"Cannot find the uniform {name} in shader {handle[0]}"); } } /// /// 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(int index, 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(handle[index], ptr); } if (uniform != -1) { return new Uniform(uniform); } else { throw new Exception($"Cannot find the uniform {name} in shader {handle[index]}"); } } /// /// Let the current context use this shader. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void Use(int index) { GL.UseProgram(handle[index]); } } }