
Lighting in GLControl
Posted Friday, 28 March, 2008 - 17:23 by Pootle inAt the moment I am using Tao and the SimpleOpenGlControl for my 3D application, but as I need it to work both in Linux and Windows environments I am thinking about converting to OpenTK. I have set up a simple test project, which just renders a 3D cube. Using OpenTK and the GLControl, the cube isn't lit properly (all faces have the same colouring) when I draw it using quads. However when I draw a cube using glutSolidCube, the lighting is fine. Both ways work perfectly when I use Tao and the SimpleOpenGlControl (I just did a straight conversion to OpenTK, no extra code). I need to render other (non-cubeish) objects using quads in my proper 3D application, so can't use glutSolidCube there.
Does anybody know what I am doing wrong? Here's my code (drawing is done in display(), change drawQuads to draw using quads or glut):
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Tao.FreeGlut; using OpenTK.OpenGL; //using Tao.OpenGl; namespace LightingForm { public partial class Form1 : Form { private bool loaded = false; public Form1() { InitializeComponent(); } // initialisation private void init() { // initialise Glut Glut.glutInit(); float[] mat_specular = { 1.0f, 1.0f, 1.0f, 1.0f }; float[] mat_shininess = { 50.0f }; float[] light_position = { 1.0f, 1.0f, 1.0f, 0.0f }; float[] light_ambient = { 0.5f, 0.5f, 0.5f, 1.0f }; GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); GL.ShadeModel(OpenTK.OpenGL.Enums.ShadingModel.Smooth); GL.Materialv(OpenTK.OpenGL.Enums.MaterialFace.Front, OpenTK.OpenGL.Enums.MaterialParameter.Specular, mat_specular); GL.Materialv(OpenTK.OpenGL.Enums.MaterialFace.Front, OpenTK.OpenGL.Enums.MaterialParameter.Shininess, mat_shininess); GL.Lightv(OpenTK.OpenGL.Enums.LightName.Light0, OpenTK.OpenGL.Enums.LightParameter.Position, light_position); GL.Lightv(OpenTK.OpenGL.Enums.LightName.Light0, OpenTK.OpenGL.Enums.LightParameter.Ambient, light_ambient); GL.Lightv(OpenTK.OpenGL.Enums.LightName.Light0, OpenTK.OpenGL.Enums.LightParameter.Diffuse, mat_specular); GL.Enable(OpenTK.OpenGL.Enums.EnableCap.Lighting); GL.Enable(OpenTK.OpenGL.Enums.EnableCap.Light0); GL.Enable(OpenTK.OpenGL.Enums.EnableCap.DepthTest); GL.Enable(OpenTK.OpenGL.Enums.EnableCap.ColorMaterial); GL.Enable(OpenTK.OpenGL.Enums.EnableCap.CullFace); } // draws the scene private void display() { GL.Clear(OpenTK.OpenGL.Enums.ClearBufferMask.ColorBufferBit | OpenTK.OpenGL.Enums.ClearBufferMask.DepthBufferBit); GL.PushMatrix(); { GL.Rotate(10, 1, 0, 0); GL.Rotate(10, 0, 1, 0); GL.Color3(0.0, 0.5, 1.0); // *** SET THIS TO FALSE TO CHANGE TO GLUTSOLIDCUBE *** bool drawQuads = true; if (drawQuads) { GL.Begin(OpenTK.OpenGL.Enums.BeginMode.Quads); { // front face GL.Normal3(0, 0, 1); GL.Vertex3(-0.5, -0.5, 0.5); GL.Vertex3(0.5, -0.5, 0.5); GL.Vertex3(0.5, 0.5, 0.5); GL.Vertex3(-0.5, 0.5, 0.5); // back face GL.Normal3(0, 0, -1); GL.Vertex3(-0.5, -0.5, -0.5); GL.Vertex3(-0.5, 0.5, -0.5); GL.Vertex3(0.5, 0.5, -0.5); GL.Vertex3(0.5, -0.5, -0.5); // top face GL.Normal3(0, 1, 0); GL.Vertex3(-0.5, 0.5, -0.5); GL.Vertex3(-0.5, 0.5, 0.5); GL.Vertex3(0.5, 0.5, 0.5); GL.Vertex3(0.5, 0.5, -0.5); // bottom face GL.Normal3(0, -1, 0); GL.Vertex3(-0.5, -0.5, -0.5); GL.Vertex3(0.5, -0.5, -0.5); GL.Vertex3(0.5, -0.5, 0.5); GL.Vertex3(-0.5, -0.5, 0.5); // right face GL.Normal3(1, 0, 0); GL.Vertex3(0.5, -0.5, -0.5); GL.Vertex3(0.5, 0.5, -0.5); GL.Vertex3(0.5, 0.5, 0.5); GL.Vertex3(0.5, -0.5, 0.5); // left face GL.Normal3(-1, 0, 0); GL.Vertex3(-0.5, -0.5, -0.5); GL.Vertex3(-0.5, -0.5, 0.5); GL.Vertex3(-0.5, 0.5, 0.5); GL.Vertex3(-0.5, 0.5, -0.5); } GL.End(); } else { Glut.glutSolidCube(1.0); } } GL.PopMatrix(); GL.Flush(); } // resizes the viewport private void reshape(int w, int h) { GL.Viewport(0, 0, w, h); GL.MatrixMode(OpenTK.OpenGL.Enums.MatrixMode.Projection); GL.LoadIdentity(); if (w <= h) { GL.Ortho(-1.5, 1.5, -1.5 * (double)h / (double)w, 1.5 * (double)h / (double)w, -10.0, 10.0); } else { GL.Ortho(-1.5 * (double)w / (double)h, 1.5 * (double)w / (double)h, -1.5, 1.5, -10.0, 10.0); } GL.MatrixMode(OpenTK.OpenGL.Enums.MatrixMode.Modelview); GL.LoadIdentity(); } // GLControl resize event handler private void glControl1_Resize(object sender, EventArgs e) { if (!loaded) return; reshape(glControl1.Width, glControl1.Height); } // GLControl paint event handler private void glControl1_Paint(object sender, PaintEventArgs e) { if (!loaded) return; display(); glControl1.SwapBuffers(); } // Main form load event handler private void Form1_Load(object sender, EventArgs e) { loaded = true; init(); reshape(glControl1.Width, glControl1.Height); } } }


