DGL https://delphigl.com/forum/ |
|
GLSL - Shader mit Lichtberechnungen funktionieren nicht https://delphigl.com/forum/viewtopic.php?f=20&t=9247 |
Seite 1 von 1 |
Autor: | Pk3 [ Sa Jun 05, 2010 16:34 ] |
Betreff des Beitrags: | GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Hi, ich habe es schon mit vielen Shadern - Programmen versucht, korrekte Lichtberechnungen durchzuführen. Jedoch ohne Erfolgt ![]() Lichteffekt verschoben oder schon garnicht mehr zu sehen. Ich verwende momentan folgende Shader: Vertex: Code: varying vec4 diffuse, ambient; varying vec3 normal, lightDir, halfVector; void main() { normal = normalize(gl_NormalMatrix * gl_Normal); lightDir = normalize(vec3(gl_LightSource[0].position)); halfVector = normalize(gl_LightSource[0].halfVector.xyz); diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse; ambient = gl_FrontMaterial.ambient * (gl_LightSource[0].ambient + gl_LightModel.ambient); gl_Position = ftransform(); } Fragment: Code: varying vec4 diffuse, ambient; varying vec3 normal, lightDir, halfVector; void main() { vec3 n, halfV, viewW, ldir; float NdotL, NdotHV; vec4 color = ambient; n = normalize(normal); NdotL = dot(n, lightDir); if(NdotL > 0.0) { halfV = normalize(halfVector); NdotHV = max(dot(n, halfV), 0.0); color += gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV, gl_FrontMaterial.shininess); color += diffuse * NdotL; } gl_FragColor = color; } Hier zur Verdeutlichung 2 Screenshots mit dem selben Shader nur aus 2 verschiedenen Positionen: http://xyross.de/download/xy1.jpg http://xyross.de/download/xy2.jpg Edit by Horazont: Bitte keine so großen Bilder direkt einfügen Woran liegt das ![]() Mfg, Pk3 ![]() |
Autor: | Coolcat [ Sa Jun 05, 2010 17:33 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Wie setzt du den die Position der Lichtquelle? Die Lichtquelle muss in den View-Space transformiert werden, da deine Normale ja durch gl_NormalMatrix ebenfalls dahin geschoben wird. Am besten setzt du den Lichtvektor nachdem du die Kamera mit gluLookAt gesetzt hast, dann sollte OpenGL sie automatisch richtig transformieren. gl_LightSource[0].halfVector hab ich noch nie benutzt, sicher das der richtig ist? Du kannst den auch via reflect(lightvec, normal) berechnen. lightvec muss dabei vom Fragment zum Licht zeigen. |
Autor: | Pk3 [ Sa Jun 05, 2010 17:42 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Ich verwende kein gluLookAt, sondern transformiere so: Code: void clRender::Lights(void) { int i; for(i = 0; i < MAX_LIGHTS; i++) { if(LightSystem.Light[i].lock == 1 && LightSystem.Light[i].enable == 1) { glLoadIdentity(); GLfloat position[] = { LightSystem.Light[i].Pos.X, LightSystem.Light[i].Pos.Y, LightSystem.Light[i].Pos.Z, 1.0f }; glRotatef(Camera.Angle.Y, 1.0f, 0.0f, 0.0f); glRotatef(360 - Camera.Angle.X, 0.0, 1.0f, 0.0f); glTranslatef(Camera.Pos.X, Camera.Pos.Y, Camera.Pos.Z); glLightfv(GL_LIGHT0+i, GL_POSITION, position); } } } Diese Funktion wird als allerstes bei jedem Rendervorgang ausgeführt. Das Licht wird ohne Shader auch fehlerfrei angezeigt, egal wie meine Kameraposition/rotation ist. |
Autor: | Pk3 [ So Jun 06, 2010 09:14 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Ich habe mal einen Shader aus eurer Shader - Sammlung ausprobiert - sieht schon besser aus ![]() Dieser: http://wiki.delphigl.com/index.php/shader_PerPixelLighting Nur funktioniert es bei mir leider nicht ganz so, wie es sein soll: http://xyross.de/download/xy3.jpg Wie man sieht ist das Licht rundlich abgehackt :/. Wenn ich meine Kamera weiter weg vom Licht bewege ist mehr vom Licht zu sehen (Radius ist groeßer). Wie beim Shader beschrieben habe ich auch das Licht mit glDisable(GL_LIGHTING) vor dem Aufruf dess Shaders deaktiviert. Scheinbar muss ich wohl die Lichtquellenposition im Shader mit einer Matrix multiplizieren. Aber wie und mit welcher? |
Autor: | Coolcat [ So Jun 06, 2010 10:16 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Zitat: Wie beim Shader beschrieben habe ich auch das Licht mit glDisable(GL_LIGHTING) vor dem Aufruf dess Shaders deaktiviert. Ähm, schalt das mal ein ![]() Zitat: Scheinbar muss ich wohl die Lichtquellenposition im Shader mit einer Matrix multiplizieren. Aber wie und mit welcher? gl_NormalMatrix müsste das für eine drektionale Lichtquelle sein. Anschließend das normalisieren nicht vergessen. |
Autor: | Pk3 [ So Jun 06, 2010 10:26 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Vertex - Shader: Code: varying vec3 v; varying vec3 lightvec; varying vec3 normal; varying vec4 FrontColor; void main(void) { normal = normalize(gl_NormalMatrix * gl_Normal); v = vec3(gl_ModelViewMatrix * gl_Vertex); // ##### G E Ä N D E R T ##### vec3 lightPos = gl_NormalMatrix * gl_LightSource[0].position.xyz; lightvec = normalize(lightPos.xyz - v); // ####################### gl_TexCoord[0] = gl_MultiTexCoord0; FrontColor = gl_Color; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } Soll das so aussehen? Sorry, ich bin noch ziemlich neu in der Shader - Programmierung. Will einfach nur das das mit der Lichtposition richtig hinhaut, denn ohne Licht kann man nicht gerade die besten Shadereffekte erzielen ![]() Also leider klappts immer noch nicht. Hab das OpenGL - Licht auch aktiviert, aber jetzt verfolgt mich das Licht.... Also es is so, dass das Licht zwar abgeschwächt wird je weiter man sich von der Lichtquellenposition entfernt, aber das Licht ist nur in einem bestimmten Radius um die Kameraposition sichtbar, und der Licht - Radius wird immer groeßer, je weiter ich mich von der Lichtposition entferne. Hoffe du verstehst, was ich meine ![]() |
Autor: | Pk3 [ So Jun 06, 2010 12:20 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Ich hab jetzt mal ein bisschen rumprobiert und habe festgestellt, das es garnix mit der Lichtposition zutun hat: Fragment - Shader: Code: varying vec3 v; varying vec3 lightvec; varying vec3 normal; varying vec4 FrontColor; uniform sampler2D Texture0; void main(void) { vec3 Eye = normalize(-v); vec3 Reflected = normalize(reflect(-lightvec, normal)); vec4 IAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient; vec4 IDiffuse = gl_LightSource[0].diffuse * dot(normal, lightvec) * gl_FrontMaterial.diffuse; // ### H I E R ### vec4 ISpecular = gl_LightSource[0].specular * pow(dot(Reflected, Eye), gl_FrontMaterial.shininess) * gl_FrontMaterial.specular; // ############ gl_FragColor = vec4((gl_FrontLightModelProduct.sceneColor + IAmbient + IDiffuse) * texture2D(Texture0, vec2(gl_TexCoord[0])) + ISpecular) + vec4(0,0,0,1); } Wenn ich statts der pow(...) - Funktion z.B. den Wert "1" eintrage, klappt alles wunderbar (Licht wird korrekt dargestellt, auch wenn ich glDisable(GL_LIGHTING); verwende). Eigentlich ist das dann aber nicht korrekt, weil der Specular - Wert immer der selbe ist. Komischerweise sieht man da aber keinen Unterschied ob Specular jetzt 0 oder nen Maximalwert hat... Jetzt is es aber ganz klar wo der Fehler liegt: Fragment - Shader: Code: vec3 Eye = normalize(-v); vec3 Reflected = normalize(reflect(-lightvec, normal)); Im Vertex - Shader sind die Variablen wie folgt: Code: normal = normalize(gl_NormalMatrix * gl_Normal); v = vec3(gl_ModelViewMatrix * gl_Vertex); vec3 aux; vec3 ecPos; ecPos = gl_ModelViewMatrix * gl_Vertex; aux = vec3(gl_LightSource[0].position - ecPos); lightvec = normalize(aux); Weißt du vielleicht, wie das richtig sein soll? Wie gesagt, ich transformiere ohne gluLookAt, sondern z.B. so: Code: GLfloat position[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glLoadIdentity(); glRotatef(Camera.Angle.Y, 1.0f, 0.0f, 0.0f); glRotatef(360 - Camera.Angle.X, 0.0, 1.0f, 0.0f); glTranslatef(Camera.Pos.X + Licht.Pos.X, Camera.Pos.Y + Licht.Pos.Y, Camera.Pos.Z + Licht.Pos.Z); glLightfv(GL_LIGHT0+i, GL_POSITION, position); |
Autor: | Coolcat [ So Jun 06, 2010 21:07 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Zitat: Also es is so, dass das Licht zwar abgeschwächt wird je weiter man sich von der Lichtquellenposition entfernt, aber das Licht ist nur in einem bestimmten Radius um die Kameraposition sichtbar, und der Licht - Radius wird immer groeßer, je weiter ich mich von der Lichtposition entferne. Hoffe du verstehst, was ich meine ![]() Da dürfte dein Problem liegen. Der Shader ist für eine direktionale Lichtquelle, offensichtlich gibst du ihm aber eine Position wie für eine Punktlichtquelle ![]() Im Fall einer Punktlichtquelle musst du den Vektor von der Fragmentposition zur Lichtquelle berechnen. Zitat: Jetzt is es aber ganz klar wo der Fehler liegt: Ja, siehe oben. Aus "-lightvec" muss dann ggf. auch einfach "lightvec" werden....wie gesagt bei mir ist lightvec die Richtung in die die direktionale Lichtquelle scheint. |
Autor: | Pk3 [ Mo Jun 07, 2010 15:00 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Also muss ich einfach nur die Direction von der Lichtquelle zum Fragment berechnen ?: Code: vec3 Reflected = normalize(reflect(lightDir, normal)); Wenn ja wie ![]() |
Autor: | Coolcat [ Mo Jun 07, 2010 15:17 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Du nimmst dir die Position vom Vertexshader und reichst sie dann an den Fragmentshader weiter. Vertexshader: Code: // ... varying vec3 position; void main() { // ... position = vec3(gl_ModelViewMatrix * gl_Vertex); // ... } Fragmentshader: Code: varying vec3 position;
void main() { vec3 lightvec = normalize(gl_LightSource[0].position.xyz - position); // ... } |
Autor: | Pk3 [ Mo Jun 07, 2010 15:36 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Thx, aber das hab ich ja gehabt, aber ich brauch ja den Richtungswinkel, weil ich kein Directionslicht sondern ein Punktlich habe. Vertex: Code: varying vec3 pos; varying vec3 normal; varying vec4 color; varying vec3 lightDistance; void main(void) { normal = normalize(gl_NormalMatrix * gl_Normal); pos = vec3(gl_ModelViewMatrix * gl_Vertex); lightDistance = normalize(gl_LightSource[0].position - pos); color = gl_Color; gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } Fragment: Code: varying vec3 pos;
varying vec3 lightDistance; varying vec3 normal; varying vec4 color; uniform sampler2D Texture0; void main(void) { vec3 Eye = normalize(-pos); vec3 Reflected = normalize(reflect(lightDistance, normal)); vec4 IAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient; vec4 IDiffuse = gl_LightSource[0].diffuse * dot(normal, lightDistance) * gl_FrontMaterial.diffuse; vec4 ISpecular = gl_LightSource[0].specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess) * gl_FrontMaterial.specular; gl_FragColor = vec4((gl_FrontLightModelProduct.sceneColor + IAmbient + IDiffuse) * texture2D(Texture0, vec2(gl_TexCoord[0])) + ISpecular); gl_FragColor.w = 1.0; } |
Autor: | Coolcat [ Mo Jun 07, 2010 16:41 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Zitat: Thx, aber das hab ich ja gehabt, aber ich brauch ja den Richtungswinkel, weil ich kein Directionslicht sondern ein Punktlich habe. Ups...hab ich irgendwie nicht gesehen. Jedenfalls damit das korrekt ist musst du den Lichtvektor im Fragmentshader berechnen, sonst könnte es Helligkeitsschwankungen geben, weil die Länge des Lichtvektors variiert. Auch könnte es Probleme bei der Interpolation geben wenn die Lichtquelle sehr nahe an deinem Dreieck bzw. das Dreieck sehr groß ist. Diese ganzen Effekte treten nur auf, wenn du Vektoren interpolierst => darum die Position interpolieren. Wenn du den Lichtvektor einmal hast berechnet sich der Richtungswinkel (*) beim Punktlicht genauso wie beim Direktionslicht, also dot-Produkt. (*) Streng genommen berechnest du hier nicht den Winkel sondern nur den Kosinus desselben. |
Autor: | Pk3 [ Mo Jun 07, 2010 18:16 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
So, hoffe dass das jetzt die letzte Frage von mir is ![]() Fragment: Code: varying vec3 pos;
varying vec3 normal; varying vec4 color; uniform sampler2D Texture0; void main(void) { vec3 lightDistance = normalize(gl_LightSource[0].position - pos); vec3 dir = dot(normalize(pos), lightDistance); vec3 Eye = normalize(-pos); vec3 Reflected = normalize(reflect(-dir, normal)); vec4 IAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient; vec4 IDiffuse = gl_LightSource[0].diffuse * dot(normal, lightDistance) * gl_FrontMaterial.diffuse; vec4 ISpecular = gl_LightSource[0].specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess) * gl_FrontMaterial.specular; gl_FragColor = vec4((gl_FrontLightModelProduct.sceneColor + IAmbient + IDiffuse) * texture2D(Texture0, vec2(gl_TexCoord[0])) + ISpecular); gl_FragColor.w = 1.0; } |
Autor: | Coolcat [ Mo Jun 07, 2010 18:58 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Ich würd sagen sieht richtig aus, aber siehe meine Signatur ![]() |
Autor: | damadmax [ Mo Jun 07, 2010 20:01 ] |
Betreff des Beitrags: | Re: GLSL - Shader mit Lichtberechnungen funktionieren nicht |
Hi, du solltest im Fragment-Shader noch die Normale normalisieren. Nebenbei: Varyings setze ich in der Regel immer ein V voraus. Damit ich immer gleich sehe woher die Variable kommt. Also etwas wie: Code: vec3 normal = normalize(vNormal);
|
Seite 1 von 1 | Alle Zeiten sind UTC + 1 Stunde |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |