
Porting C++ tutorial, triangle not showing up
Posted Saturday, 16 June, 2012 - 21:14 by jodev inHi everyone,
I'm taking my first steps in OpenGl using Jason L. McKesson's tutorial (http://www.arcsynthesis.org/gltut/index.html). I'll have to admit that it is all pretty daunting to digest, but in general lines I understand the roles of the shaders and programs that the tutorial uses. I find the actual code conversion from C++ top OpenTK not difficult at all so far. However, I seem to have hit a snag in that my code works except for showing the triangle. The file that I am converting to C#/OpenTK is this one: https://bitbucket.org/alfonse/gltut/src/3ee6f3dd04a7/Tut%2001%20Hello%20... The code that I have converted it to is as follows:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; namespace GLTest { class GLWindow : GameWindow { const string strVertexShader = "#version 330\n" + "layout(location = 0) in vec4 position;\n" + "void main()\n" + "{\n" + " gl_Position = position;\n" + "}\n"; const string strFragmentShader = "#version 330\n" + "out vec4 outputColor;\n" + "void main()\n" + "{\n" + " outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n" + "}\n"; private int vao; private int positionBufferObject; private int theProgram; private float[] vertexPositions = { 0.75f, 0.75f, 0.0f, 1.0f, 0.75f, -0.75f, 0.0f, 1.0f, -0.75f, -0.75f, 0.0f, 1.0f, }; static void Main(string[] args) { using (GLWindow wnd = new GLWindow(800, 600, GraphicsMode.Default, "Learning Modern 3D Graphics Programming")) { wnd.init(); wnd.Run(); } } public GLWindow(int width, int height, GraphicsMode mode, string title) : base(width, height, mode, title) { } protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { base.OnClosing(e); System.Diagnostics.Debug.WriteLine("Exiting program and releasing OpenGL resources..."); GL.DeleteProgram(this.theProgram); } protected void init() { System.Diagnostics.Debug.WriteLine("Initializing OpenGL..."); initializeProgram(); initializeVertexBuffer(); GL.GenVertexArrays(1, out this.vao); GL.BindVertexArray(this.vao); System.Diagnostics.Debug.WriteLine("Ready, entering the main loop..."); } protected override void OnRenderFrame(FrameEventArgs e) { GL.ClearColor(Color.CornflowerBlue); GL.Clear(ClearBufferMask.ColorBufferBit); GL.UseProgram(this.theProgram); GL.BindBuffer(BufferTarget.ArrayBuffer, this.positionBufferObject); GL.VertexAttribPointer(0, 4, VertexAttribPointerType.Float, false, 0, 0); GL.DrawArrays(BeginMode.Triangles, 0, 3); GL.DisableVertexAttribArray(0); GL.UseProgram(0); this.SwapBuffers(); } protected override void OnResize(EventArgs e) { base.OnResize(e); GL.Viewport(0, 0, this.Width, this.Height); } protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); } protected override void OnKeyPress(KeyPressEventArgs e) { base.OnKeyPress(e); } protected void initializeVertexBuffer() { GL.GenBuffers(1, out this.positionBufferObject); GL.BindBuffer(BufferTarget.ArrayBuffer, this.positionBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexPositions.Length * sizeof(float)), vertexPositions, BufferUsageHint.StaticDraw); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); } protected void initializeProgram() { List<uint> shaderList = new List<uint>(); shaderList.Add(this.CreateShader(ShaderType.VertexShader, strVertexShader)); shaderList.Add(this.CreateShader(ShaderType.FragmentShader, strFragmentShader)); this.theProgram = this.CreateProgram(shaderList); foreach (uint shader in shaderList) GL.DeleteShader(shader); } protected uint CreateShader(ShaderType eShaderType, string strShaderFile) { int shader = GL.CreateShader(eShaderType); string strFileData = strShaderFile; GL.ShaderSource(shader, strFileData); GL.CompileShader(shader); int status; GL.GetShader(shader, ShaderParameter.CompileStatus, out status); if (status == 0) { int infoLogLength; GL.GetShader(shader, ShaderParameter.InfoLogLength, out infoLogLength); string strInfolog; GL.GetShaderInfoLog(shader, out strInfolog); string strShaderType = null; switch (eShaderType) { case ShaderType.VertexShader: strShaderType = "vertex"; break; case ShaderType.GeometryShader: strShaderType = "geometry"; break; case ShaderType.FragmentShader: strShaderType = "fragment"; break; } System.Diagnostics.Debug.WriteLine("Compile failure in {0} shader:\n{1}\n", strShaderType, strInfolog); } return (uint)shader; } protected int CreateProgram(List<uint> shaderList) { int program = GL.CreateProgram(); for (int iLoop = 0; iLoop < shaderList.Count; iLoop++) GL.AttachShader((uint)program, shaderList[iLoop]); GL.LinkProgram(program); int status; GL.GetProgram(program, ProgramParameter.LinkStatus, out status); if (status == 0) { string strInfoLog = GL.GetProgramInfoLog(program); System.Diagnostics.Debug.WriteLine("Linker failure: {0}", strInfoLog); } for (int iLoop = 0; iLoop < shaderList.Count; iLoop++) { GL.DetachShader((uint)program, shaderList[iLoop]); } return program; } } }
My apologies for the long piece of code, but I honestly have no clue where I may have messed up. The CreateShader and CreateProgram methods are not reporting any issues and the OnRenderFrame method draws a beautiful cornflowerblue background. But no triangle... I have determined that the 'theProgram' field in the OnRenderFrame method is set (with a value of 3). I have also tried switching around the vertex position, figuring it may have been wound the wrong way.
Any clues as to what I may have missed? Thanks!


Comments
Re: Porting C++ tutorial, triangle not showing up
Okay, so this is a new day and after some extra strong morning coffee I went through the code again line by line and found the problem. I forgot to add GL.EnableVertexAttribArray(0); to the OnRenderFrame method. With that done it all works as expected.