DGL
https://delphigl.com/forum/

Deferred Shading
https://delphigl.com/forum/viewtopic.php?f=20&t=9735
Seite 2 von 2

Autor:  AlexMaRu [ So Feb 13, 2011 14:36 ]
Betreff des Beitrags:  Re: Deferred Shading

Hi, Du brauchst eigentlich nur für die Position eine RGBA32F-Textur, für alle weiteren Texturen würde ich das GL_RGBA8 Format verwenden.
Entsprechend der OpenGL 3(.3) Spezifikation kannst Du durchaus auch Texturen mit verschiedenen Formaten an einen Framebuffer binden.

Autor:  Pk3 [ Sa Mär 05, 2011 16:26 ]
Betreff des Beitrags:  Re: Deferred Shading

So nach langer Zeit bin ich wieder zurück ;). Also ich machs doch jetzt mit einer Depth - Texture anstatt mit einer Vertex. Leider find ich im Internet fast gar nix darüber, wie man mittels Depth - Texture die 3D - Position eines bestimmten Pixels ermittelt. Also der Deferred - Shader sieht momentan wie folgt aus:

Fragment:
Code:
uniform sampler2D Texture0;   // Color - Texture
uniform sampler2D Texture1;   // Normal - Texture
uniform sampler2D Texture2;   // Depth - Texture

varying mat4 matProjectionInverse;
varying mat4 matModelView;

const float f = 10000.0;
const float n = 0.1;

void main() {
   vec2 texcoord = vec2(gl_TexCoord[0]);

   vec4 vColor = texture2D(Texture0, texcoord);
   float fDepth = texture2D(Texture2, texcoord).x;

   // Infinity = no light
   if(fDepth >= 1.0) {
      gl_FragColor = vec4(vColor.rgb, 1.0);
      discard;
   }

   vec4 vNormal = texture2D(Texture1, texcoord);
   vNormal.xyz = vNormal.xyz * 2.0 - 1.0;


   // === Hier liegt das Problem ===

   float fZ = (2.0 * n) / (f + n - fDepth * (f - n));

   vec4 vVertex = vec4(texcoord.xy, fDepth, 1.0) * matProjectionInverse;
   vVertex.xyz /= vVertex.w;

   // ==============================


   vec3 ISpecular = vec3(0.0, 0.0, 0.0);
   vec3 IDiffuse = vec3(0.0, 0.0, 0.0);
   vec3 vEye = normalize(-vVertex.xyz);
   float lightFactor;

   for(int i = 0; i < 8; i++) {
      if(gl_LightSource[i].constantAttenuation > 0.0) {
         if(gl_LightSource[i].position.w == 1.0) {
            lightFactor = 1.0 - min(distance(gl_LightSource[i].position.xyz, vVertex.xyz) / gl_LightSource[i].constantAttenuation, 1.0);
         }
         else {
            lightFactor = 1.0;
         }

         if(lightFactor > 0.0) {
            vec3 vLight = normalize(gl_LightSource[i].position.xyz - vVertex.xyz);
            vec3 Reflected = normalize(reflect(-vLight, vNormal.xyz));
            float fDiffuse = lightFactor * (vColor.w * gl_LightSource[i].diffuse.x);
            float fSpecular = lightFactor * (vNormal.w * gl_LightSource[i].specular.x);

            IDiffuse  += fDiffuse * max(dot(vNormal.xyz, vLight), 0.0);
            ISpecular += fSpecular * pow(max(dot(Reflected, vEye), 0.0), 128.0);
         }
      }
   }

   gl_FragColor = vec4((IDiffuse + ISpecular) * vColor.rgb, 1.0);
}



Vertex:
Code:
uniform float fProj[16];

varying mat4 matProjectionInverse;
varying mat4 matModelView;

void main(void) {
   mat4 matProjection;

   matProjection[0][0] = fProj[0];
   matProjection[0][1] = fProj[1];
   matProjection[0][2] = fProj[2];
   matProjection[0][3] = fProj[3];

   matProjection[1][0] = fProj[4];
   matProjection[1][1] = fProj[5];
   matProjection[1][2] = fProj[6];
   matProjection[1][3] = fProj[7];

   matProjection[2][0] = fProj[8];
   matProjection[2][1] = fProj[9];
   matProjection[2][2] = fProj[10];
   matProjection[2][3] = fProj[11];

   matProjection[3][0] = fProj[12];
   matProjection[3][1] = fProj[13];
   matProjection[3][2] = fProj[14];
   matProjection[3][3] = fProj[15];

   matProjectionInverse = gl_ModelViewProjectionMatrixInverse;
   matModelView = gl_ModelViewMatrix;

   gl_TexCoord[0] = gl_MultiTexCoord0;
   gl_Position = matProjection * gl_Vertex;
}


Also wenn ich die Kameraposition (nur die Position!) verändere, verändert sich auch das Diffuse - Licht. Weiß jemand wie man richtig die Position daraus berechnet? (Den oben gekennzeichneten Code mit der Berechnung der Position hab ich im Internet gefunden.)

Autor:  Coolcat [ Sa Mär 05, 2011 17:00 ]
Betreff des Beitrags:  Re: Deferred Shading

Was spricht gegen die Verwendung von gl_ProjectionMatrix bzw. gl_ProjectionMatrixInverse? Des weiteren kann man auch Uniforms vom Typ mat4 benutzen. Also diese Matrix-Kopieraktion ist definitiv nicht notwendig ;)

Mit gl_ProjectionMatrix bekommst du das was mittels glMatrixMode(GL_PROJECTION) gesetzt wurde. Also wenn du dein Screen-Quad für den Deferred Shader renderst müsstest du dann die alte Projektion setzen. Ist aber kein Problem da man zum rendern eines Screen-Quads ja keine Projektion braucht....bei mir sieht der Vertexshader meist einfach so aus:
Code:
void main() {
   gl_Position = vec4(gl_Vertex.xy, 0, 1);

   gl_TexCoord[0].st = gl_Vertex.st * vec2(0.5,0.5) + vec2(0.5,0.5);
   gl_TexCoord[0].pq = vec2(0,0);
}

Die Vertices (für zwei Dreiecke) sind die folgenden:
Code:
const float vertices[] = {
      -1.0,  1.0,
      1.0,  1.0,
      -1.0, -1.0,
      -1.0, -1.0,
      1.0,  1.0,
      1.0, -1.0
};


========

Also mit Hilfe der Tiefe und der inversen Projektionsmatrix die Vertexposition zu errechnen. Dafür brauchst du den Vertex in den sog. normalisierten Gerätekoordinaten (NDC). Das ist einfach ein Einheitswürfel von -1 bis 1. Für X und Y bekommst du das leicht aus den Texturkoordinaten, ist aber natürlich abhängig wierum deine Texcoord sind...also ggf. musst du noch spiegeln.
Code:
vec4 vertex;
vertex.xy = gl_TexCoord[0].st * 2.0 - 1.0;

Die Z-Koordinate ist natürlich davon abhängig was du da in deiner Textur hast. Der Wert dürfte aber zwischen 0 und 1 liegen denke ich mal. Dann musst du das auf die gleiche weise auf den -1...1 Bereich mappen.
Code:
vertex.z = fDepth * 2.0 - 1.0;

Der Rest ist dann klar:
Code:
vertex.w = 1.0;
vertex = vertex * gl_ProjectionMatrixInverse;
vertex *= 1.0/vertex.w;

Autor:  Pk3 [ Sa Mär 05, 2011 17:44 ]
Betreff des Beitrags:  Re: Deferred Shading

Danke für die Antwort! Habs übernommen, aber scheinbar siehts leider immer noch so aus wie vorher :( ... Hab das Gefühl als würde die Vertexposition nicht richtig transformiert sein so wie die Lichtposition...

Autor:  Pk3 [ So Mär 06, 2011 00:17 ]
Betreff des Beitrags:  Re: Deferred Shading

Problem gelöst :D. Nach langem Rumprobieren hab ich herausgefunden, dass es mit gl_ProjectionMatrixInverseTranspose anstatt mit gl_ProjectionMatrixInverse funktioniert. Läuft jetzt alles perfekt. Danke an alle :)! Wens interessiert, hier der Code:

Fragment:
Code:
uniform sampler2D Texture0;   // Color - Texture
uniform sampler2D Texture1;   // Normal - Texture
uniform sampler2D Texture2;   // Depth - Texture

varying mat4 matProjectionInverse;

