PDA

View Full Version : Reverse face changes colour when using LightModelTwoSide (OpenTK)



wotnot
02-21-2016, 10:16 AM
I hope somebody may be able to help me troubleshoot a problem with a relatively simple bit of OpenTK code. (There is an OpenTK forum, but judging by the fact that the most recent posts were > 5 weeks ago and are mostly spam, it looks dead - hence I am asking it here. The problem is not necessarily OpenTK-specific.)

I have translated some OpenGL code that I wrote years ago from VB6 to C# using the OpenTK library. This has basically been a learning exercise because I am fairly new to C#. The OpenGL methods that I have used are old-school deprecated ones, rather than shaders. The object of the exercise was more about C# than OpenGL/OpenTK - I'm not out to change the code more than necessary.

The code draws a 3D model, with ambient lighting, and moves it around. The user can click and drag to spin it around the vertical axis. This works, probably as well as it ever did in the VB version. I am fairly happy with it and have learnt the basics of C# in the process.

There is only one real problem with it that I can see, which relates to the reverse side of polygons. The majority of the polygons that make up the model are only seen from one side, since it is mostly a convex/continuous surface. However, there are a few red polygons which have both sides visible. By default - if I do nothing - the reverse side is always dark. This is as expected. To address this I added the following at the end of my 'InitLighting' method, which defines the lighting parameters:


GL.LightModel(LightModelParameter.LightModelTwoSid e,1);

When this line is included, the shading looks right (i.e. the reverse face is bright when perpendicular to the light source, and increasingly dark as it is angled away). However, it is the wrong colour. Adding the above line changes the reverse face from red to white. The front face, meanwhile, is fine - in either case the front is red and correctly shaded.

I don't think it is relevant to post too much other code here. To briefly summarise how the drawing part of it works, I am using a display list, with commands something like this:


GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.PushMatrix();
GL.Rotate( ... );
GL.Translate( ... );
GL.CallList(surface_list);
GL.PopMatrix();


When creating the display list I do something like this:


SetNormal(v1, v2, v3);
GL.Begin(BeginMode.Triangles);
GL.Vertex3(v1.x, v1.y, v1.z);
GL.Vertex3(v2.x, v2.y, v2.z);
GL.Vertex3(v3.x, v3.y, v3.z);
GL.End();


Lighting is set up as follows:



GL.Light(LightName.Light0, LightParameter.Position, new[] { LightPos.X, LightPos.Y, LightPos.Z, 1f });
GL.Light(LightName.Light0, LightParameter.Ambient, new[] { 0f, 0f, 0f, 1f });
GL.Light(LightName.Light0, LightParameter.Diffuse, new[] { 1f, 1f, 1f, 1f });
GL.Light(LightName.Light0, LightParameter.Specular, new[] { 1f, 1f, 1f, 1f });
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.Light0);


...followed by, as I said above, the all important...


GL.LightModel(LightModelParameter.LightModelTwoSid e,1);

I don't know whether this problem occurred in the VB implementation, since I can no longer run it.

Using Visual Studio 2015, C#, OpenTK, Windows 10 64 bit. Thanks in advance for any suggestions.

GClements
02-21-2016, 11:24 AM
To address this I added the following at the end of my 'InitLighting' method, which defines the lighting parameters:


GL.LightModel(LightModelParameter.LightModelTwoSid e,1);

When this line is included, the shading looks right (i.e. the reverse face is bright when perpendicular to the light source, and increasingly dark as it is angled away). However, it is the wrong colour. Adding the above line changes the reverse face from red to white. The front face, meanwhile, is fine - in either case the front is red and correctly shaded.


This suggests that you're calling glMaterial() with the first parameter equal to GL_FRONT, so you're only setting the material for front faces, with back faces keeping the default material parameters (which are colourless). You need to pass GL_FRONT_AND_BACK to set the same material for both front and back faces.

wotnot
02-21-2016, 11:40 AM
Quite right - thank you very much. Blindingly obvious now you have pointed it out, but those glMaterial calls had been there for ever and I hadn't appreciated that they were face-specific.

Problem solved. Case closed.