Recent

Author Topic: [SOLVED] OpenGL Lighting Issue  (Read 876 times)

Handoko

  • Hero Member
  • *****
  • Posts: 3542
  • My goal: build my own game engine using Lazarus
[SOLVED] OpenGL Lighting Issue
« on: March 10, 2020, 02:24:48 pm »
Can anyone tell me what I did wrong why rotating the pyramid will cause it become darker then gradually bright again?

Download the code and run, press left/right shift to rotate. The demo requires LazOpenGLContext (and libgl1-mesa-dev if you use Linux).

Code: Pascal  [Select][+][-]
  1. unit unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, ExtCtrls, LCLType, LclIntf,
  9.   OpenGLContext, GL, math;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     OpenGLControl1: TOpenGLControl;
  17.     Timer1: TTimer;
  18.     procedure FormCreate(Sender: TObject);
  19.     procedure OpenGLControl1Paint(Sender: TObject);
  20.     procedure Timer1Timer(Sender: TObject);
  21.   private
  22.     FRotation: GLfloat;
  23.     procedure InitGL;
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29. const
  30.   LightDiffuse: array[0..3] of Single = (1, 1, 1, 1);
  31.  
  32. implementation
  33.  
  34. procedure gluPerspective(fovy, aspect, zNear, zFar: GLdouble);
  35. var
  36.   Width, Height: Double;
  37. begin
  38.   Height := tan(fovy * pi / 360) * zNear;
  39.   Width  := Height * aspect;
  40.   glFrustum(-Width, Width, -Height, Height, zNear, zFar);
  41. end;
  42.  
  43. {$R *.lfm}
  44.  
  45. { TForm1 }
  46.  
  47. procedure TForm1.OpenGLControl1Paint(Sender: TObject);
  48. const
  49.   AlreadyInit: Boolean = False;
  50. begin
  51.   if not(AlreadyInit) then
  52.     InitGL;
  53.  
  54.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  55.   glLoadIdentity;
  56.   glTranslatef(0, 0, -5);
  57.   glRotatef(FRotation, 0, 1, 0);
  58.   glBegin(GL_TRIANGLES);
  59.     glColor3f (1, 0, 0); glVertex3f( 0,  1,  0);
  60.     glColor3f (0, 1, 0); glVertex3f(-1, -1,  1);
  61.     glColor3f (0, 0, 1); glVertex3f( 1, -1,  1);
  62.     glColor3f (1, 0, 0); glVertex3f( 0,  1,  0);
  63.     glColor3f (0, 0, 1); glVertex3f( 1, -1,  1);
  64.     glColor3f (0, 1, 0); glVertex3f( 1, -1, -1);
  65.     glColor3f (1, 0, 0); glVertex3f( 0,  1,  0);
  66.     glColor3f (0, 1, 0); glVertex3f( 1, -1, -1);
  67.     glColor3f (0, 0, 1); glVertex3f(-1, -1, -1);
  68.     glColor3f (1, 0, 0); glVertex3f( 0,  1,  0);
  69.     glColor3f (0, 0, 1); glVertex3f(-1, -1, -1);
  70.     glColor3f (0, 1, 0); glVertex3f(-1, -1,  1);
  71.   glEnd;
  72.  
  73.   OpenGLControl1.SwapBuffers;
  74. end;
  75.  
  76. procedure TForm1.FormCreate(Sender: TObject);
  77. begin
  78.   OpenGLControl1.Anchors := [akTop, akLeft, akBottom, akRight];
  79.   OpenGLControl1.MultiSampling := 8;
  80.   FRotation := 0;
  81. end;
  82.  
  83. procedure TForm1.Timer1Timer(Sender: TObject);
  84. begin
  85.   OpenGLControl1.Invalidate;
  86.  
  87.   if GetKeyState(VK_RSHIFT) < 0 then
  88.     FRotation := FRotation - 0.8
  89.   else
  90.     if GetKeyState(VK_LSHIFT) < 0 then
  91.       FRotation := FRotation + 0.8;
  92. end;
  93.  
  94. procedure TForm1.InitGL;
  95. begin
  96.   glShadeModel(GL_SMOOTH);
  97.   glClearColor(0, 0, 0, 0);
  98.   glClearDepth(1);
  99.   glEnable(GL_DEPTH_TEST);
  100.   glDepthFunc(GL_LEQUAL);
  101.   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  102.  
  103.   glViewport(0, 0, OpenGLControl1.Width, OpenGLControl1.Height);
  104.   glMatrixMode(GL_PROJECTION);
  105.   glLoadIdentity;
  106.   gluPerspective(45, OpenGLControl1.Width/OpenGLControl1.Height, 0.1, 100);
  107.   glMatrixMode(GL_MODELVIEW);
  108.   glLoadIdentity;
  109.  
  110.   glEnable(GL_COLOR_MATERIAL);
  111.   glEnable(GL_LIGHTING);
  112.   glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
  113.   glEnable(GL_LIGHT1);
  114. end;
  115.  
  116. end.
« Last Edit: March 11, 2020, 06:51:41 pm by Handoko »

eljo

  • Sr. Member
  • ****
  • Posts: 407
Re: OpenGL Lighting Issue
« Reply #1 on: March 10, 2020, 02:29:39 pm »
I didn't looked at the code yet but from my experience the problem is usually that you rotate the camera instead of the pyramid and you do not rotate the light as well.
Just a quick fyi I'll take a closer look later.

