Axelill's picture

Shaders with openTk.

Hello everyone,

I'dl like to create a shader using opentk but I have a small problem. My shader is in a c# Strinag and opentk accept only a string[] (like the c++ version but it easy to play with pointer in c++)

string _shader = "void main() { gl_Position = ftransform();}"
GL.ShaderSource(m_shader_handle, 1, _shader, null);

this piece of code does not work. Do I need to split my string per lines? or there is something more efficient?

Axel.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
djk's picture

try

string[] _shader = new string[] { {"void main() { gl_Position = ftransform();}"} };

this will give you a array of string with one element.

djk

the Fiddler.'s picture

The latest version (0.3.13) contains a new GL.ShaderSource overload that takes a single string:

string _shader = "void main() { gl_Position = ftransform();}"
GL.ShaderSource(m_shader_handle, _shader);

It automatically takes care of unnecessary details, and there is no need for the string to be null terminated.

This overload also works well with shaders stored in files:

using (StreamReader sr = new StreamReader("vertex_shader.glsl"))
{
    GL.ShaderSource(m_shader_handle, sr.ReadToEnd());
}
Axelill's picture

Yep, true and it works perfectly.

Thanks. ;)

tak's picture

Hello to all. I'm newbie in GL and OpenTk. What means m_shader_handle and where should I get this value? Little example if anybody can.. Please!

the Fiddler's picture

Welcome.

To use a shader, you must first create it with GL.CreateShader, i.e:

int vertex_shader = GL.CreateShader(ShaderType.VertexShader);
int fragment_shader = GL.CreateShader(ShaderType.FragmentShader);

Then, you have to:

  1. to upload the shader code (GL.ShaderSource)
  2. compile it (GL.CompileShader)
  3. create a program (GL.CreateProgram)
  4. attach the shaders (GL.AttachShader)
  5. link the program (GL.LinkProgram)
  6. and, finally, use the newly created program (GL.UseProgram)

It's simpler than it sounds :)

If you wish to see this in action, check the source code of the first GLSL example (currently located at Source/Examples/Tutorial/T10_GLSL_Cube.cs).

tak's picture

I tried to Create Shader but have runtime error:
"Unable to find an entry point named 'glCreateShader' in DLL 'opengl32.dll'"
I use videocard
nVIDIA GeForce4 Ti 4200 with AGP8X
I tried to check GL.SupportsExtension("VERSION_2_0") (same in example); And it returns false!
(In examples too, of course). Maybe my card does't support this extensions. But why I can't create shader..?
What's wrong?

Mincus's picture

Geforce 4s don't support Shader v2, you'll need a newer graphics card.

Take a look at: http://en.wikipedia.org/wiki/Pixel_shader
You'll note you need at least a Geforce FX or Radeon X700 for shader 2.0.

the Fiddler's picture

Your video card is too old and does not support GLSL shaders. GLSL is only supported by GeForce FX or Radeon 9500 and newer cards.

Your card does have programmable hardware which is exposed in the form of low-level ARB vertex and fragment programs. The syntax is closer to assembly (while GLSL is closer to C), but the language is quite simple.

Your other option is to download and build Mesa3d, which is a software implementation of OpenGL with GLSL support (this is what I use when developing OpenTK).

Edit: beaten. One note: R300 cards (Radeon 9500-9800) support GLSL just fine, no need for R400 (Radeon x600-x850)

Mincus's picture

Ah, yes, my mistake.
I tend to stick to nvidia cards so didn't really follow the Radeon line closely and put the card that supported 2.0b down instead.

tak's picture

Thanks a lot!
One more question. I tried to write some affine convertion with GLSL. For shader creation I used function CreateShader so far and it's call from example Source/Examples/Tutorial/T10_GLSL_Cube.cs

using (StreamReader vs = new StreamReader("Shaders/preobr.vert"))
            using (StreamReader fs = new StreamReader("Shaders/preobr.frag"))
                CreateShaders(vs.ReadToEnd(), fs.ReadToEnd(),
                    out vertex_shader_object, out fragment_shader_object,
                    out shader_program);

which I placed at the and of Form_Load event code (I'm using WinForms)
Me shaders:
fragment shader preobr.frag

uniform sampler2D texture;
varying float intensity;
varying vec2 texCoord;
void main()
{
    vec4 color = texture2D(texture, texCoord);
    gl_FragColor = gl_FrontLightProduct[0].diffuse* color + intensity *    gl_LightSource[0].specular;
}

vertex:

void main()
{   
    texCoord = vec3(gl_MultiTexCoord0);
    mat4 MatrixPreobr = mat4(0, 0, 0, 0,
					      0, 0, 0, 0,
					      0, 0, 0, 0,
					      0, 0, 0, 0);
    gl_Position = MatrixPreobr * ftransform();
}

Where MatrixPreobr may be some conversion. But it don't give effect. (Me Surface leave in the same position with various matix). What's wrong?