Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

1

29.03.2014, 13:57

OpenGL Deferred Shading

Hallo,

ich habe wieder einmal das Problem dass ich nicht weiß in welchem space sich meine Daten befinden.
Aktuell wird die Lichtquelle mitgedreht:


(Link)


Die 4 Texturen unten sind Weltkoordinaten, diffuse, Normalen und depth.
Die Lichtquelle befindet sich bei 1|0|0, sollte also wenn ich aus dieser Perspektive schaue eigentlich nicht aus 90° von rechts kommen.

Versucht habe ich bis jetzt Kamera und Lichtposition mit der invertierten transponierten ProjectionView Matrix umzurechnen (also nicht gleichzeitig natürlich). Also transponieren(invertieren(P*V)), hat aber nicht geholfen.

So kommen die Daten in die Texturen (Vertexshader):

Quellcode

1
2
3
4
5
6
void main(){
    position = vec3(pmv*vec4(vertex0, 1.0)); // pmv = ProjectionModelView
    normal = vec3(normalPmv*vec4(normal0, 1.0)); // invertierte, transponierte pmv
    texCoord = texCoord0;
    gl_Position = pmv*vec4(vertex0, 1.0);
}


Und so wird aktuell gerechnet:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void main(){
    vec3 p = texture(position, vertex).xyz; // vertex = Koordinate eines Quads für den rasterizer
    vec3 n = normalize(texture(normal, vertex)).xyz;
        
    vec4 color = 0.5*texture(diffuse, vertex); // 0.5 ist nur ein Testwert
    
    // directional light
    vec3 l = normalize(light0.position);
    float ndotl = max(dot(n, l), 0.0);
    
    if(ndotl > 0.0){
        vec3 h = normalize(-camera-l); // halfway vector
        float ndoth = max(dot(n, h), 0.0);
        
        color += light0.diffuse*ndotl+light0.specular*pow(ndoth, mat0.shininess);
    }
    
    gl_FragColor = color;
}


Hierbei sind Licht- und Kameraposition in Weltkoordinaten (also unverändert).

Dann Frage ich mich auch noch wo ich überhaupt die Materialeigenschaften einbringen soll.
Render ich die in noch mehr Texturen für später, oder wie wird das gemacht?

Ich hätte ansonsten auch noch ein paar mehr Fragen, aber das hier wäre erstmal das wichtigste...

Wer übrigens alles einsehen will kann dies hier tun. Aktuell wird alles in states/Playing.cpp gemacht. Die Shader liegen in BurningByte/shader.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DeKugelschieber« (29.03.2014, 14:12)


Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

2

29.03.2014, 14:15

Ich weiß nicht, im Kommentar schreibst du directional light und benutzt es auch so, von daher bin ich gerade nicht überrascht, dass das Licht aus +X Richtung kommt?
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

3

29.03.2014, 14:26

Guck mal auf die Kugel, diese wird senkrecht durch das einfallende Licht halbiert. Und dies sollte nicht auf der Hälfte sein.
Ich kann drehen wie ich will das Licht kommt immer von rechts. Auch wenn ich die Position der Lichtquelle wie oben beschrieben umrechne.


(Link)


Nochmal: versucht habe ich folgendes:

C-/C++-Quelltext

1
shader->sendUniform4x4("normalPmv", (camera->projectionMatrix*camera->viewMatrix).inverse().transpose().getArray());


Und diese Matrix dann mit der Kamera und Lichtposition multipliziert (alle Möglichkeiten durch).
Da kommt entweder das selbe, oder Schrott raus.
Auf der CPU hab ichs auch schon versucht.

Mir ist relativ klar warum es nicht passt, aber wenn ich die Licht und/oder Kameraposition in den gleichen Space wie die Normalen umrechne sollte die Berechnung doch stimmen oder!?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »DeKugelschieber« (30.03.2014, 00:04)


DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

4

30.03.2014, 11:13

Ich bekomms nicht hin die Lichtposition in den passenden space umzurechnen.

Ich hab jetzt erstmal auf Weltkoordinaten umgestellt, also ich rechne die Normalen so:

Quellcode

1
2
3
4
5
6
void main(){
    position = vec3(mv*vec4(vertex0, 1.0));
    normal = vec3(normalMv*vec4(normal0, 0.0)); // da view*model Matrix (invertiert, transponiert)
    texCoord = texCoord0;
    gl_Position = p*mv*vec4(vertex0, 1.0);
}


Wenn ich die Lichtrichtung dann mit der inversen transponierten view Matrix multipliziere sieht das so aus:



Wenn ich dies nicht tue dreht sie mit:



Der Shader für beide sieht so aus, mit unterschied bei "ndotl":

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#version 330

precision highp float;

struct DirLight{
    vec3 direction;
    vec4 diffuse, specular;
};

uniform sampler2D position;
uniform sampler2D diffuse;
uniform sampler2D normal;

uniform mat4 inverseView;

DirLight light0 = DirLight(vec3(1, 0, 0), vec4(0.0), vec4(0.0));

in vec2 vertex;

void main(){
    vec3 n = normalize(texture(normal, vertex)).xyz;
    vec4 color = texture(diffuse, vertex)*0.5;
    
    float ndotl = max(dot(n, normalize(light0.direction)), 0.0); // ohne view
        float ndotl = max(dot(n, normalize(inverseView*vec4(light0.direction, 0.0)).xyz), 0.0); // mit view
    
    if(ndotl > 0.0){
        color += vec4(ndotl);
    }
    
    gl_FragColor = color;
}


Ich versteh das einfach nicht, was mache ich da ständig falsch?

