public Shader(string name) { var vertexShader = CompileShaderObject(OpenGL.GL_VERTEX_SHADER, name); var fragmentShader = CompileShaderObject(OpenGL.GL_FRAGMENT_SHADER, name); // Assemble program program = OpenGL.glCreateProgram(); OpenGL.CheckGLError(); OpenGL.glBindAttribLocation(program, VertexPosAttributeIndex, "aVertexPosition"); OpenGL.CheckGLError(); OpenGL.glBindAttribLocation(program, TexCoordAttributeIndex, "aVertexTexCoord"); OpenGL.CheckGLError(); OpenGL.glBindAttribLocation(program, TexMetadataAttributeIndex, "aVertexTexMetadata"); OpenGL.CheckGLError(); if (OpenGL.Profile != GLProfile.Legacy) { OpenGL.glBindFragDataLocation(program, 0, "fragColor"); OpenGL.CheckGLError(); } OpenGL.glAttachShader(program, vertexShader); OpenGL.CheckGLError(); OpenGL.glAttachShader(program, fragmentShader); OpenGL.CheckGLError(); OpenGL.glLinkProgram(program); OpenGL.CheckGLError(); int success; OpenGL.glGetProgramiv(program, OpenGL.GL_LINK_STATUS, out success); OpenGL.CheckGLError(); if (success == OpenGL.GL_FALSE) { int len; OpenGL.glGetProgramiv(program, OpenGL.GL_INFO_LOG_LENGTH, out len); var log = new StringBuilder(len); int length; OpenGL.glGetProgramInfoLog(program, len, out length, log); Log.Write("graphics", "GL Info Log:\n{0}", log.ToString()); throw new InvalidProgramException("Link error in shader program '{0}'".F(name)); } OpenGL.glUseProgram(program); OpenGL.CheckGLError(); int numUniforms; OpenGL.glGetProgramiv(program, OpenGL.GL_ACTIVE_UNIFORMS, out numUniforms); OpenGL.CheckGLError(); var nextTexUnit = 0; for (var i = 0; i < numUniforms; i++) { int length, size; int type; var sb = new StringBuilder(128); OpenGL.glGetActiveUniform(program, i, 128, out length, out size, out type, sb); var sampler = sb.ToString(); OpenGL.CheckGLError(); if (type == OpenGL.GL_SAMPLER_2D) { samplers.Add(sampler, nextTexUnit); var loc = OpenGL.glGetUniformLocation(program, sampler); OpenGL.CheckGLError(); OpenGL.glUniform1i(loc, nextTexUnit); OpenGL.CheckGLError(); if (OpenGL.Profile == GLProfile.Legacy) { var sizeLoc = OpenGL.glGetUniformLocation(program, sampler + "Size"); if (sizeLoc >= 0) { legacySizeUniforms.Add(nextTexUnit, sizeLoc); } } nextTexUnit++; } } }