Comments
Re: Lighting in GLControl
What happens if you change this:
to this?
Also, keep in mind that you can use Tao.OpenGl with OpenTK.GLControl (makes sense if you have a lot of existing code). OpenTK.OpenGL may be a bit cleaner than Tao.OpenGl, but functionally they are identical.
Re: Lighting in GLControl
Thanks ever so much for spotting that! Yes, using doubles in the call to GL.Normal3() means that the cube is lit properly.
Thanks also for the tip about using Tao.OpenGl with the OpenTK.GLControl, I had thought about that but I wanted to keep the number of dlls to a minimum.
Re: Lighting in GLControl
You are welcome :)
Regarding the amount of dlls, you can always merge everything into the exe with ILMerge on Windows or monomerge on Linux/MacOS. This will also reduce size, sometimes dramatically.
For example, a simple "hello world" OpenTK application can be typically compressed to 10-20KB or so. There's little point in distributing the whole 1.5MB OpenTK.dll in this case.
Re: Lighting in GLControl
How much have you tried ILMerge? Has there been any issues with it yet?
It's quite a feat, but I wouldn't buy into it if it cases any harm - OpenTK's 1.5 mb is simply quite small 2008 anyway :)
Re: Lighting in GLControl
I've tried monolinker and I'm planning to test monomerge (if I manage find how to build it). The first tools copies all dependencies of your exe and (optionally) strips them (IIRC, OpenTK.dll fell to 20KB or so for Examples.exe). The latter can merge everything into a single exe.
I haven't used ILMerge myself yet, but it's quite widespread and there's a lot of material available. I'm going to use it in the OpenTK demo though.
And while 1.5MB does not sound much, there are still dialup users out there. Besides, if you are using dependencies like Tao.OpenGl (1.2MB or so), it adds up to quite a lot. No point in distributing 3MB you can go down to 300KB (someone has to pay for the bandwidth, too).
Re: Lighting in GLControl
Problem is, .NET/mono 1.2.6 itself is not that widespread. That's like 23 mb dotnetfx.exe for windows, don't know the numbers for linux. What's the numbers for mac?
Re: Lighting in GLControl
That's not my experience at all. Almost all computers have .Net 2.0/Mono 1.2.x installed these days. Only vanilla WinXP SP2 computers don't have it, and SP3 will solve that anyway.
If this is a problem, on Linux you can create a native executable that bundles mono, with mkbundle (don't know if this works on windows). But I really don't think this is a problem.
Re: Lighting in GLControl
The user base for my app is going to be very small so I don't think I need to worry about the availability of .net 2.0/Mono 1.2.x, they are all big enough and clever enough to work out how to update their installations accordingly. I think I might look into extracting the GLControl from the OpenTK project and building it directly into my project though, then I won't need to worry about ILMerge, and I will save time converting to OpenTK from Tao.OpenGL.
By the way, is the fact that Normal3() works differently for integer and double arguments a bug?
Re: Lighting in GLControl
No, this is the expected behavior: http://www.ugrad.cs.ubc.ca/~cs314/opengl/glNormal.html
GL.Normal3 always converts its parameters to floats, by dividing the value you specify by MAX_INT (or MAX_SHORT, or MAX_BYTE etc). You should always use the float or double versions to avoid this conversion.
Extracting GLControl won't be easy. It depends on other classes (GraphicsContext, GraphicsMode), which in turn depend on platform specific methods. It might be easier to update Tao.SimpleOpenGlControl itself to run on Linux, using Tao.Platform.X11 from SVN.
Or if you don't care about size, just include OpenTK.dll and stop worrying about it :)
Re: Lighting in GLControl
Fiddler: Is it OK to include precisely the .cs files of OpenTK I actually use in eg. Dogfight? That would be another way of "bundling" to one exe, besides ILMerge?
.NET availability: SP3 will be a nice upgrade for the world, then :)
Ubuntu: which Mono will it be? (hoping 1.9, guessing 1.2.6 but that's enough for OpenTK, right?)
Mac: how is the situation here?