DGL https://delphigl.com/forum/ |
|
Deferred Shading https://delphigl.com/forum/viewtopic.php?f=20&t=9735 |
Seite 1 von 2 |
Autor: | Pk3 [ Di Feb 08, 2011 18:36 ] |
Betreff des Beitrags: | Deferred Shading |
Hallo, ich versuche gerade einen Szene mittels Deferred Shading zu beleuchten. Dafür sind ja 3 Texturen (Normal-, Vertex- und Colortexture) nötig, die dann an einen 2D - Shader weitergegeben werden. Das Problem liegt beim Erstellen der Vertex - Texture, diese wird nicht korrekt erstellt. Ich verwende folgenden Shader für die Vertex - Texture: Fragment: Code: varying vec3 vVertex; void main(void) { gl_FragColor = vec4(vVertex.xyz / 1000.0, 1.0); } Vertex: Code: varying vec3 vVertex; void main(void) { vVertex = vec3(gl_ModelViewMatrix * gl_Vertex); gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } Ich vermute auch woran es liegt: Daran, dass die Farben die man an "gl_FragColor" gegeben hat, nachträglich verändert wird. Ich habe auch schon versucht den Wert dess Vektors unterhalb von 1.0 zu bekommen (/ 1000.0), aber das ändert leider nichts... Ist es irgentwie möglich die Position in die Textur zu schreiben und diese dann auch gültig wieder auszulesen? Hier noch der 2D - Shader: Fragment: Code: uniform sampler2D Texture0; // color - texture uniform sampler2D Texture1; // normal - texture uniform sampler2D Texture2; // vertex - texture uniform mat4 matModelView; const vec3 vAmbient = vec3(0.05, 0.05, 0.05); const vec3 vSpecular = vec3(0.5, 0.5, 0.5); const vec3 vDiffuse = vec3(1.0, 1.0, 1.0); const float fShininess = 128.0; void main() { vec2 texcoord = vec2(gl_TexCoord[0]); vec3 vColor = texture2D(Texture0, texcoord).xyz; vec3 vNormal = texture2D(Texture1, texcoord).xyz; vec3 vVertex = texture2D(Texture2, texcoord).xyz; vec3 vLightPos = vec3(matModelView * vec4(100.0, 10.0, 100.0, 1.0)) / 1000.0; vec3 vLight = normalize(vLightPos.xyz - vVertex.xyz); vec3 IDiffuse = vDiffuse * max(dot(vNormal, vLight), 0.0); gl_FragColor.xyz = IDiffuse; //gl_FragColor = vec4(normalize(vVertex), 1.0); gl_FragColor.w = 1.0; } Vertex: Code: void main(void) {
gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = ftransform(); } |
Autor: | sharkman [ Di Feb 08, 2011 20:27 ] |
Betreff des Beitrags: | Re: Deferred Shading |
1) 8 bit werden für eine Vertextextur wohl zu wenig sein. Mehr bit nehmen und gut ist (möglicherweise) 2) in der Vertextextur speicherst du doch grundsätzlich daten, die du doch eigentlich bereits durch die xy koordinaten des Pixels und den Wert im Tiefenpuffer hast. Projektion rückgängig machen, und du hast auch wieder deine Werte. (Also anstelle von auslesen der Vertextextur) |
Autor: | Lord Horazont [ Di Feb 08, 2011 20:39 ] |
Betreff des Beitrags: | Re: Deferred Shading |
(hier war doch vorhin noch… verwirrt…) Ja, mehr Bits und vorallem eine Floattextur für die Vertex- und Normalendaten bietet sich an. Und was sharkman in Punkt zwei anspricht ist auch richtig. Du brauchst keine Vertextextur in dem Sinne. Projektion zurückrollen anhand von xy und z des Ausgabevertex sollte reichen. greetings |
Autor: | Coolcat [ Di Feb 08, 2011 23:56 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Das Problem an der Sache ist das du mittels FramebufferObject und MRT nicht verschiedene Datentypen schreiben kannst. Also wenn du eine Float-Textur verwendest, dann muss alles Float sein, also auch Farben und Normale. Falls du eine Float-Textur möchtest, dann benutze GL_RGBA32F_ARB oder GL_RGB32F_ARB als internes Format für alle deine Texturen für den Deferred Shader. Wenn du aber die Vertexposition wie von meinen Vorrednern beschrieben rekonstruierst kannst du dir das sparen. Die Normale müsste sich auch in 4x8bit kodieren lassen und Farben natürlich sowieso. Z.B. zwei Achsen der Normale (z.B. X und Y) in je zwei der Farbkanäle packen. Also den Bereich -1...1 auf den Bereich 0...65535 mappen und das auf zwei Farbkanäle (z.B. R und G) verteilen. (*) Die dritte Achse ergibt sich automatisch daraus, dass die Länge der Normale 1 sein muss. Was noch fehlt ist das Vorzeichen der Z-Achse. Dieses könntest du vielleicht in den Alpha-Kanal der Farbtextur packen, falls dieser nicht anderweitig benötigt wird. Letztlich benötigst du nur 1 Bit dafür. Hinweis: Das ist jetzt eine spontane Überlegung...also ich hab nicht ausprobiert ob das funktioniert bzw. sinnvoll ist. Wenn du des einfacher möchtest kannst du natürlich auch einfach die Normale auf drei 8bit Farbkanäle verteilen. ![]() Edit: (*) Shader-Output muss immer zwischen 0 und 1 liegen, also jeden Farbkanal einzeln nochmal durch 255 teilen. |
Autor: | sharkman [ Mi Feb 09, 2011 12:26 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Zitat: Was noch fehlt ist das Vorzeichen der Z-Achse. Nein, sollte eigentlich nicht noch fehlen. Sinnvoller weise hat man nämlich eh BackfaceCulling an, und sieht nur die Vorderseite der Primitive. Und dort zeigt dann auch die Normale hin (normalerweise, bzw ich wüsste nicht, wieso man es beim Deferred Shading anders machen sollte). Daraus ergibt sich, dass die Normale eigentlich immer zum Betrachter zeigt. Natürlich ist es auch möglich, dass man Normalen braucht, die vom Betrachter wegzeigen (zB bei transparenten Objekten möglich, für den Fall dass hier noch eine Erweiterung auf Inferred Lighting geplant ist), dann muss man das natürlich irgendwie speichern. |
Autor: | Coolcat [ Mi Feb 09, 2011 12:36 ] |
Betreff des Beitrags: | Re: Deferred Shading |
[Unsinn, siehe nächster Post] Zitat: Nein, sollte eigentlich nicht noch fehlen. Sinnvoller weise hat man nämlich eh BackfaceCulling an, und sieht nur die Vorderseite der Primitive. Es geht um das Vorzeichen des Z-Achse, nicht um das der gesamten Normale. Hier zeigen z.B. beide Normalen in Richtung Kamera: Dateianhang: Normale.png [ 6.63 KiB | 12701-mal betrachtet ] Ich muss allerdings zugeben, dass ich auch eine Weile gebraucht habe bis ich realisiert hatte. Ich dachte auch erst man würde das Vorzeichen nicht brauchen und hatte dann eine lang und breite Erklärung geschrieben wieso und warum....bis ich feststellte das es Unsinn ist ![]() [/Unsinn] |
Autor: | sharkman [ Mi Feb 09, 2011 12:50 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Ähm, wie kann die Kamera in Richtung x Achse schauen (so interpretiere ich zumindest dein Bild)? Soweit ich weiß sind da die Normalen nach der Transformation durch die NormalMatrix interessant (liegt hier mein Denkfehler?). |
Autor: | Coolcat [ Mi Feb 09, 2011 12:55 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Oh....richtig....ich war irgendwie von normalen Worldspace ausgegangen wo die Kamera überall sein kann. Zitat: (liegt hier mein Denkfehler?). Kein Denkfehler...der liegt bei mir.... ![]() |
Autor: | Pk3 [ Mi Feb 09, 2011 15:55 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Zitat: 1) 8 bit werden für eine Vertextextur wohl zu wenig sein. Mehr bit nehmen und gut ist (möglicherweise) 8Bit? Ich dachte immer das wären 32Bit.... Na dann erklärt sich ja vieles von selbst. Zitat: 2) in der Vertextextur speicherst du doch grundsätzlich daten, die du doch eigentlich bereits durch die xy koordinaten des Pixels und den Wert im Tiefenpuffer hast. Projektion rückgängig machen, und du hast auch wieder deine Werte. (Also anstelle von auslesen der Vertextextur) Stimmt, dadurch spare ich sogar einen Renderpass. Habs gerade so versucht, aber so wies aussieht funktionierts net richtig. Fragment: Code: uniform sampler2D Texture0; // color - texture uniform sampler2D Texture1; // normal - texture uniform sampler2D Texture2; // depth - texture varying mat4 matProjectionInverse; varying mat4 matModelView; const vec3 vAmbient = vec3(0.05, 0.05, 0.05); const vec3 vSpecular = vec3(0.5, 0.5, 0.5); const vec3 vDiffuse = vec3(1.0, 1.0, 1.0); const float fShininess = 128.0; const float f = 5000.0; const float n = 0.1; void main() { vec2 texcoord = vec2(gl_TexCoord[0]); vec3 vColor = texture2D(Texture0, texcoord).xyz; vec3 vNormal = texture2D(Texture1, texcoord).xyz; float zOverW = texture2D(Texture2, texcoord).r; vec4 H = vec4(texcoord.x * 2.0 -1.0, (1.0 - texcoord.y) * 2.0 -1.0, zOverW, 1.0); vec4 D = H * matProjectionInverse; vec3 vVertex = vec3(D / D.w); vec3 vLightPos = vec3(matModelView * vec4(100.0, 10.0, 100.0, 1.0)); vec3 vLight = normalize(vLightPos.xyz - vVertex.xyz); vec3 IDiffuse = vDiffuse * max(dot(vNormal, vLight), 0.0); gl_FragColor = vec4(IDiffuse, 1.0); gl_FragColor.w = 1.0; } Zitat: Das Problem an der Sache ist das du mittels FramebufferObject und MRT nicht verschiedene Datentypen schreiben kannst. Also wenn du eine Float-Textur verwendest, dann muss alles Float sein, also auch Farben und Normale. Falls du eine Float-Textur möchtest, dann benutze GL_RGBA32F_ARB oder GL_RGB32F_ARB als internes Format für alle deine Texturen für den Deferred Shader. Ich verwende normale Texturen, also keine Framebuffer. Aber ich glaube das ist egal. Das mit der Float-Textur muss ich mal ausprobieren, thx ![]() |
Autor: | Coolcat [ Mi Feb 09, 2011 16:07 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Zitat: Ich verwende normale Texturen, also keine Framebuffer. Ein FramebufferObject (FBO) verwendet ebenfalls "normale" Texturen. Der Vorteil ist aber das du direkt in die Textur rendern kannst. Ansonsten renderst du nämlich erst in einen Framebuffer und musst dann die Daten nochmal extra in eine Textur kopieren. Des weiteren kannst du mittels FBO in mehrere Texturen gleichzeitig rendern. Stichwort: MultipleRenderTargets (MRT). Im Fragmentshader benutzt du dann statt gl_FragColor einfach gl_FragData[0], gl_FragData[1] usw... Ist auch im FBO Tutorial erklärt. Mit dem Deferred Shading willst du ja vermutlich Performance rausholen, also die Szene nicht öfter als notwendig rendern ![]() |
Autor: | Pk3 [ Mi Feb 09, 2011 17:08 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Zitat: Mit dem Deferred Shading willst du ja vermutlich Performance rausholen, also die Szene nicht öfter als notwendig rendern Richtig, aber ich habe erstmal keine FrameBuffer verwendet, weil das ganze auch auf älterer Hardware laufen soll. Aber ich werde noch alle 2 Varianten einbaun, also falls die Hardware FrameBuffer unterstützt, werden die genutzt, ansonsten wird so gerendert wie ichs momentan mach. Das mit der Float-Textur geht glaub ich nicht, liegts an der Initialisierung? Code: glGenTextures(1, &glColorTex); glBindTexture(GL_TEXTURE_2D, glColorTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, pSystem->pRender->Window->nWidth, pSystem->pRender->Window->nHeight, 0, GL_RGBA, GL_FLOAT, 0); glGenTextures(1, &glNormalTex); glBindTexture(GL_TEXTURE_2D, glNormalTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, pSystem->pRender->Window->nWidth, pSystem->pRender->Window->nHeight, 0, GL_RGBA, GL_FLOAT, 0); glGenTextures(1, &glVertexTex); glBindTexture(GL_TEXTURE_2D, glVertexTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, pSystem->pRender->Window->nWidth, pSystem->pRender->Window->nHeight, 0, GL_RGBA, GL_FLOAT, 0); glGenTextures(1, &glDepthTex); glBindTexture(GL_TEXTURE_2D, glDepthTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, pSystem->pRender->Window->nWidth, pSystem->pRender->Window->nHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); Oder vielleicht beim Kopieren der Textur? Code: glBindTexture(GL_TEXTURE_2D, glColorTex);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, 0, 0, pSystem->pRender->Window->nWidth, pSystem->pRender->Window->nHeight, 0); glBindTexture(GL_TEXTURE_2D, glDepthTex); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, pSystem->pRender->Window->nWidth, pSystem->pRender->Window->nHeight, 0); |
Autor: | Coolcat [ Mi Feb 09, 2011 17:15 ] |
Betreff des Beitrags: | Re: Deferred Shading |
glCopyTexImage2D kopiert aus dem primären Framebuffer. Dieser ist immer 8bit RGB oder 8bit RGBA. Selbst wenn also glCopyTexImage2D in der Lage wäre das in Float umzuwandeln, das wird dir nichts bringen da zwischen durch immer in 8bit umgewandelt wird. => Wenn du in Float-Texturen rendern möchtest musst du ein FramebufferObject benutzen. Des weiteren solltest du testen ob deine Hardware das überhaupt kann, d.h. die Extension GL_ARB_texture_float muss verfügbar sein. Wenn du davon ausgehst das deine User nicht mal Support für FBOs haben, kannst du die Nutzung von Float-Texturen vermutlich vergessen. ![]() Bei glCopyTexImage2D mit GL_DEPTH_COMPONENT könnte es ein ähnliches Problem geben. Bin ich mir aber nicht sicher. Jedenfalls ist GL_DEPTH_COMPONENT im Wiki nicht als mögliches Argument aufgezählt. |
Autor: | AlexMaRu [ Do Feb 10, 2011 10:29 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Hi, vielleicht hilft dir mein Deferred Shading Programmbeispiel weiter: http://www.spieleprogrammierung.net/2011/01/opengl-tutorial-version-33-deferred.html |
Autor: | Pk3 [ Fr Feb 11, 2011 15:25 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Ok, bin jetzt doch auf Framebuffer umgestiegen und jetzt funktionierts auch endlich ![]() Ich verwende 4 Float-Texturen (Normal-, Vertex-, Color-, und Speculartexture). Jede dieser Texturen wird so initialisiert: Code: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, pSystem->pRender->Window->nWidth, pSystem->pRender->Window->nHeight, 0, GL_RGBA, GL_FLOAT, 0); Shader, der auf jede Geometrie angewendet wird: Fragment: Code: varying vec3 vNormal; varying vec3 vVertex; uniform sampler2D Texture0; void main(void) { gl_FragData[0] = texture2D(Texture0, gl_TexCoord[0]); // Color - Texture gl_FragData[1] = vec4(vNormal, 1.0); // Normal - Texture gl_FragData[2] = vec4(vVertex, 1.0); // Vertex - Texture gl_FragData[3] = vec4(gl_FrontMaterial.specular.xyz, gl_FrontMaterial.shininess); // Specular - Texture } Vertex: Code: varying vec3 vNormal; varying vec3 vVertex; void main(void) { vNormal = normalize(gl_NormalMatrix * gl_Normal); vVertex = vec3(gl_ModelViewMatrix * gl_Vertex); gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } 2D - Shader Fragment: Code: uniform sampler2D Texture0; // color - texture uniform sampler2D Texture1; // normal - texture uniform sampler2D Texture2; // vertex - texture uniform sampler2D Texture3; // specular - texture void main() { vec2 texcoord = vec2(gl_TexCoord[0]); vec3 vColor = texture2D(Texture0, texcoord).xyz; vec3 vNormal = texture2D(Texture1, texcoord).xyz; vec3 vVertex = texture2D(Texture2, texcoord).xyz; vec4 vMatSpecular = texture2D(Texture3, texcoord); vec3 IDiffuse = vec3(0.0, 0.0, 0.0); vec3 ISpecular = vec3(0.0, 0.0, 0.0); vec3 vEye = normalize(-vVertex); 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) / 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)); vec3 vProductSpecular = vMatSpecular.xyz * gl_LightSource[i].specular.xyz; IDiffuse += (gl_LightSource[i].diffuse * max(dot(vNormal, vLight), 0.0)) * lightFactor; ISpecular += (vProductSpecular * pow(max(dot(Reflected, vEye), 0.0), vMatSpecular.w)) * lightFactor; } } } gl_FragColor = vec4((IDiffuse + ISpecular) * vColor, 1.0); } @AlexMaRu Danke, werde ich mir mal anschauen ![]() |
Autor: | Coolcat [ Fr Feb 11, 2011 15:50 ] |
Betreff des Beitrags: | Re: Deferred Shading |
Zitat: Wechsel ich die Auflösung auf 1680x1050 Du benutzt RGBA32F Texturen und davon 4 Stück, richtig? Dann ist jedes Fragment 64 Byte groß. Bei dieser Bildschirmauflösung erzeugst du so also 107 MB Daten. Das ganze kaust in jedem Frame zweimal durch (einmal schreiben, einmal lesen). Bei 45 fps erzeugst du also 9.4 GB/sek Speicherzugriffe. Ich hoffe das ist dir klar... => Versuche die Daten zu komprimieren! Tipps:
Zitat: Dabei besteht die Szene nur aus 2426 Vertices. Deferred Shading ist dafür gedacht wenn du komplexe Geometrie und gleichzeitig mehr Lichtquellen hast als du in einem Pass verarbeiten könntest. Die Idee ist das du nicht für jeden Pass die komplette Geometrie verarbeiten musst. Da deine Szene aber nun mit 2000 Vertices nicht wirklich komplex ist der Deferred Shading Ansatz natürlich eher kontraproduktiv. |
Seite 1 von 2 | Alle Zeiten sind UTC + 1 Stunde |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |