Recent

Author Topic: Lighting moving with model and want it fixed position  (Read 711 times)

ranny

  • New Member
  • *
  • Posts: 39
Lighting moving with model and want it fixed position
« on: June 27, 2019, 09:03:23 pm »
Hi,

I was posting elsewhere in this forum on a clipboard problem and it was turning into a OpenGL discussion so I am starting a new subject here.

I am really new to OpenGl and have had some excellent advice on this forum.  But I have a little problem...

I am drawing a function that is displayed with quads with a colour gradient.  All is well until I go to add lighting.  When I add the lighting direction and type etc., the faces of the quads are lit, maybe not quite as I expected, but also as I rotate the model the lit faces move with the model when I want the direction of lighting to be fixed.  On advice from others I tried to ensure that lighting is fixed before any other transformations and is called only once, but it doesn't seem to make any difference.

Any advice please?

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Re: Lighting moving with model and want it fixed position
« Reply #1 on: June 27, 2019, 10:20:07 pm »
How does your shader(s) look like and how do you supply the inputs (calculated value, point, gradient, texture)?

ChrisR

  • Jr. Member
  • **
  • Posts: 84
Re: Lighting moving with model and want it fixed position
« Reply #2 on: June 27, 2019, 11:55:56 pm »
Here are two Lazarus OpenGL mesh viewers that have the light position relative to the viewer:
 https://github.com/neurolabusc/plyview
 https://github.com/neurolabusc/Metal-Demos/tree/master/mesh
They are very similar, but the latter can also be compiled for Metal on MacOS (and therefore you will have to use the package inspector to remove the Metal package when you load the project with Windows or Linux).

The shader is here
  https://github.com/neurolabusc/Metal-Demos/blob/master/mesh/Resources/shader/Phong.glsl
 Lighting uses the viewing direction (vV) and the surface normal:
    vV = -vec3(ModelViewMatrix*vec4(Vert,1.0))
    vN = normalize((NormalMatrix * vec4(Norm,1.0)).xyz);

ranny

  • New Member
  • *
  • Posts: 39
Re: Lighting moving with model and want it fixed position
« Reply #3 on: June 28, 2019, 08:19:15 am »
Thanks, I cannot get github on my works laptop and I am far from home at the moment but will look at the weekend.

I did say I was new to this (!) so this is what I do...

Make polygons in clockwise order, establish normals using dot product/cross product and normalise, use one colour for all polygons, do all this in one begin/end quad block.

Lighting is set in an initialisation procedure called once.

Rotations and translations carried out in a OpenGL.paint event.

Am I creating the normals in the wrong place?

See attached plot, I am trying to get a better distribution of colour from light to dark that is from a fixed light source.

Thanks for any help.   

wp

  • Hero Member
  • *****
  • Posts: 6312
Re: Lighting moving with model and want it fixed position
« Reply #4 on: June 28, 2019, 10:16:23 am »
Looks correct. But the devil hides in the details. For giving better help I ask you to provide a simple compilable project which shows the issue (*.pas, *.lfm, *.lpr and *.lpi files in a shared zip which you upload in section "Attachment and other options" of this site. No exe, ppi or other compiler-generated files in the zip, please).

