[OpenGL]Problem mit Schattenposition
-
Hey,
Ich kämpfe schon seit einer weile mit einem Problem bei der Schattenberechnung/erstellung und ich will einfach die Lösung nicht finden.
Die Schatten werden an sich zwar korrekt erstellt, jedoch später etwas versetzt auf die Karte gemappt. Ein Bild dazu gibt es am Ende.Ich versuche daher nun möglichst kompakt die Erstellung meiner Schatten zu erklären und hoffe einfach, dass jemand den Fehler sieht und mir helfen kann!
Zu Begin einfach erstmal eine Texture erstellen + FBO:
float cp[] = {1,1,1,1}; glGenTextures(1, &shadowdepth); glBindTexture(GL_TEXTURE_2D, shadowdepth); glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, ShadowMapSize, ShadowMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, cp); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowdepth, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
Außerdem wird schonmal die Projektionsmatrix erstellt:
glLoadIdentity(); glOrtho(-faktor1 * Window_x, faktor1 * Window_x, -faktor1 * Window_y, faktor1 * Window_y, 1000.0f, 10000.0f); glGetFloatv(GL_MODELVIEW_MATRIX, LightProjMatrix);
Dann die Shadowmap erstellen (leicht gekürzt aber alles entscheidene ist drin):
glColorMask(0, 0, 0, 0); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glLoadMatrixf(LightProjMatrix); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(Sun[0], Sun[1], Sun[2], x_change, y_change, z_change, 0.0f, 1.0f, 0.0f); glGetFloatv(GL_MODELVIEW_MATRIX, LightMatrix); glUseProgram(ShadowMapShader); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glActiveTexture(GL_TEXTURE0); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, ShadowMapSize, ShadowMapSize); // Render Objekte glBindFramebuffer(GL_FRAMEBUFFER, 0); glUseProgram(0); glViewport(0, 0, Window_x, Window_y); glDisable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glColorMask(1, 1, 1, 1);
Und noch die Finale Berechnung, bevor es in den Shader geht:
glUseProgram(ShadowShader); static float Bias[16] = { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f }; glMatrixMode(GL_TEXTURE); glActiveTexture(GL_TEXTURE1); glUniform1i(ShadowMap1, 1); glBindTexture(GL_TEXTURE_2D, shadowdepth); glLoadMatrixf(Bias); glMultMatrixf(LightProjMatrix); glMultMatrixf(LightMatrix);
So das war der C/C++ Code und nun kommen noch die Shader (relativ kurz gehalten).
Dieser Shader hat nur einen Fragment-Teil und benutze ich beim erstellen der Shadowmap:
uniform sampler2D Texture0; void main() { vec4 texel = texture2DProj(Texture0, gl_TexCoord[0]); if (texel.a < 0.1) discard; gl_FragColor = texel * gl_Color; }
Und hier die eigentlichen Shader.
Vertex:varying vec4 ShadowCoord; varying vec3 vertex_normal; varying vec3 vertex_light_position; void main() { ShadowCoord = gl_TextureMatrix[1] * gl_Vertex; vertex_normal = normalize(gl_NormalMatrix * gl_Normal); vertex_light_position = normalize(gl_LightSource[0].position.xyz); gl_TexCoord[0] = gl_MultiTexCoord0; gl_FrontColor = gl_Color; gl_Position = ftransform(); }
Fragment:
uniform sampler2DShadow ShadowMap; varying vec4 ShadowCoord; varying vec3 vertex_normal; varying vec3 vertex_light_position; void main() { float shadow=0.0, x, y; shadow = shadow2D(ShadowMap, vec3(ShadowCoord)).r; shadow += 0.3; float diffuse_value = max(dot(vertex_normal, vertex_light_position), 0.0) + 0.3; vec4 texel = texture2DProj(NormalMap, gl_TexCoord[0]); if (diffuse_value <= shadow) texel.rgb *= diffuse_value; else texel.rgb *= shadow; gl_FragColor = texel * gl_Color; }
Außerdem noch ein Bild vom Fehler:
http://abload.de/img/1f2psb.pngUnd das war es auch "schon".
Ich gebe zu es sind schon ein paar Zeilen Code aber ich würde mich wirklich sehr freuen, wenn sich mal jemand die Mühe macht und mal rüber schaut.
Sollte noch was fehlen, reiche ich das natürlich gerne nach.MfG
-
deine magischen 0.3 werte, koennten sie was damit zu tun haben?
-
Ich nehme an, du meinst den Fragment Shader?
Falls ja: Dadurch sind die Schatten nur nicht total schwarz. Wenn ich die 0.3 entferne sieht es wie folgt aus:
http://abload.de/img/1h5j39.png
-
da war ich zu schnell, das .r sah mir wie ein tiefenwert aus
mir faellt noch auf dass deine ortho tiefe von -1k bis +10k geht, deine bias matrix z mit 0.5 offsettet. eigentlich muestest du nur x und y skalieren und offsetten weil noch die viewport transformation draufgerechnet wird (viewport ist in x und y von -1 bis +1 waehrend texture space von 0 bis +1 ist), z sollte nicht modifiziert werden muessen, denke ich.
falls ich doch uebersehe weshalb es nun gerade diese z modifikation geben sollte, sollte sie auf die tiefen range von glortho mappen, oder glortho auf -10k bis +10k stellen?
-
Also der Wert bei der Near-Clippingplane ist doch positiv (1k) und nicht negativ (-1k). Würde ja bei den Planes auch nicht wirklich Sinn machen?
Kannst du mir denn sagen wie ich die Bias Matrix ändern muss, damit Z nicht mehr modizifiert wird?
-
Hm okay ich habe es jetzt mal wie folgt gemacht:
Statt dem Code hier:
glLoadMatrixf(Bias); glMultMatrixf(LightProjMatrix); glMultMatrixf(LightMatrix);
Einfach ohne Bias-Matrix laden und in den Shader:
glLoadMatrixf(LightProjMatrix); glMultMatrixf(LightMatrix);
Und im Shader dann quasi den Effekt der Biasmatrix erzeugt:
ShadowCoord.x = ShadowCoord.x * 0.5 + 0.5; ShadowCoord.y = ShadowCoord.y * 0.5 + 0.5; ShadowCoord.z = ShadowCoord.z * 0.5 + 0.5; ShadowCoord.w = ShadowCoord.w * 0.5 + 0.5;
Ich kann lediglich die Zeile mit .w auskommentieren damit es noch läuft, entferne ich .z, dann läuft nix mehr vernüftig.
-
Gibt wohl leider keine weiteren Ideen?!