void main() {
   vec2 texcoord = vec2(gl_TexCoord[0]);
   vec4 vColor = texture2D(Texture0, texcoord);
   float fDepth = texture2D(Texture2, texcoord).x;

   if(fDepth >= 1.0) {
      gl_FragColor = vec4(vColor.rgb, 1.0);
      discard;
   }

   vec4 vNormal = texture2D(Texture1, texcoord);
   vNormal.xyz = vNormal.xyz * 2.0 - 1.0;

   vec4 vVertex;
   vVertex.xy = gl_TexCoord[0].st * 2.0 - 1.0;
   vVertex.z = fDepth * 2.0 - 1.0;
   vVertex.w = 1.0;
   vVertex *= matProjectionInverse;
   vVertex *= 1.0/vVertex.w;

   float ISpecular = 0.0;
   float IDiffuse = 0.0;
   float lightFactor;

   vec3 vEye = normalize(-vVertex.xyz);

   for(int i = 0; i < 8; i++) {
      if(gl_LightSource[i].constantAttenuation > 0.0) {
         if(gl_LightSource[i].position.w == 1.0) {
            lightFactor = 1.0 - min(distance(gl_LightSource[i].position.xyz, vVertex.xyz) / gl_LightSource[i].constantAttenuation, 1.0);
         }
         else {
            lightFactor = 1.0;
         }

         if(lightFactor > 0.0) {
            vec3 vLight = normalize(gl_LightSource[i].position.xyz - vVertex.xyz);
            vec3 Reflected = normalize(reflect(-vLight, vNormal.xyz));
            float fDiffuse = lightFactor * (vColor.w * gl_LightSource[i].diffuse.x);
            float fSpecular = lightFactor * (vNormal.w * gl_LightSource[i].specular.x);

            IDiffuse  += fDiffuse * max(dot(vNormal.xyz, vLight), 0.0);
            ISpecular += fSpecular * pow(max(dot(Reflected, vEye), 0.0), 128.0);
         }
      }
   }

   gl_FragColor = vec4((IDiffuse + ISpecular) * vColor.rgb, 1.0);
}


Vertex:
Code:
varying mat4 matProjectionInverse;

void main(void) {
   matProjectionInverse = gl_ProjectionMatrixInverseTranspose;

   gl_TexCoord[0].st = gl_Vertex.st * vec2(0.5, 0.5) + vec2(0.5, 0.5);
   gl_TexCoord[0].pq = vec2(0.0, 0.0);

   gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);
}



Normal (Fragment):
Code:
varying vec3 vNormal;

void main(void) {
   vec3 vResult = (vNormal + 1.0) / 2.0;
   gl_FragColor = vec4(vResult, gl_FrontMaterial.specular.x);
}


Color (Fragment):
Code:
uniform sampler2D Texture0;

void main(void) {
   vec2 texcoord = vec2(gl_TexCoord[0]);
   vec3 vColor = texture2D(Texture0, texcoord).rgb;
   gl_FragColor = vec4(vColor, gl_FrontMaterial.diffuse.x);
}



gl_LightSource[i].constantAttenuation = Radius vom Licht
gl_LightSource[i].position.w ( 0 = unendlich strahlendes Licht, 1 = begrenzter Lichtradius)
vColor.w = Diffuse - Anteil
vNormal.w = Specular - Anteil

Autor:  Coolcat [ So Mär 06, 2011 11:06 ]
Betreff des Beitrags:  Re: Deferred Shading

Zitat:
Nach langem Rumprobieren hab ich herausgefunden, dass es mit gl_ProjectionMatrixInverseTranspose anstatt mit gl_ProjectionMatrixInverse funktioniert.

Das liegt nur an meiner Dummheit das ich
vertex = vertex * gl_ProjectionMatrixInverse;
statt
vertex = gl_ProjectionMatrixInverse * vertex;
geschrieben habe ;)

Zitat:
varying mat4 matProjectionInverse;

Alle eingebauten Uniforms sind sowohl im Vertex- als auch im Fragmentshader verfügbar. Insofern ist es nicht nötig da ein Varying zu benutzen.

Autor:  Thmfrnk [ Di Mär 08, 2011 22:59 ]
Betreff des Beitrags:  Re: Deferred Shading

ich häng mich da mal nochmal dran:

renderst du nun via MRT die Szene mit einemmal in den FBO oder einfach nacheinander in verschiedene Texturen?

Autor:  Pk3 [ Mi Mär 09, 2011 00:14 ]
Betreff des Beitrags:  Re: Deferred Shading

@Thmfrnk
Sowohl als auch ;). Habs so gemacht, das sich das an die Hardware anpasst. Also wenn MRT unterstützt wird, wirds auch verwendet. Ansonsten einzeln (2 Renderpasses).

Achja, hier könnt ihr das Ergebnis sehen (hab ein Benchmark - Programm damit gemacht):
http://xyross.de/bench/index.php?id=1

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