[SOLVED] OpenGL Lighting Issue lazarus / 70-OpenGL ---------------------------------------------------------------------- Handoko · 2020-03-10 13:24 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, ExtCtrls, LCLType, LclIntf,  OpenGLContext, GL, math; type   { TForm1 }   TForm1 = class(TForm)    OpenGLControl1: TOpenGLControl;    Timer1: TTimer;    procedure FormCreate(Sender: TObject);    procedure OpenGLControl1Paint(Sender: TObject);    procedure Timer1Timer(Sender: TObject);  private    FRotation: GLfloat;    procedure InitGL;  end; var  Form1: TForm1; const  LightDiffuse: array[0..3] of Single = (1, 1, 1, 1); implementation procedure gluPerspective(fovy, aspect, zNear, zFar: GLdouble);var  Width, Height: Double;begin  Height := tan(fovy * pi / 360) * zNear;  Width  := Height * aspect;  glFrustum(-Width, Width, -Height, Height, zNear, zFar);end; {$R *.lfm} { TForm1 } procedure TForm1.OpenGLControl1Paint(Sender: TObject);const  AlreadyInit: Boolean = False;begin  if not(AlreadyInit) then    InitGL;   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);  glLoadIdentity;  glTranslatef(0, 0, -5);  glRotatef(FRotation, 0, 1, 0);  glBegin(GL_TRIANGLES);    glColor3f (1, 0, 0); glVertex3f( 0,  1,  0);    glColor3f (0, 1, 0); glVertex3f(-1, -1,  1);    glColor3f (0, 0, 1); glVertex3f( 1, -1,  1);    glColor3f (1, 0, 0); glVertex3f( 0,  1,  0);    glColor3f (0, 0, 1); glVertex3f( 1, -1,  1);    glColor3f (0, 1, 0); glVertex3f( 1, -1, -1);    glColor3f (1, 0, 0); glVertex3f( 0,  1,  0);    glColor3f (0, 1, 0); glVertex3f( 1, -1, -1);    glColor3f (0, 0, 1); glVertex3f(-1, -1, -1);    glColor3f (1, 0, 0); glVertex3f( 0,  1,  0);    glColor3f (0, 0, 1); glVertex3f(-1, -1, -1);    glColor3f (0, 1, 0); glVertex3f(-1, -1,  1);  glEnd;   OpenGLControl1.SwapBuffers;end; procedure TForm1.FormCreate(Sender: TObject);begin  OpenGLControl1.Anchors := [akTop, akLeft, akBottom, akRight];  OpenGLControl1.MultiSampling := 8;  FRotation := 0;end; procedure TForm1.Timer1Timer(Sender: TObject);begin  OpenGLControl1.Invalidate;   if GetKeyState(VK_RSHIFT) < 0 then    FRotation := FRotation - 0.8  else    if GetKeyState(VK_LSHIFT) < 0 then      FRotation := FRotation + 0.8;end; procedure TForm1.InitGL;begin  glShadeModel(GL_SMOOTH);  glClearColor(0, 0, 0, 0);  glClearDepth(1);  glEnable(GL_DEPTH_TEST);  glDepthFunc(GL_LEQUAL);  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   glViewport(0, 0, OpenGLControl1.Width, OpenGLControl1.Height);  glMatrixMode(GL_PROJECTION);  glLoadIdentity;  gluPerspective(45, OpenGLControl1.Width/OpenGLControl1.Height, 0.1, 100);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity;   glEnable(GL_COLOR_MATERIAL);  glEnable(GL_LIGHTING);  glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);  glEnable(GL_LIGHT1);end; end. ---------------------------------------------------------------------- eljo · 2020-03-10 13:29 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 · 2020-03-10 13:33 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 · 2020-03-10 13:37 Oh well shoot in dark missed I'll look at the code from home later tonight. ---------------------------------------------------------------------- Handoko · 2020-03-11 17:47 I just found an article saying that we can get weird result if enabling light without setting the polygon normal. Problem solved. ---------------------------------------------------------------------- ChrisR · 2020-03-12 15:15 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 · 2020-03-12 15:44 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 · 2020-03-12 17:30 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. ---------------------------------------------------------------------- Handoko · 2020-03-12 18:11 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if not(AlreadyInit) then  begin    InitGL;    AlreadyInit := True;  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. ---------------------------------------------------------------------- wp · 2020-03-12 18:54 OK. Made the requested change. Re-phrased some comments and added on- screen instructions how to use the program. Quote from: Handoko on March 12, 2020, 07:11:35 pmAs 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. ---------------------------------------------------------------------- ChrisR · 2020-03-15 11:37 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 · 2020-03-15 11:54 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.