I have been using OpenTK with mono on Fedora and have not seen that error. YourYour example uses some C# features I'm not familiar with, and I don't know what is in your draw sphere, so I have created a simple example that works on Linux below. Although only a triangle is drawn, it uses the shaders, and I enabled and disabled the shader programs as you have in your example above.
Although only a triangle is drawn, it uses the shaders, and I assumeenabled and disabled the shader programs as you already have a GLControl you can pass into this functionin your example above. My program sets up a 512 x 512 GLControl like this before calling the test function:
int w = GlControl1.Width;
int h = GlControl1.Height;
GL.MatrixMode (MatrixMode.Projection);
GL.LoadIdentity ();
GL.Ortho (0, w, 0, h, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
GL.Viewport (0, 0, w, h); // Use all of the glControl painting area
using System;
using System.Text;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System.Windows.Forms;
namespace OpenTkTestNamespace
{
public class StackExchangeTestsClass
{
public StackExchangeTestsClass()
{
}
static string VertexShader =
"float;" +
"attribute vec4 vPosition;" +
"void main()" +
"{" +
"gl_Position = vPosition;" +
"}";
static string FragmentShader =
"float;" +
"uniform vec4 vColor;" +
"void main()" +
"{" +
"gl_FragColor = vColor * 1.0 / 256.0 + 1.0 / 256.0 * vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1);" + // (1-clamp(gl_FragCoord.z - 0.05, 0, 1));" +
"}";
static int programId;
static OpenTK.GLControl GlControl;
static bool setup_complete = false;
public static StringBuilder Test(OpenTK.GLControl GlControl_in)
{
StringBuilder result = new StringBuilder();
if (setup_complete == false)
{
GlControl = GlControl_in;
Compile();
result.AppendLine("Compile Complete");
setup_complete = true;
}
Apply();
result.AppendLine("Apply Complete");
DrawSomething();
Unapply();
result.AppendLine("UnApply Complete");
Apply();
result.AppendLine("Apply Complete");
DrawSomething();
Unapply();
result.AppendLine("UnApply Complete");
return result;
}
public static int loadShader(ShaderType type, String shaderCode)
{
int shader_ok;
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GL.CreateShader(type);
// add the source code to the shader and compile it
GL.ShaderSource(shader, shaderCode);
GL.CompileShader(shader);
GL.GetShader(shader, ShaderParameter.CompileStatus, out shader_ok);
if (shader_ok == 0) {
MessageBox.Show("Failed to compile " + shaderCode);
//fprintf(stderr, "Failed to compile %s:\n", filename);
//show_info_log(shader, glGetShaderiv, glGetShaderInfoLog);
//glDeleteShader(shader);
return 0;
}
return shader;
}
public static void Compile()
{
int VshaderId = loadShader(ShaderType.VertexShader, VertexShader);
int FshaderId = loadShader(ShaderType.FragmentShader, FragmentShader);
programId = GL.CreateProgram();
GL.AttachShader(programId, VshaderId);
GL.AttachShader(programId, FshaderId);
GL.LinkProgram(programId);
int program_ok;
GL.GetProgram(programId, ProgramParameter.LinkStatus, out program_ok);
if (program_ok == 0)
{
MessageBox.Show("Failed to link " + program_ok.ToString());
}
}
public static void Apply()
{
if (programId == -1)
throw new InvalidOperationException("Compile() has to be called before Apply()");
GL.UseProgram(programId);
}
public static void Unapply()
{
GL.UseProgram(0);
}
static int mColorHandle;
// Set color with red, green, blue and alpha (opacity) values
static OpenTK.Graphics.Color4 color = new OpenTK.Graphics.Color4(0.5f, 0.5f, 0.5f, 1.0f);
private static void DrawTriangle()
{
//GL.MatrixMode(MatrixMode.Modelview);
//GL.LoadIdentity();
GL.Color3(Color.Yellow);
GL.Begin(BeginMode.Triangles);
GL.Vertex3(0.0, 1, -1);
GL.Vertex3(-1, -1, 0);
GL.Vertex3(1, -1, 1);
GL.End();
}
public static void DrawSomething()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// get handle to fragment shader's vColor member
mColorHandle = GL.GetUniformLocation(programId, "vColor");
// Set color for drawing the triangle
GL.Uniform4(mColorHandle, color);
DrawTriangle();
GlControl.SwapBuffers();
}
}
}
Hope that helpsI assume you already have a GLControl you can pass into this function. My program sets up a 512 x 512 GLControl like this before calling the test function:
int w = GlControl1.Width;
int h = GlControl1.Height;
GL.MatrixMode (MatrixMode.Projection);
GL.LoadIdentity ();
GL.Ortho (0, w, 0, h, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
GL.Viewport (0, 0, w, h); // Use all of the glControl painting area
using System;
using System.Text;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System.Windows.Forms;
namespace OpenTkTestNamespace
{
public class StackExchangeTestsClass
{
public StackExchangeTestsClass()
{
}
static string VertexShader =
"float;" +
"attribute vec4 vPosition;" +
"void main()" +
"{" +
"gl_Position = vPosition;" +
"}";
static string FragmentShader =
"float;" +
"uniform vec4 vColor;" +
"void main()" +
"{" +
"gl_FragColor = vColor * 1.0 / 256.0 + 1.0 / 256.0 * vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1);" + // (1-clamp(gl_FragCoord.z - 0.05, 0, 1));" +
"}";
static int programId;
static OpenTK.GLControl GlControl;
static bool setup_complete = false;
public static StringBuilder Test(OpenTK.GLControl GlControl_in)
{
StringBuilder result = new StringBuilder();
if (setup_complete == false)
{
GlControl = GlControl_in;
Compile();
result.AppendLine("Compile Complete");
setup_complete = true;
}
Apply();
result.AppendLine("Apply Complete");
DrawSomething();
Unapply();
result.AppendLine("UnApply Complete");
Apply();
result.AppendLine("Apply Complete");
DrawSomething();
Unapply();
result.AppendLine("UnApply Complete");
return result;
}
public static int loadShader(ShaderType type, String shaderCode)
{
int shader_ok;
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GL.CreateShader(type);
// add the source code to the shader and compile it
GL.ShaderSource(shader, shaderCode);
GL.CompileShader(shader);
GL.GetShader(shader, ShaderParameter.CompileStatus, out shader_ok);
if (shader_ok == 0) {
MessageBox.Show("Failed to compile " + shaderCode);
//fprintf(stderr, "Failed to compile %s:\n", filename);
//show_info_log(shader, glGetShaderiv, glGetShaderInfoLog);
//glDeleteShader(shader);
return 0;
}
return shader;
}
public static void Compile()
{
int VshaderId = loadShader(ShaderType.VertexShader, VertexShader);
int FshaderId = loadShader(ShaderType.FragmentShader, FragmentShader);
programId = GL.CreateProgram();
GL.AttachShader(programId, VshaderId);
GL.AttachShader(programId, FshaderId);
GL.LinkProgram(programId);
int program_ok;
GL.GetProgram(programId, ProgramParameter.LinkStatus, out program_ok);
if (program_ok == 0)
{
MessageBox.Show("Failed to link " + program_ok.ToString());
}
}
public static void Apply()
{
if (programId == -1)
throw new InvalidOperationException("Compile() has to be called before Apply()");
GL.UseProgram(programId);
}
public static void Unapply()
{
GL.UseProgram(0);
}
static int mColorHandle;
// Set color with red, green, blue and alpha (opacity) values
static OpenTK.Graphics.Color4 color = new OpenTK.Graphics.Color4(0.5f, 0.5f, 0.5f, 1.0f);
private static void DrawTriangle()
{
//GL.MatrixMode(MatrixMode.Modelview);
//GL.LoadIdentity();
GL.Color3(Color.Yellow);
GL.Begin(BeginMode.Triangles);
GL.Vertex3(0.0, 1, -1);
GL.Vertex3(-1, -1, 0);
GL.Vertex3(1, -1, 1);
GL.End();
}
public static void DrawSomething()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// get handle to fragment shader's vColor member
mColorHandle = GL.GetUniformLocation(programId, "vColor");
// Set color for drawing the triangle
GL.Uniform4(mColorHandle, color);
DrawTriangle();
GlControl.SwapBuffers();
}
}
}
JamesHope that helps.