DGL
https://delphigl.com/forum/

ShadowMapping - das ewige Problem
https://delphigl.com/forum/viewtopic.php?f=20&t=10316
Seite 1 von 1

Autor:  AMD [ Di Feb 21, 2012 14:08 ]
Betreff des Beitrags:  ShadowMapping - das ewige Problem

Hey,

Das Thema Schatten ist wohl das schlimmste was mir bis jetzt bei OpenGL begegnet ist. Es ist mir zwar möglich ein ganz normales ShadowMapping durchzuführen aber wenns schon darum geht, das etwas auf Shader auszulagern und dann z.B. PCF anzuwenden hörts auf :(

Ich zeige daher mal ein paar Codeteile, in der Hoffnung das jemand den Fehler findet (oder die Fehler).

VertexShader:
Code:
  1. void main()
  2. {
  3.     gl_FrontColor = gl_Color;
  4.     gl_TexCoord[0] = gl_MultiTexCoord1;
  5.     gl_TexCoord[1] = gl_MultiTexCoord2;
  6.     gl_Position = ftransform();
  7. }


Fragment Shader:
Code:
  1. uniform sampler2D Depth1;
  2. uniform sampler2D Depth2;
  3.  
  4. void main()
  5. {
  6.     vec4 texel = texture2DProj(Depth1, gl_TexCoord[0]);
  7.     texel += texture2DProj(Depth2, gl_TexCoord[1]);
  8.     texel.rgb *= 0.2;
  9.     gl_FragColor = texel * gl_Color;
  10. }


C/C++ Code:
Code:
  1.     glPushMatrix();
  2.     float TextureMatrix[16], TextureMatrix2[16];
  3.     float Bias[16] = {  0.5f, 0.0f, 0.0f, 0.0f,
  4.                         0.0f, 0.5f, 0.0f, 0.0f,
  5.                         0.0f, 0.0f, 0.5f, 0.0f,
  6.                         0.5f, 0.5005f, 0.5f, 1.0f
  7.                         };
  8.  
  9.  
  10.     glLoadMatrixf(Bias);
  11.     glMultMatrixf(LightProjMatrix);    
  12.     glMultMatrixf(LightMatrix);
  13.     glGetFloatv(GL_MODELVIEW_MATRIX, TextureMatrix);
  14.  
  15.     glLoadMatrixf(Bias);
  16.     glMultMatrixf(LightProjMatrix2);       
  17.     glMultMatrixf(LightMatrix);
  18.     glGetFloatv(GL_MODELVIEW_MATRIX, TextureMatrix2);
  19.  
  20.     float Row1[4] = {TextureMatrix[0], TextureMatrix[4], TextureMatrix[8], TextureMatrix[12]};
  21.     float Row2[4] = {TextureMatrix[1], TextureMatrix[5], TextureMatrix[9], TextureMatrix[13]};
  22.     float Row3[4] = {TextureMatrix[2], TextureMatrix[6], TextureMatrix[10], TextureMatrix[14]};
  23.     float Row4[4] = {TextureMatrix[3], TextureMatrix[7], TextureMatrix[11], TextureMatrix[15]};
  24.     float Row5[4] = {TextureMatrix2[0], TextureMatrix2[4], TextureMatrix2[8], TextureMatrix2[12]};
  25.     float Row6[4] = {TextureMatrix2[1], TextureMatrix2[5], TextureMatrix2[9], TextureMatrix2[13]};
  26.     float Row7[4] = {TextureMatrix2[2], TextureMatrix2[6], TextureMatrix2[10], TextureMatrix2[14]};
  27.     float Row8[4] = {TextureMatrix2[3], TextureMatrix2[7], TextureMatrix2[11], TextureMatrix2[15]};
  28.  
  29.     glPopMatrix();
  30.  
  31.     glMatrixMode(GL_TEXTURE);
  32.     glPushMatrix(); // Pop Matrix erfolgt nach dem Shader/Code
  33.     glActiveTexture(GL_TEXTURE2);
  34.     glLoadMatrixf(TextureMatrix2);
  35.     glActiveTexture(GL_TEXTURE1);
  36.     glLoadMatrixf(TextureMatrix);
  37.     glMatrixMode(GL_MODELVIEW);
  38.  
  39.  
  40.     glActiveTexture(GL_TEXTURE2);
  41.     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  42.     glTexGenfv(GL_S, GL_EYE_PLANE, Row5);
  43.     glEnable(GL_TEXTURE_GEN_S);
  44.     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  45.     glTexGenfv(GL_T, GL_EYE_PLANE, Row6);
  46.     glEnable(GL_TEXTURE_GEN_T);
  47.     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  48.     glTexGenfv(GL_R, GL_EYE_PLANE, Row7);
  49.     glEnable(GL_TEXTURE_GEN_R);
  50.     glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  51.     glTexGenfv(GL_Q, GL_EYE_PLANE, Row8);
  52.     glEnable(GL_TEXTURE_GEN_Q);
  53.  
  54.     glBindTexture(GL_TEXTURE_2D, depth2);
  55.     glUniform1i(S2, 2);
  56.     glEnable(GL_TEXTURE_2D);
  57.  
  58.  
  59.     glActiveTexture(GL_TEXTURE1);
  60.     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  61.     glTexGenfv(GL_S, GL_EYE_PLANE, Row1);
  62.     glEnable(GL_TEXTURE_GEN_S);
  63.     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  64.     glTexGenfv(GL_T, GL_EYE_PLANE, Row2);
  65.     glEnable(GL_TEXTURE_GEN_T);
  66.     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  67.     glTexGenfv(GL_R, GL_EYE_PLANE, Row3);
  68.     glEnable(GL_TEXTURE_GEN_R);
  69.     glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  70.     glTexGenfv(GL_Q, GL_EYE_PLANE, Row4);
  71.     glEnable(GL_TEXTURE_GEN_Q);
  72.  
  73.     glBindTexture(GL_TEXTURE_2D, depth);
  74.     glUniform1i(S1, 1);
  75.     glEnable(GL_TEXTURE_2D);


Im Shader halt noch:
Code:
  1.     S1 = glGetUniformLocation(ShadowShader, "Depth1");
  2.     S2 = glGetUniformLocation(ShadowShader, "Depth2");



Das sollten die wichtigsten Sachen sein. Das im FBO die richtigen Texturen weiss ich sicher, da ich das schon am laufen hatte (nur eben ohne Shader)! Für mich ist es eben wichtig die beiden Texturen in den Shader zu bekommen damit ich dort auch PCF anwenden kann. Falls noch irgendwas fehlt einfach sagen!

Wäre über Hilfe sehr dankbar :?

Autor:  Thmfrnk [ Di Feb 21, 2012 18:51 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

mhh
also ich hab das mal so gemacht:

Auszug aus Fragmentshader:
Code:
  1.  
  2. uniform sampler2DShadow sunShadowMap;
  3. ...
  4. float xPixelOffset = 0.0002;
  5. float yPixelOffset = 0.0002;
  6.  
  7.  
  8. float lookup( vec2 offSet)
  9.     {  
  10.         return shadow2DProj(sunShadowMap, projCoord + vec4(offSet.x * xPixelOffset * projCoord.w, offSet.y * yPixelOffset * projCoord.w, 0.05, 0.0) ).w;
  11.     }
  12. void main(void) {
  13. ...
  14.    float shadow;
  15.         if (projCoord.w > 3.0)
  16.         {
  17.             float x,y;
  18.             for (y = -1.5 ; y <=1.5 ; y+=1.0)
  19.                 for (x = -1.5 ; x <=1.5 ; x+=1.0)
  20.                     shadow += lookup(vec2(x,y));
  21.            
  22.             shadow /= 16.0 ;   
  23.         }
  24. ...
  25.   gl_FragColor = MeinLicht * shadow;
  26. }
  27.  


VertexShader:
Code:
  1.  
  2.  ...
  3.   vVertex      = gl_ModelViewMatrix * gl_Vertex;    
  4.    vec4 posWorld = InvMat * vVertex;  
  5.    projCoord  = texMat * posWorld;  
  6.    projCoord.z -= 0.14;
  7. ..
  8.  

Autor:  Thmfrnk [ Di Feb 21, 2012 18:57 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

und hier noch auszug wie ich die ProjektionsMatrix erstelle und die Objekte in die Map rendere:
Code:
  1.  
  2. procedure TCoreEngine.GenSunShadowMap;
  3.  procedure SetShadowMatrix;
  4.  begin
  5.   glMatrixMode(GL_PROJECTION);
  6.    glLoadidentity;
  7.     gluPerspective(sunfov, 1, shadowNear, shadowFar);
  8.    glMatrixMode(GL_MODELVIEW);
  9.     glLoadIdentity;
  10.      gluLookat(SunlightX, SunlightY, SunlightZ, 0, 0, 0,   0, 1, 0);
  11.  end;
  12.  
  13.  procedure SetProjectionMatrix;
  14.  const
  15.     bias: TMatrix4f = ((0.5, 0.0, 0.0, 0.0),
  16.                        (0.0, 0.5, 0.0, 0.0),
  17.                        (0.0, 0.0, 0.5, 0.0),
  18.                        (0.5, 0.5, 0.5, 1.0));
  19.   var
  20.     projection: TMatrix4f;
  21.     ModelView: TMatrix4f;
  22.  begin
  23.   glGetFloatv(GL_MODELVIEW_MATRIX, @modelView);
  24.   glGetFloatv(GL_PROJECTION_MATRIX, @projection);
  25.   glMatrixMode(GL_MODELVIEW);
  26.   glLoadidentity;
  27.    glLoadMatrixf(@bias);
  28.    glMultMatrixf(@projection);
  29.    glMultMatrixf(@modelview);
  30.    glGetFloatv(GL_MODELVIEW_MATRIX, @sunMatrix);
  31.  end;
  32.  var
  33.   M: TMatrix4f;
  34.   n, i: Integer;
  35.   cVec: TVector3f;
  36. begin
  37.  cVec := Cam_Vec;
  38.  glMatrixMode(GL_PROJECTION);
  39.   glPushMatrix;
  40.  glMatrixMode(GL_MODELVIEW);
  41.   glPushMatrix;
  42.    SetShadowMatrix;
  43.     //Auf sonnenmatrix setzten
  44. //     glGetFloatv(GL_MODELVIEW_MATRIX, @m);
  45.      //for i := 0 to project.ObjList.Count - 1 do
  46.      // if not assigned (project.ObjList[i].ParentObject) then
  47.      //   project.ObjList[i].SetRenderMatrix(m);
  48.  
  49.         sunShadowFbo.Bind;
  50.  
  51.       glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
  52.            GL_TEXTURE_2D, sunShadowFbo.Tex[0], 0);
  53.            glViewPort(0, 0, sunshadowFBO.Width, sunshadowFBO.Height);
  54.  
  55.           glEnable(GL_CULL_FACE);
  56.            glCullFace(GL_BACK);
  57.             glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  58.             glColorMask(false, false, false, false);
  59.             glPushMatrix;
  60.             glEnable(GL_ALPHA_TEST);
  61.             glAlphafunc(GL_GREATER, 0.9);
  62.             cam_vec[0] := self.SunLightX;
  63.             cam_vec[1] := self.SunLightY;
  64.             cam_vec[2] := Self.SunlightZ;
  65.  
  66.             SunShadowShader.Enable;
  67.                for I := 0 to project.ModelList.Count - 1 do
  68.               if not T3DBasicObject(project.ModelList[i]).IsWaterSurface then
  69.                if T3DBasicObject(project.ModelList[i]).CastShadow then
  70.                 T3DBasicObject(project.ModelList[i]).Render;
  71.             sunShadowShader.Disable;
  72.             glPopMatrix;
  73.             glDisable(GL_ALPHA_TEST);
  74.             glColorMask(true, true, true, true);
  75.            glDisable(GL_CULL_FACE);
  76.    SetProjectionMatrix;
  77.    SunShadowFBO.Unbind;
  78.  
  79.  glMatrixMode(GL_PROJECTION);
  80.   glPopMatrix;
  81.  glMatrixMode(GL_MODELVIEW);
  82.   glPopMatrix;
  83.  //self.SetRenderMatrix;
  84.  cam_vec := cVec;
  85. end;
  86.  
  87.  


hier das Tutorial is auch nich verkehrt: http://fabiensanglard.net/shadowmappingPCF/index.php

Autor:  AMD [ Di Feb 21, 2012 22:46 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

Erstmal danke für die Antwort!

Dieses Tutorial auf der Website habe ich mir schonmal angeschaut aber das klappt doch garnicht?
Wenn ich die fertige exe downloade und ausführe => verbuggt!
Lade den Code und compile es selber => verbuggt!

Dort wird nicht mal im Ansatz ein korrekter Schatten angezeigt (siehe Anhang)

Dateianhänge:
softshadow.jpg
softshadow.jpg [ 26.08 KiB | 8504-mal betrachtet ]

Autor:  AMD [ Mi Feb 22, 2012 10:39 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

Also ich habe den Code mal durchgearbeitet aber letztendlich will es nicht laufen.
Ich wollte mir zum Debuggen das FBO anzeigen lassen - also die DepthTexture - doch da ist nicht wirklich viel zu sehen! Habe daher mal ein FBO von mir 1 zu 1 übernommen, was aber komischerweise nix bringt. Hab auch schon andere Parts ausgetauscht aber ebenso ohne Erfolg. Ich packe den Source nochmal in den Anhang, vllt. stößt ja jemand auf ein Problem - so lang ist der Code ja nicht.

Ich hatte mir auch mal sein normales ShadowMapping angeschaut und muss sagen, dass es auch dort ein Fehler gibt.
Im Fragment Shader will er z.B. eine vec4 Variable an texture2D übergeben - läuft natürlich nicht. Als vec2 mit .st oder texture2DProj und dann vec4 läuft. Fehler sind wohl keine Seltenheit :?

Dateianhänge:
main.cpp [7.5 KiB]
447-mal heruntergeladen

Autor:  AMD [ Mo Mär 19, 2012 22:02 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

Ich schieb das Thema nochmal nach oben und zeige mein aktuellen Stand nochmal kurz aber deutlich:

Im C++ Code:
- Shader wird aktiviert
- Szene wird gerendert
- Shader deaktiviert

Der C++ Code übergibt dem Shader die Tiefentextur sowie die Matrix von der Texture. Diese Matrix setzt sich aus folgenden 3 Dingen zusammen:
BiasMatrix * ProjectionMatrix * LightMatrix

BiasMatrix sollte klar sein.
ProjectionMatrix hat den Inhalt von gluPerspective (also Fov, Ration, Near, Far)
LightMatrix enthält die Kameradaten der Lichtquelle (also Ort und Blickrichtung (via gluLookAt).


Diese Daten werden jedenfalls an den Shader übergeben.

Im VertexShader sieht es so aus:
Code:
  1. uniform mat4 SMC1;
  2.  
  3. void main()
  4. {
  5. gl_FrontColor = gl_Color;
  6. gl_TexCoord[0] = gl_MultiTexCoord0;
  7. gl_TexCoord[1] = gl_Vertex * SMC1;
  8. gl_Position = ftransform();
  9. }


Einen passenden Fragmentshader kann ich nicht wirklich präsentieren, da ich vieles Probiert habe aber nix klappt.
Habe halt lediglich meine uniform sampler2DShadow ShadowMap und eben es mit Shadow2DProj probiert (als Koordinaten gl_TexCoord[1]) genommen - aber es geht halt leider nicht.

Anmerkung, vllt. ist es wichtig:
Ohne Shader habe ich die Schatten immer mit diesen beiden Zeilen dargestellt:

Code:
  1. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  2. glTexGenfv(GL_S, GL_EYE_PLANE, Row1);

(war natürlich auch GL_R, GL_Q, GL_T vorhanden).


Könnte mir bitte jemand einen korrekten FragmentShader zeigen, also wo einfach nur der Schatten dargestellt wird? Wäre wirklich nett! Bei Fragen steh ich natürlich zur Verfügung :)

Autor:  AMD [ Do Apr 19, 2012 13:48 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

Ich habe es nun endlich zum laufen gebracht! :roll:

Welche Technik wäre denn "state of art", um weiche Kanten zu erzeugen? PCF liefert zwar bei ausreichender samplerate gute Ergebnisse aber die Performance ist nicht so überzeugend.

Autor:  Schläfer [ Do Apr 19, 2012 22:25 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

Du könntest dir noch Variance Shadow Maps anschauen. Dabei kann man die Shadowmaps filtern wie man will und benötigt nur noch einen Texturelookup um dann den Schatten darzustellen. Allerdings wird das durch höheren Speicherverbrauch erkauft.
Außerdem hat man nicht das Problem mit Bias und inkorrekten Selfshadows (dafür aber ein anderes: Light Bleeding).

Eine Möglichkeit für PCF wäre noch es mit Dithering zu verwenden. So kann man die nötigen Texturlookups reduzieren und hat trotzdem noch weiche Schatten (die allerdings aus vielen kleinen Einzelpunkten bestehen). Wenn Geschwindigkeit wichtiger ist, wäre das aber zumindest eine Überlegung wert.

Autor:  damadmax [ Fr Apr 20, 2012 00:37 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

AMD hat geschrieben:
Ich habe es nun endlich zum laufen gebracht! :roll:


Woran lag es denn ?

Auf jeden Fall kommt mir folgendes aus dem Vertex Shader merkwürdig vor:
Code:
  1. gl_TexCoord[1] = gl_Vertex * SMC1;

Sollte die Matrix nicht vorne stehen?

AMD hat geschrieben:
Welche Technik wäre denn "state of art", um weiche Kanten zu erzeugen? PCF liefert zwar bei ausreichender samplerate gute Ergebnisse aber die Performance ist nicht so überzeugend.


Ich hatte mich bislang mit 5 Samples zufrieden gegeben und vorhin mal auf 1 Sample mit dithering umgestellt. Nicht der wahnsinn, aber es reicht erstmal.
Aber meinen Shader muss ich sowieso nochmal überarbeiten, weil ich an verschiedenen Stellen immer die Kameraposition rausrechnen muss. Du musst das anscheinend nicht. Allerdings komme ich an die Fragmentkoordinaten auch erst im Fragmentshader, da sie ja aus der Positionstextur des Deferredrenderer kommt.

Autor:  AMD [ Fr Apr 20, 2012 07:09 ]
Betreff des Beitrags:  Re: ShadowMapping - das ewige Problem

Danke für die Antworten.
Qualität ist zwar nicht unrelevant aber das ganz so wichtig ist es auch nicht. Ich schau mir jedenfalls mal das dithering an.

Der Fehler war im Fragmentshader. Es wurde vom shadow2DProj der Wert .w genommen - das klappt auf nvidia Karten ganz gut aber nicht bei AMD/ATI. Nachdem ich es auf .r geändert habe läuft es auf beiden Karten :roll:

Seite 1 von 1 Alle Zeiten sind UTC + 1 Stunde
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/