Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mi Jul 09, 2025 15:56

Foren-Übersicht » Programmierung » Shader
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mo Dez 28, 2009 16:04 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
Is there a best way for normals in glsl?

E.g. on modifying the brick shader from the orange book i stumbled upon this line:
Code:
  1.     vec3 tnorm      = normalize(gl_NormalMatrix * gl_Normal);

So with opengl 3.x we no longer have gl_NormalMatrix so better provide my own. And have a look on the delphigl wiki on the go:
Code:

But i do not fully understand it, eg:
Code:
  1. for (unsigned int i=0;i<3;i++)
  2.             for (unsigned int j=0;j<3;j++)
  3.               m_NormalMatrix[i*3+j]=tnmat[i*3+j]/d;
  4.           return tnmat;

What is the endresult? tnmat or m_NormalMatrix?
But when using it with the following in the vertex shader:
Code:
  1.     vec3 tnorm      = normalize(normalMatrix * normal);

Some sides of the cube look to dark e.g. are pitch black.
This is how my normal matrix and determinant code looks like:
Code:
  1.  
  2. type
  3.   GLMatrix4 = array[0..15] of GLfloat; // 4x4 Matrix type
  4.   GLMatrix3 = array[0..8] of GLfloat; // 3x3 Matrix type
  5.  
  6. function determinant(const amatrix: GLmatrix3): GLFloat;
  7. begin
  8.   result := amatrix[0]*((amatrix[4]*amatrix[8])-(amatrix[5]*amatrix[7]))
  9.           - amatrix[1]*((amatrix[3]*amatrix[8])-(amatrix[5]*amatrix[6]))
  10.           + amatrix[2]*((amatrix[3]*amatrix[7])-(amatrix[4]*amatrix[8]))
  11. end;
  12.  
  13. procedure normalMatrix(var aresult: GLmatrix3; const modelviewmatrix: GLmatrix4);
  14. var
  15.   tnmat : GLmatrix3;
  16.   m_NormalMatrix  : GLmatrix3;
  17.   d     : GLfloat;
  18.   i,j   : GLuint;
  19. begin
  20.   //Kopiere den Rotations- und Skalierungsanteil aus der Modelview Matrix.
  21.   for i:=0 to 2 do
  22.     for j:=0 to 2 do
  23.       m_NormalMatrix[i*3+j]:=modelviewmatrix[i*4+j];
  24.  
  25.   //Inverse mit Hilfe der Determinante berechnen und Transponieren in einem Schritt(im Fall der Rotationsmatrix
  26.   //ist es nicht wichtig in welcher Reihenfolge Transponieren und Determinieren geschehen.)
  27.  
  28.   d:=Determinant(m_NormalMatrix);
  29.   tnmat[0]:=m_NormalMatrix[4]*m_NormalMatrix[8]-m_NormalMatrix[5]*m_NormalMatrix[7];
  30.   tnmat[3]:=m_NormalMatrix[5]*m_NormalMatrix[6]-m_NormalMatrix[3]*m_NormalMatrix[8];
  31.   tnmat[6]:=m_NormalMatrix[3]*m_NormalMatrix[7]-m_NormalMatrix[4]*m_NormalMatrix[6];
  32.  
  33.   tnmat[1]:=m_NormalMatrix[2]*m_NormalMatrix[7]-m_NormalMatrix[5]*m_NormalMatrix[8];
  34.   tnmat[4]:=m_NormalMatrix[0]*m_NormalMatrix[8]-m_NormalMatrix[2]*m_NormalMatrix[6];
  35.   tnmat[7]:=m_NormalMatrix[1]*m_NormalMatrix[6]-m_NormalMatrix[1]*m_NormalMatrix[7];
  36.  
  37.   tnmat[2]:=m_NormalMatrix[1]*m_NormalMatrix[5]-m_NormalMatrix[2]*m_NormalMatrix[4];
  38.   tnmat[5]:=m_NormalMatrix[2]*m_NormalMatrix[3]-m_NormalMatrix[0]*m_NormalMatrix[5];
  39.   tnmat[8]:=m_NormalMatrix[0]*m_NormalMatrix[4]-m_NormalMatrix[1]*m_NormalMatrix[3];
  40.  
  41.   for i:=0 to 2 do
  42.     for j:=0 to 2 do
  43.       m_NormalMatrix[i*3+j]:=tnmat[i*3+j]/d;
  44.  
  45.   aresult := tnmat; //or should it be m_NormalMatrix?
  46. end;
  47.  

Going away from that i decided to use something more simple:
Code:
  1.     vec3 tnorm      = (modelViewMatrix*vec4(normal, 0.0)).xyz;

And everything looks like i expect it to be.

So is there somthing wrong with my code? Or can i always use the last regarding to normals or is a normalmatrix a must need?

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Dez 28, 2009 16:32 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Probably that method should return m_NormalMatrix ;)

