2012-03-25 10 views
4

Im Rahmen eines Versuchs, einen sehr einfachen aussehenden Himmel zu erzeugen, hat ich eine Skybox erstellt habe (im Grunde ein Würfel geht aus (-1, -1, -1) bis (1, 1, 1), die nach dem all meinen Geometrie und gezwungen, nach hinten über den folgenden einfachen Vertex-Shader gezogen wird:einfache Verfahren Skybox

#version 330 
layout(location = 0) in vec4 position; 
layout(location = 1) in vec4 normal; 

out Data 
{ 
    vec4 eyespace_position; 
    vec4 eyespace_normal; 
    vec4 worldspace_position; 
    vec4 raw_position; 
} vtx_data; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 

void main() 
{ 
    mat4 view_without_translation = view; 
    view_without_translation[3][0] = 0.0f; 
    view_without_translation[3][1] = 0.0f; 
    view_without_translation[3][2] = 0.0f; 

    vtx_data.raw_position = position; 
    vtx_data.worldspace_position = model * position; 
    vtx_data.eyespace_position = view_without_translation * vtx_data.worldspace_position; 

    gl_Position = (projection * vtx_data.eyespace_position).xyww; 
} 

Daraus ich versuche, meinen Himmel Anzeige als eine sehr einfache Gradienten von einem tiefen blau auf dem haben oben auf einem helleren Blau am Horizont.

Offensichtlich wird das Mischen meiner zwei Farben, die auf der Y-Koordinate jedes Fragments basieren, sehr schlecht aussehen: die Tatsache, dass Sie eine Kiste und nicht eine Kuppel betrachten sofort säubern r, wie hier zu sehen:

wrong skybox

Beachten Sie die ziemlich sichtbar „Ecken“ in der oberen linken und oberen rechten Ecke der Box.

Instinktiv dachte ich, dass die offensichtliche fix die Position jedes Fragment normalisieren würde, eine Position auf einer Einheitskugel zu erhalten, dann die Y-Koordinate, daß. Ich dachte, dass in einem Wert führen würde, die für eine gegebene „Höhe“ konstant sein würde, wenn der Sinn macht. Wie folgt aus:

#version 330 
in Data 
{ 
    vec4 eyespace_position; 
    vec4 eyespace_normal; 
    vec4 worldspace_position; 
    vec4 raw_position; 
} vtx_data; 

out vec4 outputColor; 

const vec4 skytop = vec4(0.0f, 0.0f, 1.0f, 1.0f); 
const vec4 skyhorizon = vec4(0.3294f, 0.92157f, 1.0f, 1.0f); 

void main() 
{ 
    vec4 pointOnSphere = normalize(vtx_data.worldspace_position); 
    float a = pointOnSphere.y; 
    outputColor = mix(skyhorizon, skytop, a); 
} 

Das Ergebnis jedoch ist sehr ähnlich wie der erste Screenshot (ich kann es schreiben, wenn nötig, aber da es mit dem ersten optisch ähnlich ist, ich bin das Überspringen es um diese Frage zu verkürzen jetzt).

Nach einiger zufälligen Hantieren (Cargo-Kult-Programmierung, ich weiß: /), wurde mir klar, dass dies funktioniert:

void main() 
{ 
    vec3 pointOnSphere = normalize(vtx_data.worldspace_position.xyz); 
    float a = pointOnSphere.y; 
    outputColor = mix(skyhorizon, skytop, a); 
} 

Der einzige Unterschied ist, dass ich die Position normalisieren, ohne es zu W-Komponente ist.

Und hier ist das Arbeitsergebnis: (der Unterschied in Screenshots subtil, aber deutlich spürbar in Bewegung) correct skybox

So, endlich, meine Frage: warum diese Arbeit nicht, wenn die vorherige Version nicht funktioniert? Ich muss etwas extrem Grundlegendes über homogene Koordinaten falsch verstehen, aber mein Gehirn klickt gerade nicht gerade!

Antwort

3

GLSL normalize nicht homogen ist behandeln Koordinaten per se. Er interpretiert die Koordinate als R^4. Dies ist im Allgemeinen nicht das, was Sie wollen. Wenn jedoch vtx_data.worldspace_position.w == 0, dann sollte das Normalisieren das gleiche Ergebnis.

Ich weiß nicht, was vec3 pointOnSphere = normalize(vtx_data.worldspace_position); bedeutet, weil die linke Seite sollte Typ vec4 auch haben.

+0

vec3 pointOnSphere = normalisieren (vtx_data.worldspace_position) ist ein Tippfehler meinerseits mit dem Code während fidling die Screenshots für diese Frage zu generieren: o Entschuldigen Sie! Und danke für die Antwort! –