
My first try, render to 2d texture to quad and GLSL
Posted Saturday, 13 October, 2012 - 19:04 by sanchiski inHello everyone, this is my first ever experiment with OpenTK. I am trying to render a 2d bitmap into a quad and apply some effect with GLSL. I think I am quite near, but so far I only get a black screen, can anyone spot what I am doing wrong? thanks in advance.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using OpenTK; using OpenTK.Input; using System.Drawing; using System.Drawing.Imaging; using GL = OpenTK.Graphics.OpenGL.GL; using OpenGL = OpenTK.Graphics.OpenGL; namespace ThumbMaker { public class Demo : GameWindow { private int textureId; int vertex_shader_object, fragment_shader_object, shader_program; int vertex_buffer_object, color_buffer_object, element_buffer_object; public Demo() : base(800, 600, OpenTK.Graphics.GraphicsMode.Default, "Quad Test") { } protected override void OnLoad(EventArgs e) { OnResize(null); GL.ClearColor(Color.Black); String vs = "attribute vec4 a_position;" + "attribute vec2 a_texcoord;" + "varying vec2 v_texcoord;" + "void main()" + "{" + " v_texcoord = a_texcoord.st;" + " gl_Position = a_position;" + "}"; String fs = "varying vec2 v_texcoord; " + "uniform sampler2D u_texture_y; " + "void main()" + "{" + " vec3 color = texture2D(u_texture_y, v_texcoord).rgb;" + " gl_FragColor.rgb = color;"+ "}"; CreateShaders(vs, fs, out vertex_shader_object, out fragment_shader_object, out shader_program); InitTexturing(); textureId = CreateTexture(); GL.ActiveTexture(OpenTK.Graphics.OpenGL.TextureUnit.Texture0); GL.BindTexture(OpenTK.Graphics.OpenGL.TextureTarget.Texture2D, textureId); int textureHandle = GL.GetUniformLocation(shader_program, "u_texture_y"); GL.Uniform1(textureHandle, 0); } private static void InitTexturing() { GL.Disable(OpenGL.EnableCap.CullFace); GL.Enable(OpenGL.EnableCap.Texture2D); GL.Enable(OpenGL.EnableCap.Blend); GL.BlendFunc(OpenGL.BlendingFactorSrc.SrcAlpha, OpenGL.BlendingFactorDest.OneMinusSrcAlpha); GL.PixelStore(OpenGL.PixelStoreParameter.UnpackAlignment, 1); } private static int CreateTexture() { // Load the bitmap from the resources Bitmap bitmap = global::TestApp.Properties.Resources.TestBitmap; BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int tex = GL.GenTexture(); GL.BindTexture(OpenGL.TextureTarget.Texture2D, tex); GL.BindTexture(OpenGL.TextureTarget.Texture2D, tex); GL.TexImage2D(OpenGL.TextureTarget.Texture2D, 0, OpenGL.PixelInternalFormat.Rgba, data.Width, data.Height, 0, OpenGL.PixelFormat.Bgra, OpenGL.PixelType.UnsignedByte, data.Scan0); bitmap.UnlockBits(data); GL.TexParameter(OpenGL.TextureTarget.Texture2D, OpenGL.TextureParameterName.TextureMinFilter, (int)OpenGL.TextureMinFilter.Linear); GL.TexParameter(OpenGL.TextureTarget.Texture2D, OpenGL.TextureParameterName.TextureMagFilter, (int)OpenGL.TextureMagFilter.Linear); return tex; } protected override void OnUpdateFrame(FrameEventArgs e) { if (Keyboard[Key.Escape]) Exit(); if (Keyboard[Key.Space]) { OpenGL.ErrorCode err = GL.GetError(); Console.WriteLine(err + " " + OpenTK.Graphics.Glu.ErrorString((OpenTK.Graphics.GluErrorCode)err)); Console.WriteLine("GL error code: {0}", err); } } protected override void OnResize(EventArgs e) { GL.Viewport(new System.Drawing.Size(Width, Height)); GL.MatrixMode(OpenGL.MatrixMode.Projection); GL.LoadIdentity(); GL.Ortho(0, Width, 0, Height, -1, 1); GL.MatrixMode(OpenGL.MatrixMode.Modelview); } protected override void OnRenderFrame(FrameEventArgs e) { GL.Clear(OpenGL.ClearBufferMask.ColorBufferBit); GL.MatrixMode(OpenGL.MatrixMode.Modelview); GL.LoadIdentity(); GL.DrawArrays(OpenGL.BeginMode.TriangleStrip, 0, 4); SwapBuffers(); } void CreateShaders(string vs, string fs, out int vertexObject, out int fragmentObject, out int program) { int status_code; string info; vertexObject = GL.CreateShader(OpenGL.ShaderType.VertexShader); fragmentObject = GL.CreateShader(OpenGL.ShaderType.FragmentShader); // Compile vertex shader GL.ShaderSource(vertexObject, vs); GL.CompileShader(vertexObject); GL.GetShaderInfoLog(vertexObject, out info); GL.GetShader(vertexObject, OpenGL.ShaderParameter.CompileStatus, out status_code); if (status_code != 1) throw new ApplicationException(info); // Compile vertex shader GL.ShaderSource(fragmentObject, fs); GL.CompileShader(fragmentObject); GL.GetShaderInfoLog(fragmentObject, out info); GL.GetShader(fragmentObject, OpenGL.ShaderParameter.CompileStatus, out status_code); if (status_code != 1) throw new ApplicationException(info); program = GL.CreateProgram(); GL.AttachShader(program, fragmentObject); GL.AttachShader(program, vertexObject); GL.LinkProgram(program); float[] vertexVertices = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f }; float[] textureVertices = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; int handleAPosition = GL.GetAttribLocation(program, "a_position"); int handleATexcoord = GL.GetAttribLocation(program, "a_texcoord"); GL.EnableVertexAttribArray(handleAPosition); GL.EnableVertexAttribArray(handleATexcoord); GL.VertexAttribPointer(handleAPosition, 2, OpenGL.VertexAttribPointerType.Float, false, 0, vertexVertices); GL.VertexAttribPointer(handleATexcoord, 2, OpenGL.VertexAttribPointerType.Float, false, 0, textureVertices); GL.UseProgram(program); } } static class Program { static void Main(string[] args) { using (Demo demo = new Demo()) { demo.Run(1.0, 0.0); } } } }


Comments
Re: My first try, render to 2d texture to quad and GLSL
You aren't assigning any value in to the alpha channel of the shader output.
So
GL.BlendFunc(OpenGL.BlendingFactorSrc.SrcAlpha, OpenGL.BlendingFactorDest.OneMinusSrcAlpha);Can't work.
Fix:
Re: My first try, render to 2d texture to quad and GLSL
Some other comments I have on your code :p
- You don't need these:
- I rather write
GL.Enable(EnableCap.Texture2D), shorter to type easier to read.- don't use matrix mode
GL.MatrixMode(OpenGL.MatrixMode.Modelview);this only used for fixed pipeline ( so when you're not using shaders )
- also (could be wrong here) I don't think you need this
OpenTK throws an exception when there is an error.
To get the errors and warnings from the shader you could do something like this
Re: My first try, render to 2d texture to quad and GLSL
WOW WOW WOW, excellent, the entire problem was the rgba issue on the shader, plus thanks for all the annotations about the code, very helpful :)
Re: My first try, render to 2d texture to quad and GLSL
- also (could be wrong here) I don't think you need this
OpenTK throws an exception when there is an error.
That's wrong, OpenTK generally does not throw exceptions for OpenGL errors.
Re: My first try, render to 2d texture to quad and GLSL
I check the opentk source now and I still believe it does but only for debug target.
If you look in GL.cs at the beginnen of each function you can see
using (new ErrorHelper(GraphicsContext.CurrentContext))And in ErrorHelper.cs