public Shader(string[] vs, string[] fs) { if (!compile(ref verterxId_, ShaderType.VertexShader, vs)) { Console.WriteLine("ERROR: while compiling vertex shader"); } if (!compile(ref fragmentId_, ShaderType.FragmentShader, fs)) { Console.WriteLine("ERROR: while compiling fragment shader"); } programId_ = Gl.CreateProgram(); Gl.AttachShader(programId_, verterxId_); Gl.AttachShader(programId_, fragmentId_); Gl.BindAttribLocation(programId_, ATTRIB_VERTICES_POS, "in_vertex"); Gl.LinkProgram(programId_); int errorlk = 0; Gl.GetProgram(programId_, ProgramProperty.LinkStatus, out errorlk); if (errorlk != Gl.TRUE) { Console.WriteLine("ERROR: while linking Shader :"); int errorSize = 0; Gl.GetProgram(programId_, ProgramProperty.InfoLogLength, out errorSize); StringBuilder error = new StringBuilder(1024); Gl.GetShaderInfoLog(programId_, errorSize, out errorSize, error); Console.WriteLine(error.ToString()); error.Clear(); Gl.DeleteProgram(programId_); } }
/// <summary> /// Create a shader program by linking compiled shaders. /// </summary> /// <param name="vertShader">The vert shader to attach.</param> /// <param name="fragShader">The frag shader to attach.</param> /// <returns></returns> public static ShaderProgram CreateFromShaders(uint vertShader, uint fragShader) { Debug.Assert(GLThread.IsGLThread()); uint pointer = Gl.CreateProgram(); Gl.AttachShader(pointer, vertShader); Gl.AttachShader(pointer, fragShader); // Set default parameter locations. Gl.BindAttribLocation(pointer, VertexLocation, "vertPos"); Gl.BindAttribLocation(pointer, UvLocation, "uv"); Gl.BindAttribLocation(pointer, ColorLocation, "color"); Gl.LinkProgram(pointer); if (Engine.Configuration.GlDebugMode) { Gl.ValidateProgram(pointer); } // Check linking status. var programCompileStatusReader = new StringBuilder(1024); Gl.GetProgramInfoLog(pointer, 1024, out int length, programCompileStatusReader); if (length > 0) { var programStatus = programCompileStatusReader.ToString(0, length); if (programStatus != "") { Engine.Log.Warning($"Log for linking shaders (v:{vertShader} f:{fragShader}) is {programStatus}", MessageSource.GL); } } var valid = false; Gl.GetProgram(pointer, ProgramProperty.LinkStatus, out int state); if (state == 0) { Engine.Log.Warning($"Couldn't link shader program {pointer}.", MessageSource.GL); } else { valid = true; } var newProgram = new ShaderProgram { Pointer = pointer, Valid = valid }; return(newProgram); }
public ShaderProgram(uint vertShader, uint fragShader) { Pointer = Gl.CreateProgram(); Gl.AttachShader(Pointer, vertShader); Gl.AttachShader(Pointer, fragShader); // Set default parameter locations. Gl.BindAttribLocation(Pointer, VertexLocation, "vertPos"); Gl.BindAttribLocation(Pointer, UvLocation, "uv"); Gl.BindAttribLocation(Pointer, TidLocation, "tid"); Gl.BindAttribLocation(Pointer, ColorLocation, "color"); Gl.LinkProgram(Pointer); // Check linking status. var programCompileStatusReader = new StringBuilder(1024); Gl.GetProgramInfoLog(Pointer, 1024, out int length, programCompileStatusReader); if (length > 0) { var programStatus = programCompileStatusReader.ToString(0, length); if (programStatus != "") { Engine.Log.Warning($"Log for linking shader {Pointer} is {programStatus}", MessageSource.GL); } } Gl.GetProgram(Pointer, ProgramProperty.LinkStatus, out int state); if (state == 0) { Engine.Log.Warning($"Couldn't link shader program {Pointer}.", MessageSource.GL); } else { Valid = true; } if (!Valid) { return; } // Set default uniforms - this requires binding, so save the currently bound. uint previouslyBound = Bound; EnsureBound(Pointer); SetUniformIntArray("textures", Enumerable.Range(0, Engine.Renderer.TextureArrayLimit).ToArray()); SetUniformFloat("iTime", 0); EnsureBound(previouslyBound); }
internal GlShaderProgram(uint vertPointer, uint fragPointer) { try { _uniformLocationsMap = new Dictionary <string, uint>(); // Create and link the program with the vert and fragment shaders. Id = Gl.CreateProgram(); Gl.AttachShader(Id, vertPointer); Gl.AttachShader(Id, fragPointer); Gl.BindAttribLocation(Id, Engine.GraphicsManager.VertexLocation, "vertPos"); Gl.BindAttribLocation(Id, Engine.GraphicsManager.UvLocation, "uv"); Gl.BindAttribLocation(Id, Engine.GraphicsManager.TidLocation, "tid"); Gl.BindAttribLocation(Id, Engine.GraphicsManager.ColorLocation, "color"); Engine.GraphicsManager.CheckError("setting locations"); Gl.LinkProgram(Id); Gl.GetProgram(Id, ProgramProperty.LinkStatus, out int state); if (state == 0) { Engine.Log.Warning($"Couldn't link shader - {vertPointer} / {fragPointer}.", MessageSource.GL); Broken = true; } // Check linking status. StringBuilder compileStatusReader = new StringBuilder(1024); Gl.GetProgramInfoLog(Id, 1024, out int length, compileStatusReader); string programStatus = compileStatusReader.ToString(0, length); if (programStatus != "") { Engine.Log.Warning($"Log for linking shader {Id} is {programStatus}", MessageSource.GL); } Gl.DetachShader(Id, vertPointer); Gl.DetachShader(Id, fragPointer); Gl.ValidateProgram(Id); Engine.GraphicsManager.CheckError("making program and shaders"); } catch (Exception ex) { ErrorHandler.SubmitError(ex); } }
protected void bindAttribute(uint attribute, string variableName) { Gl.BindAttribLocation(programID, attribute, variableName); }
public void Initialize(uint[] indices, string shader) { VertexArray = Gl.GenVertexArray(); Gl.BindVertexArray(VertexArray); // Allocate a vertex buffer that is big enough to hold 'MaxVerticies' number of vertices. // The draw hint 'DynamicDraw' indicades, that the data may be changed every frame. VertexBuffer = Gl.GenBuffer(); Gl.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffer); Gl.BufferData(BufferTarget.ArrayBuffer, (uint)(Renderer.MaxVerticies * Marshal.SizeOf <Vertex>()), IntPtr.Zero, BufferUsage.DynamicDraw); Gl.EnableVertexAttribArray(0); // The vertex position is a 4-component vector that is not normalized. Gl.VertexAttribPointer(0, 4, VertexAttribType.Float, false, Marshal.SizeOf <Vertex>(), Marshal.OffsetOf <Vertex>("Position")); Gl.EnableVertexAttribArray(1); // The vertex color is a 4-component vector that is normalized. Gl.VertexAttribPointer(1, 4, VertexAttribType.Float, true, Marshal.SizeOf <Vertex>(), Marshal.OffsetOf <Vertex>("Color")); Gl.EnableVertexAttribArray(2); // The vertex texture coordinates is a 2-component vector that is not normalized. Gl.VertexAttribPointer(2, 2, VertexAttribType.Float, false, Marshal.SizeOf <Vertex>(), Marshal.OffsetOf <Vertex>("TexCoord")); Gl.EnableVertexAttribArray(3); // The vertex texture index is a 1-component vector that is not normalized. Gl.VertexAttribPointer(3, 1, VertexAttribType.Float, false, Marshal.SizeOf <Vertex>(), Marshal.OffsetOf <Vertex>("TexIndex")); // Allocate an index buffer that is big enough to hold 'MaxIndices' number of indices. // The draw hint 'StaticDraw' indicades, that the data will not be changed. IndexBuffer = Gl.GenBuffer(); Gl.BindBuffer(BufferTarget.ElementArrayBuffer, IndexBuffer); Gl.BufferData(BufferTarget.ElementArrayBuffer, (uint)(indices.Length * sizeof(uint)), indices, BufferUsage.StaticDraw); // Load the shader source. string shaderText = File.ReadAllText(shader); // The shader source is split into a vertex shader and a fragment shader via preprocessor statements. string vertexShaderText = "#version " + ShaderVersion + "\n#define VS_BUILD\n" + shaderText; string fragmentShaderText = "#version " + ShaderVersion + "\n#define FS_BUILD\n" + shaderText; // Create a new shader program and compile the vertex shader and fragment shader. ShaderProgram = Gl.CreateProgram(); VertexShader = CompileShader(ShaderType.VertexShader, vertexShaderText); FragmentShader = CompileShader(ShaderType.FragmentShader, fragmentShaderText); // Attach the shaders to the program and link. Gl.AttachShader(ShaderProgram, VertexShader); Gl.AttachShader(ShaderProgram, FragmentShader); Gl.LinkProgram(ShaderProgram); Gl.ValidateProgram(ShaderProgram); Gl.UseProgram(ShaderProgram); // Find and bind the attribute locations. Gl.GetProgram(ShaderProgram, ProgramProperty.ActiveAttributes, out int numActiveAttribs); Gl.GetProgram(ShaderProgram, ProgramProperty.ActiveAttributeMaxLength, out int maxAttribNameLength); StringBuilder nameData = new StringBuilder(maxAttribNameLength); for (uint attrib = 0; attrib < numActiveAttribs; attrib++) { Gl.GetActiveAttrib(ShaderProgram, attrib, nameData.Capacity, out _, out _, out _, nameData); Gl.BindAttribLocation(ShaderProgram, attrib, nameData.ToString()); } // Query the uniform locations. Gl.GetProgram(ShaderProgram, ProgramProperty.ActiveUniforms, out int numActiveUniforms); Gl.GetProgram(ShaderProgram, ProgramProperty.ActiveUniformMaxLength, out int maxUniformNameLength); Uniforms = new Dictionary <string, int>(); nameData = new StringBuilder(maxUniformNameLength); for (uint uniform = 0, samplerCount = 0; uniform < numActiveUniforms; uniform++) { Gl.GetActiveUniform(ShaderProgram, uniform, nameData.Capacity, out _, out int arraySize, out int type, nameData); string uniformName = nameData.ToString(); if (arraySize > 1) { uniformName = uniformName.Substring(0, uniformName.IndexOf("[")); } for (int i = 0; i < arraySize; i++) { string name = arraySize == 1 ? uniformName : uniformName + "[" + i + "]"; int location = Gl.GetUniformLocation(ShaderProgram, name); Uniforms[name] = location; // Additionally bind the sampler2D uniforms to the OpenGL texture slots in order of appearence. if (type == Gl.SAMPLER_2D) { Gl.Uniform1(location, (int)(samplerCount++)); } } } }