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

Aktuelle Zeit: Sa Jul 19, 2025 11:33

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



Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: ShadowMapping - das ewige Problem
BeitragVerfasst: Di Feb 21, 2012 14:08 
Offline
DGL Member

Registriert: Di Aug 09, 2011 07:33
Beiträge: 163
Programmiersprache: C/C++
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 :?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Feb 21, 2012 18:51 
Offline
DGL Member

Registriert: Do Apr 22, 2010 17:17
Beiträge: 543
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.  


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Feb 21, 2012 18:57 
Offline
DGL Member

Registriert: Do Apr 22, 2010 17:17
Beiträge: 543
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


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Feb 21, 2012 22:46 
Offline
DGL Member

Registriert: Di Aug 09, 2011 07:33
Beiträge: 163
Programmiersprache: C/C++
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 | 8501-mal betrachtet ]
Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Feb 22, 2012 10:39 
Offline
DGL Member

Registriert: Di Aug 09, 2011 07:33
Beiträge: 163
Programmiersprache: C/C++
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]
446-mal heruntergeladen
Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Mär 19, 2012 22:02 
Offline
DGL Member

Registriert: Di Aug 09, 2011 07:33
Beiträge: 163
Programmiersprache: C/C++
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 :)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Apr 19, 2012 13:48 
Offline
DGL Member

Registriert: Di Aug 09, 2011 07:33
Beiträge: 163
Programmiersprache: C/C++
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.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Apr 19, 2012 22:25 
Offline
DGL Member

Registriert: Fr Okt 03, 2008 13:32
Beiträge: 367
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.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Apr 20, 2012 00:37 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
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.

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Apr 20, 2012 07:09 
Offline
DGL Member

Registriert: Di Aug 09, 2011 07:33
Beiträge: 163
Programmiersprache: C/C++
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:


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 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.011s | 17 Queries | GZIP : On ]