Robbepop's picture

How to render a processed image?

Hiho,

I am very new to OpenTK and to GPU programming in general and have already read through many OpenTK/GL tutorials, however I am currently stuck at getting my code working.

Basically, I am trying to read out images (Bitmaps) do some image processing with them and display them on my screen - so no 3D but only 2D OpenGL features are needed.
At the moment not a single image is displayed and I am not even aware what steps are working at all but what I can say is that my whole code runs through all stages without exceptions etc. ...

Here is what I have wrote, copied, brainstormed so far:

My initialization codes.

        int vertexShaderObject, fragmentShaderObject, shaderProgram;
        int vertexBufferObject, colorBufferObject, elementBufferObject;
        int currentTextureId;
 
        private void SetupViewport()
        {
            int w = glControl1.Width;
            int h = glControl1.Height;
            GL.ClearColor(Color.Black);
            GL.MatrixMode(MatrixMode.Modelview);
            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 paintining area
        }
 
        private void InitTexturing()
        {
            GL.Disable(EnableCap.CullFace);
            GL.Enable(EnableCap.Texture2D);
            GL.Enable(EnableCap.Blend);
            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
            GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
        }
 
        private void OnLoadGL(object sender, EventArgs e)
        {
            this.GLContextLoaded = true;
            this.SetupViewport();
            this.InitTexturing();
        }

A method to create my shaders which I read out of the embedded files.

        private void CreateShaders(byte[] vsFile, byte[] fsFile, out int vertexObject, out int fragmentObject, out int program)
        {
            int status_code;
            string info;
            // Read shader files
            string vs = System.Text.Encoding.UTF8.GetString(
                DaltonEyes.Properties.Resources.testVertexShader);
            string fs = System.Text.Encoding.UTF8.GetString(
                DaltonEyes.Properties.Resources.testFragmentShader);
            // Setup shader objects
            vertexObject = GL.CreateShader(ShaderType.VertexShader);
            fragmentObject = GL.CreateShader(ShaderType.FragmentShader);
            // Compile vertex shader
            GL.ShaderSource(vertexObject, vs);
            GL.CompileShader(vertexObject);
            GL.GetShaderInfoLog(vertexObject, out info);
            GL.GetShader(vertexObject, 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, 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, VertexAttribPointerType.Float, false, 0, vertexVertices);
            GL.VertexAttribPointer(handleATexcoord, 2, VertexAttribPointerType.Float, false, 0, textureVertices);
            GL.UseProgram(program);
        }

Vertex Shader: Should just move the texture through my GPU pipeline so that my fragment shaders can work on the pixels later on.

attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
 
void main()
{
	v_texcoord = a_texcoord.st;
	gl_Position = a_position;
}

Fragment Shader: Should do nothing right now for testing purpose.

varying vec2 v_texcoord;
uniform sampler2D u_texture_y;
 
void main()
{
	vec4 color;
	color.rgba = texture2D(u_texture_y, v_texcoord).rgba;                     
	gl_FragColor = color;
}

My method to store a texture in the GPU with the data of a given bitmap.

        public int LoadTexture(Bitmap bitmap)
        {
            int tex;
            GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
 
            GL.GenTextures(1, out tex);
            GL.BindTexture(TextureTarget.Texture2D, tex);
 
            BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
                OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
            bitmap.UnlockBits(data);
 
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
            return tex;
        }

The method which actually should draw the current bitmap (which stays the same due to testing purpose).
However, nothing is drawn. :-( I only see the black clear color.

        public void DrawImage(int image)
        {
            int w = glControl1.Width;
            int h = glControl1.Height;
 
            GL.MatrixMode(MatrixMode.Projection);
            GL.PushMatrix();
            GL.LoadIdentity();
 
            GL.MatrixMode(MatrixMode.Modelview);
            GL.PushMatrix();
            GL.LoadIdentity();
 
            GL.Disable(EnableCap.Lighting);
 
            GL.Enable(EnableCap.Texture2D);
 
            GL.BindTexture(TextureTarget.Texture2D, image);
            GL.Color3(Color.Yellow);
 
            GL.Begin(BeginMode.Quads);
 
            GL.TexCoord2(0, 0); GL.Vertex3(0, 0, 0);
            GL.TexCoord2(0, h); GL.Vertex3(w, 0, 0);
            GL.TexCoord2(w, 0); GL.Vertex3(w, h, 0);
            GL.TexCoord2(w, h); GL.Vertex3(0, h, 0);
 
            GL.End();
 
            GL.Disable(EnableCap.Texture2D);
            GL.PopMatrix();
 
            GL.MatrixMode(MatrixMode.Projection);
            GL.PopMatrix();
 
            GL.MatrixMode(MatrixMode.Modelview);
        }
 
        private void Render()
        {
            if (!this.GLContextLoaded)
            {
                return;
            }
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
            this.DrawImage(this.currentTextureId);
 
            glControl1.SwapBuffers();
        }
 
        private Bitmap currentBitmap = null;
        private void OnPaintGL(object sender, PaintEventArgs e)
        {
            currentBitmap = DaltonEyes.Properties.Resources.testImage;
            if (currentBitmap != null)
            {
                this.currentTextureId = this.LoadTexture(currentBitmap);
            }
            this.Render();
        }

That's all the code related to OpenTK. =)
Can you tell me what I have done wrong or where I am missing wisdom to get why it is not working?

Robbepop


Comments

Comment viewing options

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

You are doing this when instead you should setup a projection matrix:

GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();

This is what you should do:

GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho (-1f, 1f, -1f, 1f, 10f, -10f); // left, right, bottom, top, near, far

If you want it in screen pixels you can use this trick:

int viewWidth;
int viewHeight;
 
// assign viewWidth and viewHeight with the correct values
 
GL.Ortho (0, viewWidth, viewHeight, 0, 10f, -10f);

This works really well in C with pure OpenGL but I haven't tried it in OpenTK. Should work the same though.
Happy coding and good luck :)

------------------------------------------------
The best method for accelerating a computer is the one that boosts it by 9.8 m/s^2.