However, if that doesn't work, you may try this Java code:
Code:
  1. public double _00, _01, _02, _03;
  2. public double _10, _11, _12, _13;
  3. public double _20, _21, _22, _23;
  4. public double _30, _31, _32, _33;
  5.  
  6. public Matrix33d getNormalMatrix() {
  7.     double det = _00 * (_22*_11 - _21*_12)
  8.                - _10 * (_22*_01 - _21*_02)
  9.                + _20 * (_12*_01 - _11*_02);
  10.     return new Matrix33d(
  11.          (_22*_11 - _12*_21) / det, -(_22*_10 - _12*_20) / det,  (_21*_10 - _11*_20) / det,
  12.         -(_22*_01 - _02*_21) / det,  (_22*_00 - _02*_20) / det, -(_21*_00 - _01*_20) / det,
  13.          (_12*_01 - _02*_11) / det, -(_12*_00 - _02*_10) / det,  (_11*_00 - _01*_10) / det
  14.     );
  15. }


Zitat:
Going away from that i decided to use something more simple:
Code:
  1. vec3 tnorm = (modelViewMatrix*vec4(normal, 0.0)).xyz;

And everything looks like i expect it to be.

That will work only in a (common) special case: The upper left part of your modelViewMatrix needs to be orthonormal. The NormalMatrix is the transpose of the inverse of modelViewMatrix. So, if modelViewMatrix is orthonormal, you can invert it just by transposing it. The transpose of the transpose is again the matrix you started with.
The upper left part of your modelViewMatrix is orthonormal, if modelViewMatrix does ONLY contain rotation and/or translation, NO scaling or shearing.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Dez 28, 2009 20:32 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
both m_normalmatrix and tmat give wrong results making some faces of my cube black.

while looking at your java example i discovered at typo in my determinant code. The last 8 should have been a 6.
But as it turned out that was not the solution.
Ok then further with the java example and compare that with the normalmapmatrix calculation itself.
A quick comparision tells met that there are differences, so on with the hard job of renumbering the indices.
Now i have the following source:
Code:
  1.  
  2. function determinant(amatrix: GLmatrix3): GLFloat;
  3. begin
  4.   result := amatrix[0]*(amatrix[8]*amatrix[4]-amatrix[5]*amatrix[7])
  5.           - amatrix[1]*(amatrix[8]*amatrix[3]-amatrix[5]*amatrix[6])
  6.           + amatrix[2]*(amatrix[7]*amatrix[3]-amatrix[4]*amatrix[6]);
  7. end;
  8.  
  9. procedure normalMatrix(var aresult: GLmatrix3; modelviewmatrix: GLmatrix4);
  10. var
  11.   tnmat : GLmatrix3;
  12.   m_NormalMatrix  : GLmatrix3;
  13.   d     : GLfloat;
  14.   i,j   : GLuint;
  15. begin
  16.   //Kopiere den Rotations- und Skalierungsanteil aus der Modelview Matrix.
  17.   for i:=0 to 2 do
  18.     for j:=0 to 2 do
  19.       m_NormalMatrix[i*3+j]:=modelviewmatrix[i*4+j];
  20.  
  21.   //Inverse mit Hilfe der Determinante berechnen und Transponieren in einem Schritt(im Fall der Rotationsmatrix
  22.   //ist es nicht wichtig in welcher Reihenfolge Transponieren und Determinieren geschehen.)
  23.  
  24.   d:=Determinant(m_NormalMatrix);
  25.   tnmat[0]:=(m_NormalMatrix[4]*m_NormalMatrix[8]-m_NormalMatrix[5]*m_NormalMatrix[7])/d;
  26.   tnmat[3]:=-(m_NormalMatrix[1]*m_NormalMatrix[8]-m_NormalMatrix[2]*m_NormalMatrix[7])/d;
  27.   tnmat[6]:=(m_NormalMatrix[1]*m_NormalMatrix[5]-m_NormalMatrix[4]*m_NormalMatrix[2])/d;
  28.  
  29.   tnmat[1]:=-(m_NormalMatrix[8]*m_NormalMatrix[3]-m_NormalMatrix[5]*m_NormalMatrix[6])/d;
  30.   tnmat[4]:=(m_NormalMatrix[8]*m_NormalMatrix[0]-m_NormalMatrix[2]*m_NormalMatrix[6])/d;
  31.   tnmat[7]:=-(m_NormalMatrix[5]*m_NormalMatrix[0]-m_NormalMatrix[3]*m_NormalMatrix[2])/d;
  32.  
  33.   tnmat[2]:=(m_NormalMatrix[7]*m_NormalMatrix[3]-m_NormalMatrix[6]*m_NormalMatrix[4])/d;
  34.   tnmat[5]:=-(m_NormalMatrix[7]*m_NormalMatrix[0]-m_NormalMatrix[6]*m_NormalMatrix[1])/d;
  35.   tnmat[8]:=(m_NormalMatrix[4]*m_NormalMatrix[0]-m_NormalMatrix[3]*m_NormalMatrix[1])/d;
  36.  
  37.   aresult := tnmat;
  38. end;
  39.  


And this actualy seems to work ... (at least i do not get pitch black sides anymore ;-) )

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Dez 28, 2009 22:32 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
The complete example: http://www.noeska.net/downloads/ogl3brick.zip

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 
Foren-Übersicht » Programmierung » Shader


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.015s | 15 Queries | GZIP : On ]