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() { return new ShaderProgram(GL); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected Shader CreateShader(ShaderType type, int count) { return new Shader(this.gl, gl.CreateShaderSet(count, type), type); } } public class Shader { internal readonly glHandleSet handle; public readonly ShaderType type; private readonly IglFunc GL; internal Shader(IglFunc gl, glHandleSet handle, ShaderType usage) { this.handle = handle; GL = gl; type = usage; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void Compile(int index, string code) { if (code == null) { throw new ArgumentNullException("Must provide enough code"); } GL.LoadShaderSource(handle[index], code + '\0'); GL.CompileShader(handle[index]); } //TODO:写链接着色器的文档注释 /// /// /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AttachTo(int index, ShaderProgram target) { GL.AttachShader(target.handle, handle[index]); } public override string ToString() { return $"This is a {type} shader, its shader handles are {handle.ToString()}."; } } public class ShaderProgram { internal readonly glHandle handle; private readonly IglFunc GL; /// /// Inti a shader with no program attached. /// internal unsafe ShaderProgram(IglFunc gl) { GL = gl; handle = GL.CreateProgram(); } /// /// Link the shader to current context. /// public unsafe void Link() { if (InternalIO.InternalLinkShaderProgram(GL.Context, handle.Value) == 0) { IntPtr logPtr = InternalIO.InternalReadSSCLog(); 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 /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe Uniform GetUniform(string name) where T : struct { return new Uniform(this, name, GL); } /// /// 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 { return new Uniform(this, name, GL); } /// /// 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 { return new Uniform(this, name, GL); } /// /// Let the current context use this shader. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void Use() { GL.UseProgram(handle); } } }