2015-05-14 17 views
5

Wenn ich die Größe oder Position eines Objekts in WebGL ändern möchte, nehme ich die ursprünglichen Vertexdaten {x, y, z} dieses Objekts und übergebe es an den Vertex-Shader, wo es mit einer Matrix multipliziert wird. das enthält die Informationen über die Transformationen, was zu einer neuen Menge von Koordinaten führt, die nur meiner GPU bekannt ist, aber für mich unsichtbar ist.Wie transformieren Sie Vertices, ohne das Format zu ändern?

Das funktioniert gut, soweit das einzige, was zählt, ist das Bild auf dem Bildschirm, aber ich möchte in der Lage sein, die transformierten Ecken ohne zusätzliche Informationen über Matrix Multiplikationen zu speichern, einfach als x, y, z- Werte, genau wie die Originaldaten.

Die Idee war, den letzten Schritt der Multiplikation der Transformationsmatrix mit den ursprünglichen Vertexdaten durch meine eigene in JavaScript zu machen, aber ich bekomme es einfach nicht funktionieren!

Ich schrieb die folgende Funktion, um eine 4x4-Matrix mit einer Vielzahl von x, y, z-Werten zu multiplizieren, um einen vierten Wert Hinzufügen {1,0} die vec3-Daten in vec4-Daten zu ändern ...

function matrixVectorProduct (mat4, data) { 

    var result = new Array(); 

    for (var i = 0; i < data.length/3; i++) { 

    var n = i * 3; 

    var vec4 = [data[n], data[n + 1], data[n + 2], 1.0]; 

    var x = mat4[0] * vec4[0] + mat4[1] * vec4[1] + 
      mat4[2] * vec4[2] + mat4[3] * vec4[3]; 

    var y = mat4[4] * vec4[0] + mat4[5] * vec4[1] + 
      mat4[6] * vec4[2] + mat4[7] * vec4[3]; 

    var z = mat4[8] * vec4[0] + mat4[9] * vec4[1] + 
      mat4[10] * vec4[2] + mat4[11] * vec4[3]; 

    var w = mat4[12] * vec4[0] + mat4[13] * vec4[1] + 
      mat4[14] * vec4[2] + mat4[15] * vec4[3]; 

    result.push(x, y, z, w); 

    } 

    return result; 

} 

... aber neben der Tatsache, dass ich keine Ahnung, wie haben die vec4-Werte wieder auf vec3-Werte zu konvertieren, muss es etwas falsch mit dem Konzept als Ganzes:

die wir annehmen lassen haben die Ecken für ein einfaches Dreieck wie

var vertices = [0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0]; 

und wir eine 4x4-Matrix mit

function createMat4 () { 

    var mat4 = new Float32Array(16); 

    mat4[0] = 1; mat4[1] = 0; mat4[2] = 0; mat4[3] = 0; 
    mat4[4] = 0; mat4[5] = 1; mat4[6] = 0; mat4[7] = 0; 
    mat4[8] = 0; mat4[9] = 0; mat4[10] = 1; mat4[11] = 0; 
    mat4[12] = 0; mat4[13] = 0; mat4[14] = 0; mat4[15] = 1; 

    return mat4; 

} 

übersetzen sie durch erstellen - sagen wir mal [0, 0, -5] - Mit dieser Funktion