[Edit] Ach mist ich hab doppelt invertiert, trotzdem sieht es ähnlich aus wie im ersten Video, nur etwas schwächer. Die Beleuchtung verschwindet auch einfach ab einem bestimmten Winkel (hinter der Kugel).

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

5

30.03.2014, 11:42

Das Licht ist üblicherweise in WorldSpace definiert. Davon sprichst du auch, wenn ich dich richtig verstanden habe. Dementsprechend musst du die Normalen auch in den WorldSpace transformieren. Das inverse-transponierte ist nur dann unbedingt notwendig, wenn du non-uniform-skalierung auf die Objekte anwendest. Dann sollte alles korrekt sein. View und Projektion spielen für Beleuchtung dabei überhaupt keine Rolle, besonders beim stinknormalen Diffuse Shading.

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

6

30.03.2014, 12:13

Verdammt, ich habs an der falschen Stelle probiert :(
Ich wollte eigentlich den Lichtvektor dann in den ModelViewSpace bringen. Was solls, so gehts auch.

Also ich rechne jetzt für die Normalen invertierte transponierte Model Matrix * Normale und komme auf den WorldSpace dieser. Tada, ja klappt, dreht nicht mehr mit.

Vielen Dank.

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

7

01.04.2014, 14:50

Hmm zu früh gefreut.

Wenn ich meinen FBO Texturen mit denen von diesem Tutorial vergleiche, sieht die Position- und Normalentextur ganz anders aus, obwohl in diesem Tutorial angeblich auch im worldspace gearbeitet wird. Soweit ich das sehen kann wird in der "pipeline.cpp" des Quellcodes dort auch nur eine normale Modelmatrix aufgesetzt.
Übrigens werden dort auch die Normalen mit der Modelmatrix multipliziert, ich nehme die invertierte.

Jetzt hab ich das Problem, dass ich einmal Streifen auf den Objekten habe, hier an der Kugel deutlich sichtbar:


(Link)


Und dass Lichtquellen mit negativer Position (hier Punktlicht -2|-2|1) sich kaum oder gar nicht auswirken (garnicht z.B. für das directional):


(Link)


Die Daten kommen so in die Texturen:

Quellcode

1
2
3
4
position = vec3(m*vec4(vertex0, 1.0));
normal = vec3(normalM*vec4(normal0, 0.0));
texCoord = texCoord0;
gl_Position = pmv*vec4(vertex0, 1.0);

Also eigentlich alles im worldspace, oder nicht?

Die Lichtberechnung selbst ist dann auch sehr simpel (die Lichtposition ist hardcoded im Shader):

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vec4 point(vec4 color, vec3 p, vec3 n, PointLight pl){ // Ausgangsfarbe, Position, Normale, Punktlicht
    float ndotl = max(dot(n, normalize(pl.position-p)), 0.0);
    
    if(ndotl > 0.0){
        float ndoth = max(dot(n, (normalize(camera-p)+normalize(pl.position-p))), 0.0);
        float distance = length(p-pl.position);
        float attenuation = 1.0/(pl.constantAttenuation+pl.linearAttenuation*distance+pl.quadraticAttenuation*distance*distance);
        
        color += light0.diffuse*ndotl*attenuation+pl.specular*pow(ndoth, 6)*attenuation; // 6 = fixer Testwert
    }
    
    return color;
}

void main(){
    vec3 p = vec3(texture(position, vertex));
    vec3 n = vec3(normalize(texture(normal, vertex)));
    
    vec4 color = texture(diffuse, vertex)*0.5; // 0.5 = fixer Testwert
    color = point(color, p, n, light1); // Punktlicht berechnen
    
    gl_FragColor = color;
}

Sehr merkwürdig das alles...

Was übrigens schon sehr nahe dran kommt ist folgendes beim Aufsetzen der Texturen. Allerdings nur für das directional:

C-/C++-Quelltext

1
2
shader->sendUniform4x4("pmv", (camera->projectionMatrix*camera->viewMatrix*object->modelMatrix).getArray()); // projection*view*model
shader->sendUniform4x4("normalPm", (camera->projectionMatrix*object->modelMatrix).inverse().transpose().getArray()); // transpose(inverse(projection*model))



(Link)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DeKugelschieber« (01.04.2014, 15:15)


Sc4v

Alter Hase

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

8

01.04.2014, 17:36

Mh also ich finde deine Normale irgendwie strange. Wenn die Normale in Worldspace wäre, dass müsste die Schachbrett Ebene grün sein (RGB = XYZ).
Deine World position sieht korrekt aus.

Normale mit der transponierten inversen der ModelView-Matrix (nicht Projektion!)

Zitat

Und dass Lichtquellen mit negativer Position (hier Punktlicht -2|-2|1) sich kaum oder gar nicht auswirken (garnicht z.B. für das directional):


Die Position hat auch keinen Einfluss auf directional Light ;)

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

9

01.04.2014, 19:01

Zitat

Die Position hat auch keinen Einfluss auf directional Light

Ja sorry, ich mein natürlich die Richtung. Aber für das point light schon ;)

Zitat

dass müsste die Schachbrett Ebene grün sein (RGB = XYZ).

Nicht unbedingt, ich hab die z-Achse als Hochachse. Vielleicht hängt das ganze Dilemma ja auch damit zusammen? :P

Sc4v

Alter Hase

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

10

01.04.2014, 20:04

Nicht unbedingt, ich hab die z-Achse als Hochachse. Vielleicht hängt das ganze Dilemma ja auch damit zusammen? :P


Was hat dich denn dazu bewegt? ^^

Werbeanzeige