migueltk's picture

GL.Normal3 () not working when the parameters are integers

Hi, ...

I have prepared a small program that demonstrates this. In the picture on the left when the parameters are integers and right when the parameters are floats.

Why does this happen?

using System;
 
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
 
namespace LightingTest
{
    public class LightingGameWindow : GameWindow
    {
    	bool floatNormals = false;
    	string titleBase = "LightingTest (Help: The key 'N' switching the parameter type of normal)";
 
    	public LightingGameWindow()
            : base(800, 600, new GraphicsMode(32, 16, 8, 0))
        {
            Title = titleBase + " [Normals as integers]";
 
            this.VSync = OpenTK.VSyncMode.Off;
 
            Keyboard.KeyDown += new EventHandler<KeyboardKeyEventArgs>(Keyboard_KeyDown);
    	}
 
    	void Keyboard_KeyDown(object sender, KeyboardKeyEventArgs e)
    	{
    		if(e.Key == Key.N)
    		{
    			floatNormals = !floatNormals;
 
    			if(floatNormals)
    				Title = titleBase + " [Normals as floats]";
    			else
    				Title = titleBase + " [Normals as integers]";
    		}
    	}
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
            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(ShadingModel.Smooth);
 
            GL.Material(MaterialFace.Front, MaterialParameter.Specular, mat_specular);
            GL.Material(MaterialFace.Front, MaterialParameter.Shininess, mat_shininess);
            GL.Light(LightName.Light0, LightParameter.Position, light_position);
            GL.Light(LightName.Light0, LightParameter.Ambient, light_ambient);
            GL.Light(LightName.Light0, LightParameter.Diffuse, mat_specular);
 
            GL.Enable(EnableCap.Lighting);
            GL.Enable(EnableCap.Light0);
            GL.Enable(EnableCap.DepthTest);
            GL.Enable(EnableCap.ColorMaterial);
            GL.Enable(EnableCap.CullFace);
        }
 
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
 
            GL.Viewport(0, 0, Width, Height);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            if (Width <= Height)
            {
                GL.Ortho(-1.5, 1.5, -1.5 * (double)Height / (double)Width, 1.5 * (double)Height / (double)Width, -10.0, 10.0);
            }
            else
            {
                GL.Ortho(-1.5 * (double)Width / (double)Height, 1.5 * (double)Width / (double)Height, -1.5, 1.5, -10.0, 10.0);
            }
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
        }
 
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);
 
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
            GL.PushMatrix();
            {
                GL.Rotate(10, 1, 0, 0);
                GL.Rotate(10, 0, 1, 0);
 
                GL.Color3(0.0, 0.5, 1.0);
 
                GL.Begin(BeginMode.Quads);
                {
                	// front face
                	if(floatNormals)
                		GL.Normal3(0, 0, 1.0f);
                	else
                    	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
                  	if(floatNormals)
                		GL.Normal3(0, 0, -1.0f);
                	else
                    	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
                  	if(floatNormals)
                		GL.Normal3(0, 1.0f, 0);
                	else
                    	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
                   	if(floatNormals)
                		GL.Normal3(0, -1.0f, 0);
                	else
                    	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
                  	if(floatNormals)
                		GL.Normal3(1.0f, 0, 0);
                	else
                    	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
                  	if(floatNormals)
                		GL.Normal3(-1.0f, 0, 0);
                	else
                    	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();
            }
            GL.PopMatrix();
 
            GL.Flush();
 
            SwapBuffers();
        }      
 
        [STAThread]
        public static void Main(string[] args)
        {
            try
            {
                using (LightingGameWindow p = new LightingGameWindow())
                {
                    p.Run();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}
Inline Images

Comments

Comment viewing options

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

The integer version is rescaled to [-1.0, 1.0] linearly. For instance:

GL.Normal3(-1, 0, 0);

corresponds to:

GL.Normal3(-1.0f / 2^31, 0.0f, 0.0f);

which is about -0.0000000004.6.

migueltk's picture

Why is re-scaled? I understand that the right thing is not rescaled. The problem has been to adapt a code in java to csharp, using lwjgl, I understand that to maintain maximum compatibility with other wrappers right thing is not rescaled.

Regards, ...

the Fiddler's picture

'Rescale' was a wrong choice of words. 'Map' is the correct term. This is done by the driver, not OpenTK:

Quote:

The current normal is set to the given coordinates whenever glNormal is issued. Byte, short, or integer arguments are converted to floating-point format with a linear mapping that maps the most positive representable integer value to 1.0 and the most negative representable integer value to -1.0 .

http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml

OpenTK doesn't modify your parameters in any way. It passes them down to the drivers directly (with the sole exception of strings, which must be converted to ascii).

c2woody's picture

Probably the java-based wrapper has no integer overload for this function and thus converts the integer parameter to float, thus (wrongly) calling a different function than OpenTK which chooses the intended function according to the parameter type.