Handoko

  • Hero Member
  • *****
  • Posts: 3542
  • My goal: build my own game engine using Lazarus
Re: OpenGL Lighting Issue
« Reply #2 on: March 10, 2020, 02:33:41 pm »
That's sound possible. But I don't think it happens on my case. Actually in my 'complete' code, it has several objects. Only the object that rotates becomes darker, while the others stay correct as what they should be (as long as they don't rotate). What I submitted here was a simplified version, consisted only 1 object.

eljo

  • Sr. Member
  • ****
  • Posts: 407
Re: OpenGL Lighting Issue
« Reply #3 on: March 10, 2020, 02:37:08 pm »
Oh well shoot in dark missed I'll look at the code from home later tonight.

Handoko

  • Hero Member
  • *****
  • Posts: 3542
  • My goal: build my own game engine using Lazarus
Re: OpenGL Lighting Issue
« Reply #4 on: March 11, 2020, 06:47:50 pm »
I just found an article saying that we can get weird result if enabling light without setting the polygon normal.

Problem solved.

ChrisR

  • Full Member
  • ***
  • Posts: 124
Re: [SOLVED] OpenGL Lighting Issue
« Reply #5 on: March 12, 2020, 04:15:42 pm »
You might want to look for at the code for plyview https://github.com/neurolabusc/plyview - it provides Pascal code to estimate surface normals for any arbitrary triangular mesh.

Handoko

  • Hero Member
  • *****
  • Posts: 3542
  • My goal: build my own game engine using Lazarus
Re: [SOLVED] OpenGL Lighting Issue
« Reply #6 on: March 12, 2020, 04:44:09 pm »
That's great. I was thinking how to auto calculate the normals. So far I model using Blender and export to obj file, the normals will be provided.

Thank you very much.

wp

  • Hero Member
  • *****
  • Posts: 7213
Re: [SOLVED] OpenGL Lighting Issue
« Reply #7 on: March 12, 2020, 06:30:51 pm »
Maybe you got the solution already, but your problem motivated me to brush up my geometry knowledge.

It should be noted that normals usually must point outwards. To find the correct order of points you must arrange the points such that they follow the direction of your fingers of your right hand - then the thumb points outward.

And the normal vectors must be normalized to unit length.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Handoko

  • Hero Member
  • *****
  • Posts: 3542
  • My goal: build my own game engine using Lazarus
Re: [SOLVED] OpenGL Lighting Issue
« Reply #8 on: March 12, 2020, 07:11:35 pm »
Very educative, thank you for providing that comments in the source code.

I already knew about the normal must point outside and ccw rules. I am more interested in the normal calculations. As I am only high school graduated, I'm very weak in vector equation.

Your improvement of the code works but there was a small not serious bug in my code. Can you please change the line #139, #140 to:

Code: Pascal  [Select][+][-]
  1.   if not(AlreadyInit) then
  2.   begin
  3.     InitGL;
  4.     AlreadyInit := True;
  5.   end;

So, we can add the demo to the how-to demo page.

What I suggested to change, almost has no impact on the performance or whatever. But that was inefficient in the code.

Actually the other way to initialize the OpenGL, as found in Lazarus tutorials is to include enabling TOpenGLContex.AutoResizeViewport. But I did it differently, which is more efficient. Because enabling AutoResizeViewport will always 'reconfigure' the viewport every time the OnPaint event is called, while mine is only once.  That's why I need to put the InitGL at the beginning of OnPaint. Of course the performance gain will be less than 1 millisecond but why not if you know it.
« Last Edit: March 12, 2020, 07:14:37 pm by Handoko »

wp

  • Hero Member
  • *****
  • Posts: 7213
Re: [SOLVED] OpenGL Lighting Issue
« Reply #9 on: March 12, 2020, 07:54:00 pm »
OK. Made the requested change. Re-phrased some comments and added on-screen instructions how to use the program.

As I am only high school graduated, I'm very weak in vector equation.
The key word to search for is "vector cross product". This is some weird way to multiply two vectors in a way that the resulting vector is perpendicular to the plane defined by the two vectors.
« Last Edit: March 12, 2020, 08:00:22 pm by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

ChrisR

  • Full Member
  • ***
  • Posts: 124
Re: [SOLVED] OpenGL Lighting Issue
« Reply #10 on: March 15, 2020, 12:37:46 pm »
Handoko, your OpenGL project uses legacy OpenGL. Be aware that GTK3 drops legacy support (requiring OpenGL Core). Likewise, while MacOS supports legacy OpenGL, it only does so up to OpenGL 2.1. If you want to use modern OpenGL features in MacOS, you must use OpenGL core. Therefore, targeting OpenGL core ensures your Lazarus projects are 'write once, compile anywhere' and can target Windows, GTK2, GTK3, QT5 and Cocoa.

You can see some Lazarus OpenGL core demos here
  https://github.com/neurolabusc/OpenGLCoreTutorials
Also, the Metal-Demos can target either Metal or OpenGL-Core on MacOS, and OpenGL Core on other platforms:
  https://github.com/neurolabusc/Metal-Demos

Handoko

  • Hero Member
  • *****
  • Posts: 3542
  • My goal: build my own game engine using Lazarus
Re: [SOLVED] OpenGL Lighting Issue
« Reply #11 on: March 15, 2020, 12:54:10 pm »
I knew. I am starting to learn the newer OpenGL but before I really start it I am now making sure I really fully understand the legacy mode. And thank you for the links, I am sure to study them but later.

 

TinyPortal © 2005-2018