Pootle's picture

Lighting in GLControl

At 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

Comment viewing options

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

As long as you keep the license in source distributions, it's ok.

Ubuntu 8.04 will ship with 1.2.6, which is ok (not great, but ok). MacOS does not contain Mono by default, but there's an installer available. If that's a problem, I think there's a way to bundle the runtime with your app (MacOS users probably have broadband too :) ).

Inertia's picture

As long as you keep the license in source distributions, it's ok.
Are you sure this is the correct interpretation of the license? The way I understand it, the license must be included in anything that contains a "substantial portion" of OpenTK (which after my definition refers to the complexity of a class/struct, but not a single function. Not sure how this can be interpreted legally) no matter if binary or source.

Either way, I wouldn't recommend to bother too much with filesize or how the application's directory looks like. Most users will never care to take a look, and a shortcut to the executable is all contact they have to your app's directory after install. Including the OpenTK.dll has advantages aswell, as you don't have to release a new version of your app every time OpenTK is updated and you have a clean separation between OpenTK vanilla code and your custom changes.

objarni's picture

Mac: It seems it's a 100 mb download. Not very inspiring for an indie game developer as myself (the game is probably gonna be a tenth of that, tops).

I'm gonna include OpenTK.dll, I think that is the most robust way. And I'm not going force the user to install OpenTK system-wide, I will put it alongside the game. Since the game is tested and developed for a specific OpenTK version (guess somewhere between 0.9.0 and 1.0) there is no point having it "updateble" and I don't like installing things systemwide at all. Harddrive space if cheap, develop/user time is expensive.

Inertia's picture

Don't misunderstand my last post as "we will sue!" or a similar threat. You can do pretty much whatever you want with OpenTK (even rebuild it, name it OpenBla and distribute that) as long as you give credit.
My point was that people shouldn't worry about it too much because in the end it makes little difference. The .dll is ~300kb compressed and you will want to distribute your applications in a compressed format anyway, be it solely for easier handling (1 file) and the CRC checks.

the Fiddler's picture

Inertia you raised an interesting point. Do you need to include the OpenTK license when you distribute OpenTK binaries with your program?

It's not stated clearly, and IANAL, but reading it now I think you do. I've googled around, but couldn't find anything definitive - other people raise the same question, indicating that the BSD license (which MIT/X11 resembles) states this clearly.

Now, we aren't going to sue anyone, but if you plan to distribute a program into the wild it might be a good idea to dump OpenTK's license into your readme/license agreement - if only to keep yourself covered (especially if you are going commercial, better safe than sorry! :) )

Inertia's picture

Do you need to include the OpenTK license when you distribute OpenTK binaries with your program?
I think so too, the way I understand the license the idea behind it is that the original author is protected from lawsuits, the users have full access to source code and may modify it for their needs, but must note that they haven't completely written it all on their own (which including the license pretty much implies). I believe this concept is quite good for an open-source project, because things like the TKU library will rise or fall, depending on user contributions. OpenTK mentioned in readme files might attract new users, which leads to more people working with it and is pretty much a win situation for everyone involved (tested on many platforms, bug findings, maybe code contributions and the list goes on)

You aren't getting paid for your work on OpenTK and giving credit for it is hopefully nothing that will stop anyone from using it. I can't really think of any reason why this would be a problem, unless you *need* someone else to blame besides yourself in case a user of your application sues you and you need a scapegoat.