2014-12-16 8 views
5

verschoben wird Ich möchte eine planetenähnliche Kugel darstellen. Die allgemeine Idee ist wie folgt:Analytische Normale zu einer Kugel, die mit Simplex Noise

  • Generieren Sie eine Reihe von Einheit Länge Vertices, die eine Kugel bilden.
  • Beim Rendern der Kugel wertet der Shader das 3D-Simplex-Rauschen am Punkt der Einheitskugel aus.
  • Das Ergebnis wird als "Höhe" verwendet, um den aktuellen Scheitelpunkt entlang seiner Richtung zu verschieben.

Bis hier funktioniert alles wie es soll.

Jetzt möchte ich Beleuchtung hinzufügen und daher Normalen auf der Oberfläche benötigen.

Während die Beleuchtung bezogenen Teile Umsetzung fügte ich schnell eine Methode der Normalen des Geländes mit partiellen Ableitungen im Fragment-Shader wie folgt zu ermitteln:

vec3 X = dFdx(ins.position); 
vec3 Y = dFdy(ins.position); 
vec3 normal = normalize(cross(X,Y)); 

wo ins.position ist die interpolierte Weltposition.

Während dies funktioniert, sieht es nicht sehr gut aus, weil es im Wesentlichen zu Normalen führt.

Bad normal approximation

Nun zu den eigentlichen Fragen:

  • Berechnung pro-Vertex-Normalen in glatten Normalen, anders als im Bild führen würde, nicht wahr?
  • Einer der Vorteile von Simplex Noise über Perlin Noise ist, dass es überall einen "klar definierten und kontinuierlichen Gradienten hat, der relativ günstig berechnet werden kann" (um den ausgezeichneten Simplex Noise demystified zu zitieren) und mit dem Gradienten, den man berechnen kann das normale, richtig?

Wenn die Sekunden Frage ist ein „Ja“ Ich habe zwei Probleme:

  • Der Simplex-Rausch-Algorithmus von einem popular source genommen wurde, die leider nicht die Gradientenberechnungssystems enthält. Ich werde meinen Versuch, es hinzuzufügen, unten veröffentlichen, aber ich habe keine Ahnung, ob es korrekt ist.
  • Selbst wenn ich den Gradienten hatte, bin ich fest davon ab, das normale von dort abzuleiten.

Jede Hilfe wird sehr geschätzt!

Mein Schuss auf der Gradienten-Implementierung (die letzten Zeilen von snoise ersetzt):

float snoise(vec3 v, out vec3 grad) 
{ 
    ...... 

    // Mix final noise value 
    vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 
    vec4 m2 = m * m; 
    vec4 m4 = m2 * m2; 

    vec4 pdotx = vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3)); 

    vec4 temp = m2 * m * pdotx; 
    grad = -8.0 * (temp.x * x0 + temp.y * x1 + temp.z * x2 + temp.w * x3); 
    grad += m4.x * p0 + m4.y * p1 + m4.z * p2 + m4.w * p3; 
    grad *= 42.0; 

    return 42.0 * dot(m4, pdotx); 
} 

UPDATE:

Der Teil über die Oberfläche normalen aus dem Gradienten der Berechnung wurde hier beantwortet: Surface normal to point on displaced sphere.

Die verbleibende Frage ist jetzt, wie man die Gradientenberechnung in die GLSL-Version des 3D Simplex Noise implementiert, weil meine Implementierung Probleme zu haben scheint.

UPDATE 2:

Die Gradientenberechnungssystems scheint fast Recht zu sein, scheint nur die Skalierung ausgeschaltet zu sein.
Anstatt mit 42 zu multiplizieren, gibt die Division durch 5 ziemlich gute Ergebnisse, aber das wurde durch Versuch und Irrtum herausgefunden. Ein richtiger Skalierungsfaktor wäre schön.

+0

Um Ihre erste Frage zu beantworten: ja und nein. Die Vertex-Normalen können glatt sein, wenn Sie Informationen über benachbarte Dreiecke haben, oder sie können flach sein, wenn Sie sie mit einem einzelnen Dreieck berechnen. Mit Geometrie-Shadern und einem Dreiecksstreifen mit Adjazenz können Sie bis zu 4 geteilte Dreiecke pro Vertex erhalten, was *** (wenn man bedenkt, dass * nicht * tatsächlich die Anzahl der Dreiecke ist, zu denen jeder Eckpunkt gehört) ausreicht Berechnen Sie eine ungefähre, glatte Per-Vertex-Norm. Sie müssen Ihre Eingabe-Vertex-Indizes in einer ganz bestimmten Reihenfolge strukturieren, um dies zu erreichen, und sie erfordert GL 3.2+. –

+0

Wenn ich das richtig verstanden habe, sind die resultierenden Normalen glatt, wenn die Normale für einen gegebenen Knoten gleich ist, egal welche Seite gerade bearbeitet wird. Angenommen, die Berechnung funktioniert so, wie ich es beschrieben habe, weil die Normalen nur von der Information des einzelnen Scheitelpunktes abhängen, zu dem sie gehören. – Gigo

+0

Nun, die (glatte) Vertex-Normale hängt von den anderen 2 Vertices in jedem Dreieck ab, das diesen Vertex teilt. Ich schaue auf dein Mesh und bemerke einige Scheitelpunkte mit bis zu 10 Dreiecken, die sich denselben Scheitelpunkt teilen. Wenn Sie diese Vertex-Normalen korrekt glätten möchten, müssten Sie die Gesichtsnormale für alle 10 dieser Dreiecke berechnen. Deshalb erscheint es nicht praktisch. –

Antwort

1

In Ordnung, stellt sich heraus, mein Problem war fast rein mathematisch verwandt.

Wenn jemand interessiert ist:
Die GLSL-Implementierung der Gradienten-Berechnung in der Frage geschrieben ist völlig richtig.
Berechnung der Normalen direkt aus dem Gradienten ist möglich wie beschrieben here.

Und das Ergebnis sieht genauso aus wie ich es sein wollte, ich bin glücklich;)

Smooth per-vertex normals