Interestingly I have the same issue in my own 3d-chart project (https://github.com/wp-xyz/OpenGLChart). Because every data point sphere, but not the calculated surfece, behaves correctly with respect to lighting I think that the issue is somewhere related to calculation of normals.

As for the contrast between dark and light: Did you change the position of the light? Did you play with the properties of the light source and, if you don't use COLOR_MATERIAL, of the surface (ambient, diffuse, specular)?
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

ranny

  • New Member
  • *
  • Posts: 39
Re: Lighting moving with model and want it fixed position
« Reply #5 on: June 28, 2019, 10:56:37 am »
Well here goes!

I apolgise in advance for the state of the coding, its got pieces from everywhere stitched in and it doesn't use the best of routines for anything, but it does work in principle.  I have included a sample text file with data to plot and hopefully it will work.

Comments welcome... 

Update:-

Yes, I did play with the light direction and COLOR_MATERIAL but didn't see significant changes towards what I was looking for.
« Last Edit: June 28, 2019, 11:04:09 am by ranny »

wp

  • Hero Member
  • *****
  • Posts: 6312
Re: Lighting moving with model and want it fixed position
« Reply #6 on: June 28, 2019, 12:21:18 pm »
Nice.

I found these issues:
  • You calculate the normals from the grid points in world coordinates. I think this is not correct, because OpenGL plots the data using the normalized coordinates of the bounding box. Since your x and z data  are in the range of 10s, but the y data are in the range of 1s the "normal vectors" are not perpendicular to the patches any more after this transformation. Calculate the normals from the output of the WorldToScreen procedure - see code below.
  • The normals must point in the "outside" direction. This means for your function that the cross-product vector must point in the positive z direction, and quads must be added in counter-clockwise order. I did not go into the details where your code is wrong here, but after using the negative vn.data coordinates in the glNormal call results in a more pleasing surface, also, see code below.
  • When I zoom in around some point symbols I see that the pyramid faces sometimes are not drawn correctly. I guess there is a problem with inside/outside here too (i.e. normals facing in the wrong direction). - see screenshot below
  • Your code turns lighting off and on at several places. To be more general you should store the previous lighting state in a local boolean variable (hasLighting := glIsEnabled(GL_LIGHTIG)) and restore it at the end of these procedures.
  • A very general issue: In the TForm1. methods "FormActivate" and "mnuOpenClick" you refer to the instance variable "Form1". NEVER do this because it will make your code work only when the instance of class TForm1 is really named "Form1"; if you'd once decide to rename the form class to TFitForm (because it is used in a larger project) your code will stop working. Just drop the "form1." in "form1.caption:='PolyFit3';" and simply call "caption := 'PolyFit2';", or in ambiguous cases use "Self" instead - the class automatically knows that it has a property named "caption".
  • Do not pre-dimension the data array type. This limits the amount of data the program is being able to handle, and, most of the time, wastes memory. Just use dynamic arrays instead (type x:array of single). For reading from the file pre-allocate some buffer size (SetLength(x, BUFFER_SIZE)), count the lines during reading and increase the array length when the allocated block is full (if counter = Length(x) then SetLength(x, Length(x) + BUFFER_SIZE)). Finally, after reading trim the array to the correct size (SetLength(x, counter)). (Of course, counter must be intialized to begin with 0,and initially the length of the array must be set to 0, too.
Code: Pascal  [Select]
  1. var
  2.     v1,v2,v3,vn:TVector3_single;
  3.     vs1, vs2, vs3: TVector3_single;
  4.     vline:array[1..2] of TVector3_single;
  5. begin
  6.     ...
  7.  
  8.               v1.data[0]:=xp[i];
  9.               v1.data[1]:=yp[i,j];
  10.               v1.data[2]:=zp[j];
  11.               v2.data[0]:=xp[i];
  12.               v2.data[1]:=yp[i,j+1];
  13.               v2.data[2]:=zp[j+1];
  14.               v3.data[0]:=xp[i+1];
  15.               v3.data[1]:=yp[i+1,j];
  16.               v3.data[2]:=zp[j];
  17.  
  18.               WorldToScreen(v1.data[0], v1.data[1], v1.data[2], vs1.data[0], vs1.data[1], vs1.data[2]);
  19.               WorldToScreen(v2.data[0], v2.data[1], v2.data[2], vs2.data[0], vs2.data[1], vs2.data[2]);
  20.               WorldToScreen(v3.data[0], v3.data[1], v3.data[2], vs3.data[0], vs3.data[1], vs3.data[2]);
  21.  
  22.               vline[1]:=Vector_sub(vs2,vs1);
  23.               vline[2]:=Vector_sub(vs3,vs1);
  24.  
  25.               vn:=vector_crossproduct(vline[1],vline[2]);
  26.               vn:=vector_normalise(vn);
  27.               glNormal3f(-vn.data[0],-vn.data[1],-vn.data[2]);
  28.   ...
  29.  

A suggestion finally: When you do a glRotatef(-90, 1, 0, 0 before the first intruction to create the model, i.e. before "DrawFunc", then the entire view is rotated by 90 degrees around the x axis, and you end up in a coordinate system in which z points upward (and y into the screen) - therefore it is no longer required to exchange y and z in the OpenGL calls.
« Last Edit: June 28, 2019, 01:26:24 pm by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

ranny

  • New Member
  • *
  • Posts: 39
Re: Lighting moving with model and want it fixed position
« Reply #7 on: June 28, 2019, 01:20:51 pm »
Thanks for the valuable comments.

Normals - Yes, when to calculate them was a thought of mine.  I have done some other basic 3D work before and the normals were actually calculated after transforms.  But does this mean they are calculated in the OnPaint event since this is where the WorldtoScreen conversion is carried out?  Also how should this work with display lists where they list is supposed to be generated once for all transforms?  I can give it a go and see what happens.

Update:- Hmm..  I wasn't thinking about that properly.  Does the WorldtoScreen not just normalise all the data for the screen in terms of the values being from 0-1?  Would this make a fundamental difference?  I'm trying a few things to see what the difference is.

I thought my normals were "pointing out" based on my previous programs but I will take account of your suggestions and review the difference.  My other 3D work had Z in the opposite direction to OpenGL so I can imagine it is not right as is.

Good advice on use of Tform1. I tried to learn Delphi many years ago and didn't really do any proper studying on it.  I just followed some snippets of code and managed to make them work, eventually.  My biggest adventure was a complete 2D CAD package that works pretty well with lots of features but I am scared to look back on it now because it will be a real mess with such issues in its 50,000 lines of code!

Arrays - Good advice, again I just did what worked in the past but know dynamic arrays are better.  Something I can implement in all my programs going forward.

Normally I can handle the maths and fundamental scope of such programs, but I am never very elegant in my coding or in employing best practice so thanks for the tips, I will get working on it.

In my work we have to create lots of curves and so next up is trying to accommodate parametric splines and Akima fits, good for sharp turns and reversals,  although they don't generate simple formulas for spreadsheets.


Update:-  Lighting being called many times - that was me fiddling with trying to get it to work and was on the cards to tidy up once I got it to work reasonably well

Update:-  Pyramids - Since the pyramids represent the actual data point, they lie precisely on the curve and I guess it is which gets drawn first, pyramid or curve surface.  The centre of the pyramid is the point so if it were a flat surface you should see a little pyramid above the surface and a frustrum below.  Sometimes the pyramid is inside the cube which means the calculated and actual points are the same
« Last Edit: June 28, 2019, 02:03:27 pm by ranny »

ranny

  • New Member
  • *
  • Posts: 39
Re: Lighting moving with model and want it fixed position
« Reply #8 on: June 28, 2019, 01:45:04 pm »
Ah!  I have just had a major thought....

What I was hoping to achieve was when the image is rotated it will "light" the image based on the light direction being fixed.  Before I attempted OpenGL I did all my own rotations and transforms then calculated the normals.  I did not get the result I wanted because it was assuming the object drawn was solid so if you "looked underneath" it was dark, same is happening in the OpenGl version.

Previously I had the normal being considered against the light source and if the normal was pointing directly to it, it was bright, 90 deg to is was dark, more than 90 was dark (or actually removed from view thinking it was solid).  Seeing the issue I just changed the light intensity to be from 0 to 90 got darker, 90 to 180 got brighter and then you could see the underside being lit.  Have a look at the two images attached showing rotation where you can see the underside.  In the OpenGL version looking at the underside is always dark and it makes me think this is the same sort of issue..... 

ranny

  • New Member
  • *
  • Posts: 39
Re: Lighting moving with model and want it fixed position
« Reply #9 on: July 19, 2019, 11:11:31 am »
Just a quick update, was unable to try some of the links that were provided, I am using 1.6.4 and  I think the code in the links is for later versions?  I have not installed a later version on my PC because when I did it once before, one of my programs would not compile and I have not got around to sorting it yet.

Thanks for the support.