function translateMat4 (mat4, vec3) { 

    var x = vec3[0], 
     y = vec3[1], 
     z = vec3[2]; 

    var a = mat4; 

    mat4[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; 
    mat4[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; 
    mat4[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; 
    mat4[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; 

    return mat4; 

} 

und schließlich die erstellt und übersetzt Matrix multiplizieren mit den in vertices gespeicherten Vertex-Daten unter Verwendung der matrixVectorProduct -function oben erwähnt, soll das Ergebnis

translatedVertices = [0.0, 1.0, -5.0, -1.0, -1.0, -5.0, 1.0, -1.0, -5.0]; 

sein, aber es ist nur [x, y, z, 1], weil -5 x 0.0 (z-Wert) gleich 0 ist, also kann es nicht so funktionieren.

Was mache ich falsch?

+0

„* Ich habe keine Ahnung, wie die vec4-Werte zurück zu vec3 konvertieren *“ Sie benötigen eine Vektor zu teilen, indem er w, diese implizit in Shadern gemacht wird. –

+0

@ LJ_1102 Moin und danke für die Info!Wie Entity Black sagte, muss ich jeweils separate Funktionen schreiben, um den Übersetzungs-/Dreh-/Skalenmatrix-Inhalt in Vertex-Daten umzuwandeln ... –

+0

Nun, vielleicht verstehe ich nicht, worauf Sie abzielen, aber Sie Sicherlich müssen Sie Ihre Matrixtransformationen nicht zerlegen, um sie auf einen Stützpunkt anzuwenden. Vielleicht werfen Sie einen Blick auf die Implementierung von [vec3.transformMat4] (https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/vec3.js#L496) (die Übersetzung wird in der Zeile angewendet) 498). Es gibt nichts "Magisch" innerhalb von Shadern außer dem [Perspektive teilen] (http://www.learnopengles.com/tag/perspective-divide/) für 'gl_Position'. –

Antwort

1

Sie sind sehr nah dran. Ich werde es von Anfang an implementieren, nur für den Fall.

Ermöglicht ein einfaches Modell Dreieck mit den Eckpunkten haben:

var triangleVertices = [ 0.0, 1.0, 0.0, 
         -1.0, -1.0, 0.0, 
         1.0, -1.0, 0.0 ]; 

Jetzt erstellen wir eine MAT4, die alle Transformationen auf diesem Modell fertig stellen. Keine Transformation wird durch eine Identitätsmatrix dargestellt, die alle 0 ist, aber 1 auf Diagonale.

Wir sind bereit, Übersetzungen, Rotationen oder Maßstab zu machen. Der beste Weg, sie auf das Modell anzuwenden, ist, eine andere mat4 zu erstellen, die unsere gewünschte Transformation darstellt, und dann die Modellmatrix mit der Transformationsmatrix zu multiplizieren. Auf diese Weise können wir mehrere Transformationen in der gewünschten Reihenfolge mit nur wenigen Matrixoperationen durchführen, und wir müssen uns erst einmal nicht mit Knoten beschäftigen.

So lassen Sie Übersetzungsmatrix erstellen, die am einfachsten ist. Sie beginnen mit der Identitätsmatrix, und Sie müssen nur die mat [12, 13, 14] ändern, also x, y, z.

übersetzen sie von - sagen wir mal [0, 0, -5] - Mit dieser Funktion

var translate = [ 1.0, 0.0, 0.0, 0.0, 
        0.0, 1.0, 0.0, 0.0, 
        0.0, 0.0, 1.0, 0.0, 
        0.0, 0.0,-5.0, 1.0 ]; 

Transformation Matrix erfolgt, und wir wollen sie mit unserer Modellmatrix multiplizieren. Multiplikationsmatrizen ist die Transformation, jede Transformation. Funktion für Matrixmultiplikation habe ich gerade gemacht. Es sollte funktionieren Ich hoffe :) Math source from wiki.

var mat4Multiply = (function() { 

    function ABProduct(i, j, a, b) { 
     var k, sum = 0; 
     for (k = 0; k < 4; k++) { 
      sum += a[i * 4 + k] * b[j + k * 4]; 
     } 
     return sum; 
    } 

    function mat4Multiply(a, b) { 
     var i, j, product = []; 

     for (i = 0; i < 4; i++) { 
      for (j = 0; j < 4; j++) { 
       product[i * 4 + j] = ABProduct(i, j, a, b); 
      } 
     } 

     return product; 
    } 

    return mat4Multiply; 
})(); 
// a = model matrix, b = transformation 

Nur um zu zeigen, wie die Multiplikation, kurzen Code zu tun:

modelMatrix = mat4Multiply(modelMatrix, translate); 

// but now I change my mind and I want to move model again by another 3 in Z 
translate = [ 1.0, 0.0, 0.0, 0.0, 
       0.0, 1.0, 0.0, 0.0, 
       0.0, 0.0, 1.0, 0.0, 
       0.0, 0.0, 3.0, 1.0 ]; 

modelMatrix = mat4Multiply(modelMatrix, translate); 
// after this content of the modelMatrix is: 
// [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -2, 1] 

Nun müssen wir die endgültige Transformation von Eckpunkten nur tun. Wie gesagt, Übersetzung ist die einfachste Transformation, daher werde ich nur die Übersetzungsfunktion this is related article from wiki übernehmen.

HINWEIS

Dont verwirrt dieses Bild: enter image description here

Dies war die Darstellung in OpenGL verwendet, aber später haben wir uns entschlossen umgesetzt Version der Matrix zu verwenden, wich ist eine einfache Bedienung auf folgendes Bild:

http://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Matrix_transpose.gif/200px-Matrix_transpose.gif

Endnote

Übersetzungsfunktion:

function vec3TranslateMat4(vec, mat4) { 
    vec[0] += mat4[12]; 
    vec[1] += mat4[13]; 
    vec[2] += mat4[14]; 
    return vec; 
} 

Um Dreieckvertices zu übersetzen Sie müssen nur tun:

var i, vertex; 
for(i=0;i<triangleVertices.length;i+=3) { 
    vertex = triangleVertices.slice(i, i+3); 
    vertex = vec3TranslateMat4(vertex, modelMatrix) 
    triangleVertices[i] = vertex[0]; 
    triangleVertices[i+1] = vertex[1]; 
    triangleVertices[i+2] = vertex[2]; 
} 

Sobald wir Transformations-Matrix angewendet wird, sollten wir wieder Modellmatrix auf Einheitsmatrix eingestellt. Danach können wir neue Transformationen, aber auf modifizierten Scheitelpunkten durchführen.

Und wir sind fertig. Persönlich verwende ich gl matrix library, die bereits alle Operationen für Matrizen und Vektoren enthält, die ich brauche.

Transformationen mit und ohne Matrizen

Alle Transformationen auch ohne Matrizen getan werden könnte. Aber die Matrix erlaubt uns, den aktuellen Ort in einer Variablen zu halten, ohne dass wir die Knoten sofort transformieren müssen. Vertex-Transformationen sind lang und zeitaufwendig.

Ein weiterer guter Grund ist, dass Sie mit nur wenigen Kernfunktionen, mat4Multiply und vec3TransformMat4, gehen können (ich habe Ihnen das nicht gezeigt). Sehen Sie, wie Rotation und Skalierung in der Matrix integriert sind (linker Teil des Bildes, rechter Teil über Kamera).

enter image description here

+0

Vielen Dank für Ihre Antwort Entity Black und Entschuldigung für die späte Reaktion! Deine Erklärung ist großartig, aber ich bin immer noch ein wenig verwirrt: Bedeutet das, dass es keine einzige Funktion gibt, um die Matrix-Vektor-Mathematik zu machen? Ich meine, wenn ich dieses calc im Shader mache, kann ich eine Identität erzeugen, dann _gl-matrix-lib_ähnliche Funktionen verwenden, um Übersetzung, Rotation und Skalierung (und vielleicht Perspektive) ohne eine Rücksetzung auf Identität zu übertragen, diese Matrix zu übergeben Hält _alle_ diese Information an den Shader, schreibe 'uniformMat * posAttrib' und es funktioniert !? Um es selbst zu tun, brauche ich getrennte Funktionen? Wie kann ich drehen und skalieren? –

+0

@var korrekt! JS hat keine Vektor-/Matrix-Mathematik. Alle Mathematik muss zuerst implementiert werden. Gl-Matrix ist eine gute Lösung. GLSL (Shader) hat diese Mathematik bereits, also können Sie im Shader Vektoren und Matrizen multiplizieren. Vertex-Daten werden in Puffern gespeichert. In den meisten Fällen müssen Sie die Puffer nicht ändern, Sie behalten die Modellmatrix, um die Modellwelt pos/rot/sca beizubehalten. Daten im Puffer sollten nur geändert werden, wenn Sie: ein Modell prozedural erstellen möchten (eindeutiger Baum, Blume, Haus ...) ODER die Form des Objekts während des Laufs ändern (Echtzeit-Zerstörung). –

+0

@var Wenn Sie mehr über Transformation wissen möchten, erstellen Sie bitte eine andere Frage. Lesen Sie zuerst http://webglfundamentals.org/. –

Verwandte Themen