Deutsch
PHP, HTML & JavaScript- Forum

3D Grafik - WebGL mit three.js

 
- Seite 1 -



HofK
Auf einen heißen Tipp von IF hin, habe ich mir mal
three.js  [...]  angeschaut. Da  [...]  (ganz unten) die ersten Resultate.
 
31.01.2016  
 



 
- Seite 14 -



HofK
ByteAttack (28.02.2018)
Zu kompliziert für mich Bin raus


Wenn ich fremde Quelltexte zu three.js anschaue, denke ich das Zitat auch sehr oft. Wenn es mich interessiert und Zeit ist, wühle ich mich rein - und dann bin oft, aber nicht immer "drin".

Nur wenn man laufend in der Materie ist hat man eine Chance.

p.specht (01.03.2018)
...dass die untere Biegung der Figur etwas nachhinkt im Bildaufbau...


Kann ich jetzt nicht nachvollziehen, demnächst gibt es die Box wie die Sphere im "Sandkasten". Dann kann man richtig testen woran es liegen könnte.

-------------------------------------

Mittlerweile habe ich Multimaterial "eingebaut". Es sind 11 Materialien nutzbar, für die 6 Seiten, die Kanten zu den 3 Achsen und die oberen und unteren Ecken, also zu +y und -y.



Die Systematik der Kanten musste ich noch einmal ändern, es gab Probleme beim uv-Mapping und dem Multimaterial.


Der Code vom gestrigen Beitrag wurde korrigiert.


 
01.03.2018  
 




HofK
demnächst gibt es die Box wie die Sphere im "Sandkasten"

Noch nicht final, aber schon zum testen. Die Struktur musste ich nochmals leicht ändern, es gibt sehr viele Abhängigkeiten zu beachten.

Magische Kugel und Kiste sollen auch noch möglichst zueinander passen. Auch deshalb gibt es eine Änderung bei sideCorner im obige Bild.

Neu:



Zwei Varianten der Explosionsdarstellung sind verfügbar.

Einmal (wie bisher) in Richtung der Flächennormalen und zusätzlich neu in Richtung des Strahls vom Ursprung zum Mittelpunkt der rechteckigen Segmente bzw. der Dreiecke bei den 4 Ecken der Kiste.

Dies ist eigentlich die korrekte Art und gar nicht so aufwändig, wie ich anfangs dachte. Wenn man einen guten Ansatz findet! Das war mein Problem.

Ich werde schauen und diese Art dann bei TREEf nachrüsten. Ob es bei THREEp Sinn macht, muss ich erst prüfen, die Normalen sind dort (fast???) identisch dem Strahl vom Kugelzentrum.

Über  [...]  bzw.  [...]  oder  [...]  gelangt man zur magischen Kugel oder Kiste.



Der Code muss nochmal durchgesehen und auch etwas optimiert werden.
Erst dann auf GitHub und discourse.

Übrigens ist nun bereits Revision 90 von three.js aktuell. Damit funktioniert es. 
 
05.03.2018  
 




HofK
...die Normalen sind dort (fast???) identisch dem Strahl vom Kugelzentrum.

Ja bei der Kugel, aber die verforme ich ja teils sehr kräftig. Dann gibt es auch bei MagicSphere und TEREEp sehr große Unterschiede.

Also habe ich bei MagicSphere die Modi 'center' und 'normal' integriert.

Bei THREEf und THREEp demnächst.
 

Aktualisiert auf sandboxthreeg  [...]  und nun auch bei GitHub.  [...] 

Bei einigen Beispielen habe ich Funktionen function(t) so manipuliert, dass die Mausbewegung Einfluss auf die Form hat.

Beispielsweise

function depthFunc( t ){ return mouse.y }
...
depth: depthFunc,

waffleDeep: function( t ) { return mouse.y % Math.floor( t ) }, // use mouse
 
07.03.2018  
 




HofK
Auch auf discourse  [...]  vorgestellt und weitere Beispiele dort [...] 

Auf meiner Seite [...]  [...] 

 
07.03.2018  
 




HofK
HofK (07.03.2018)
Bei THREEf und THREEp demnächst. 


Abhängig von



ändert sich in der Sandbox THRREf und THREEp der Bereich



bei non indexed zu



und man kann den Modus für die Explosionsdarstellung auswählen.

Einfach mal probieren.

---
NACHTRAG 11.03. - jetzt auch auf GitHub und dort  [...] 
 
10.03.2018  
 




HofK
Mir ist aufgefallen, dass ich beim "seichten" Einstieg in die 3D Browserwelt immer nur schrittweise einige grundlegende Dinge als solche erkannt habe.

Deshalb habe ich das nun mal in sehr knapper Form und hoffentlich verständlich zusammengefasst.

Hier in der Box und ganz unten auf meiner Seite  [...]  .

WebGL - GLSL - three.js - JavaScript - DOM

WebGL

Bei WebGL (Web Graphics Library) handelt es sich um eine JavaScript-Programmierschnittstelle, mit deren Hilfe bewgte 3D-Grafiken hardwarebeschleunigt im Webbrowser dargestellt werden können. Dazu werden keine zusätzliche Erweiterungen benötigt.

WebGL wurde im Vergleich zu den Browsern (ab 1989) relativ spät entwickelt. Der Beginn datiert etwa 20 Jahre danach!

WebGL basiert auf OpenGL ES (Open Graphics Library for Embedded Systems) im Zusammenspiel mit der Programmiersprache JavaScript. WebGL wird von der Khronos Group und Mozilla als lizenzfreier Standard entwickelt.

OpenGL ES selbst ist eine Spezifikation für eine plattform- und sprachenunabhängige Programmierschnittstelle zur Entwicklung von 3D-Computergrafik. Die Spezifikation beschreibt eine vereinfachte Version von OpenGL (Open Graphics Library). Diese wiederum beschreibt etwa 250 Befehle, die die Darstellung komplexer 3D-Szenen in Echtzeit erlauben. OpenGL wurde erstmals bereits 1992 veröffentlicht.

WebGL wird zumeist in der GPU (Graphics Processing Unit) statt in der CPU (Central Processing Unit) ausgeführt. Die GPU kann viele Operationen gleichzeitig ausführen, sie arbeitet massiv parallel. Dabei geht es letztendlich hauptsächlich um die Bestimmung von Koordinaten und Farbwerten. So entsteht die bewegte 3D Grafik auf dem Bildschirm.

Wenn man ein 2D Bildschirmbild aus einer 3D WebGL Scene berechnet, muss für jeden einzelnen Bildschirmpunkt ein Farbwert bestimmt werden. Es sind sehr viele "einfache", voneinander unabhängig Berechnungen nötig. Darauf ist die GPU spezialisiert.

GLSL

Die in WebGL benutzte Sprache ist GLSL (OpenGL Shading Language), eine Programmiersprache, um auf dem Grafikprozessor eigene Programme, sogenannte Shader (Schattierer), auszuführen. GLSL ist eine C-ähnliche Programmiersprache, die speziell an die Notwendigkeiten von Shadern angepasst wurde. Es gibt eingebaute Typen für Vektoren, Matrizen und viele Mathematik- und Grafikfunktionen. Viele Operationen können auf mehreren Datenelementen parallel arbeiten.

Es gibt die GLSL-Shadertypen Vertex-, Tessellation-, Geometry- und Fragmentshader als Teil der Rendering-Pipeline (Darstellunsschrittezur 3D-Szene) und die davon unabhängigen Compute-Shader. Der Programmierer übergibt für jeden Shadertyp den Shader-Quellcode und zusätzliche Variablen/Konstanten. Der WebGL-Treiber kompiliert und linkt die Shader zu einem Shaderprogramm. Dies wird in der GPU ausgeführt.

three.js

Die in JavaScript vorliegende Bibliothek three.js wurde erstmals im April 2010 von Mr. Doob (Ricardo Cabello) bei GitHub veröffentlicht. Bibliotheken wie three.js ermöglichen es, komplexe 3D-Computeranimationen zu erstellen, die im Browser angezeigt werden. Mit three.js können mit wesentlich geringerem Aufwand und sehr übersichtlich komplexere Scenarien erstellt werden. Letztendlich wird dann aber über WebGL die Scene dargestellt. Dabei hat three.js Zugriff auf alle Funktionen von GLSL. Die Bibliothek wird von einer Community kontinuierlich weiterentwickelt und ist auf GitHub verfügbar. Sie ist Open Source, kann aber für eigene kommerzielle Projekte verwendet werden (MIT-Lizenz).

JavaScript

JS (JavaScript) ist eine Skriptsprache, die 1995 beginnend von Netscape entwickelt wurde. Sie ermöglicht dynamisches HTML in Webbrowsern, um Benutzer- Interaktionen auszuwerten, Inhalte zu modifizieren, nachzuladen oder auch dynamisch zu generieren. Die Möglichkeiten von HTML und CSS wurden so wesentlich erweitert.

DOM

Das DOM (Document Object Model) ist die Spezifikation einer Programmierschnittstelle. HTML- Dokumente werden dabei als Baumstruktur dargestellt, in der jeder Knoten ein Objekt ist, welches einen Teil des Dokumentes darstellt. So kann mit JavaScript gezielt auf die Elemente der Seite lesend / schreibend zugegriffen werden. Dadurch können Objekteigenschaften verändert werden. Es lassen sich auch dynamisch Objekte auf der HTML Seite erstellen und löschen.

DOM wird vom W3C (World Wide Web Consortium, gegründet 1994 ) definiert.
Es ist seit 1998 ein Standard des W3C und wurde seitdem mehrfach aktualisiert und erweitert. Es existieren mehrere Versionen (Levels).
 
13.03.2018  
 




HofK
Nach so viel Geometrie, die hauptsächlich aus den Funktionswerten diverser Funktionen generiert wird, habe ich mir jetzt einmal etwas anderes vorgeknöpft.

Man muss recht viele Daten eingeben, um einen möglichst frei konfigurierbaren Innenraum in 3D zu generieren.

Dabei gibt es eine Vielzahl von Möglichkeiten. Nach einigen interessanten aber oft nicht brauchbaren Tests, habe ich momentan folgende Variante "in Arbeit".



Dabei kann man die so definierten Felder (mit Kommentar) editieren.
<textarea id="floors"  style="width: 620px; height: 120px " > [
<!-- Hauptraum: x,z Grundriss gegen Uhrzeigersinn, y Niveauhöhe -->
[ 0,7, 0,  9,7, 0,  9,0, 0,  0,0, 0 ],
<!-- Erker: x,z Grundriss gegen Uhrzeigersinn, y Niveauhöhe -->
[ 9,6, 0.2,  11,5, 0.2,  11,2, 0.2,  9,1, 0.2 ]
] </textarea>

Nach Aktualisierung (F5) sieht man sofort die Änderung, da der Inhalt des veränderten Textfeldes erhalten bleibt.

Die Wände haben noch keine uv's und werden zufällig gefärbt.

Wenn ich nicht noch eine bessere Variante entdecke, werde ich das mal zu einem kleinen Schauraum ausbauen.
 
18.03.2018  
 




HofK
HofK (18.03.2018)
Man muss recht viele Daten eingeben, um einen möglichst frei konfigurierbaren Innenraum in 3D zu generieren.



Im obigen Bild habe ich für den Boden eigene uv's eingegeben. Das kann für Figuren jenseits vom Rechteck sinnvoll sein. Bei einfachen Figuren sollte das Script die uv-Werte bei Bedarf aber sinnvoll selbst ermitteln können.

Gibt man ein leeres Feld   an, so geschieht das nun.



Beim Hauptraum ist kein Unterschied, da die Werte auf 0 bzw 1 gesetzt waren. Beim Erker hingegen wurde aus der großen Textur durch die Brüche etwas herausgeschnitten. Nun wird die gesamte Textur sehr stark gestaucht. Zum Vergleich jetzt die identische Wandtextur.



Bei der Rechnerei zu den uv's der non-indexed BufferGeometry habe ich, obwohl ich theoretisch weiß wie es geht, glatt wieder Fehler eingebaut. Schade für Anfänger, dass die einfache Geometry nicht dauerhaften Bestand haben soll.

So "einfach" geht es:
if ( floorsUVArray[ f ].length === 0 ) {

    for ( var c = 0, uv = 0, p = 0; c < corners; c ++, uv += 6, p += 9 ) {

        floorUVs[ f ][ uv ] = ( xM - xMin ) / dx;
        floorUVs[ f ][ uv + 1 ] = ( zM - zMin ) / dz;
        floorUVs[ f ][ uv + 2 ] = ( floorPositions[ f ][ p + 3 ] - xMin) / dx;
        floorUVs[ f ][ uv + 3 ] = ( zMax - floorPositions[ f ][ p + 5 ] ) / dz;
        floorUVs[ f ][ uv + 4 ] = ( floorPositions[ f ][ p + 6 ] - xMin) / dx;
        floorUVs[ f ][ uv + 5 ] = ( zMax - floorPositions[ f ][ p + 8 ] ) / dz;

    }

} else {

    u = 0;
    v = 0;

    for (  var c = 0, uv = 0; c < corners; c ++, uv += 2 ) {

        u += floorsUVArray[ f ][ uv ];
        v += floorsUVArray[ f ][ uv + 1 ];

    }

    u = u / corners;
    v = v / corners;

    for ( var c = 0, uv = 0; c < corners; c ++, uv += 6 ) {

        floorUVs[ f ][ uv ] = u;
        floorUVs[ f ][ uv + 1 ] = v;
        floorUVs[ f ][ uv + 2 ] = floorsUVArray[ f ][ c * 2 ];
        floorUVs[ f ][ uv + 3 ] = floorsUVArray[ f ][ c * 2 + 1 ];
        floorUVs[ f ][ uv + 4 ] = floorsUVArray[ f ][ ( c + 1 ) % corners * 2 ];
        floorUVs[ f ][ uv + 5 ] = floorsUVArray[ f ][ ( c + 1 ) % corners * 2 + 1 ];

    }

}

 
19.03.2018  
 




HofK
Die interne Struktur der Generierung der Wände musste noch einmal geändert werden, da sie nur für dünne Wände (Innenseite der Außenwände) konzipiert war. Da ich aber auch dicke Wände als Trennwände haben möchte und mit dieser Verfahrensweise auch andere Bauteile wie Konsolen, Podeste, Ausstellungstische usw. realisiert werden sollten, war eine Neuprogrammierung unumgänglich.

Mal abgesehen von den noch unmöglichen Texturen, kann man aber schon erkennen, wo es hin geht.





Es sind auch runde Formen möglich.

Die Böden, Decken und Wände und eckigen Bauteile habe ich mit selbst erstellter non-indexed BufferGeometry erzeugt.

Für die runden Formen bot sich THREE.CylinderBufferGeometry an.
Diese wird in three.js als indexed BufferGeometry realisiert.

Mit den uv's hatte ich dann ein Problem. Standardmäßig ist die Textur nach außen richtig herum und innen gespiegelt. Im obigen Bild ist aber der Zylinderteil (runde Raum"ecke") von innen zu sehen.

Nach Recherche habe ich gleich zwei einfache Lösungen gefunden. Wer die Wahl hat, hat die Qual. Ich habe mich noch nicht entschieden.

Einmal kann man die Textur spiegeln

var uvMirroredGrid= new THREE.TextureLoader().load( "uvgrid01.png" );
uvMirroredGrid.wrapS = THREE.RepeatWrapping;
uvMirroredGrid.repeat.x = - 1;


oder man spiegelt die uv's im Attribut der Geometrie

for ( var i = 0; i < roundWallGeometrys[ r ].getAttribute('uv').array.length; i += 2 ) {

roundWallGeometrys[ r ].getAttribute('uv').array[ i ] =
1 - roundWallGeometrys[ r ].getAttribute('uv').array[ i ];

}


Um einige passende Texturen zu bekommen, muss ich mich noch intensiver mit Grafik befassen. Mit Gimp 2.8 bin ich nicht so richtig "warm" geworden.

Habe etwas gesucht und Krita gefunden. Ist auch größtenteils Deutsch.
Bei heise  [...]  .
Mal schauen, ob ich da besser klarkomme. Die getupfte Rückwand ist ein erster Versuch!
 
25.03.2018  
 




HofK
oder man spiegelt die uv's im Attribut der Geometrie

... erscheint mir sinnvoller, da sie die Geometrie selbst betrifft und die Textur nicht verändert wird. So kann man die Textur auch unverändert mehrfach benutzen.

.....................................................................................................................................

In den obigen Bildern klafft ein Loch. Da muss eine Tür rein. Zuerst aber mal die Zarge.

Da gab es bei Discourse mal eine Frage [...] 
und eine tolle Lösung von prisoner849[...] 
function ProfiledContourGeometry(profileShape, contour, contourClosed) { ...

Mit dieser Funktion ist es dann schnell getan. Hier die Türzarge kurz vor dem Einbau.



Aus den beiden Werten 0.5 einfach 0 gemacht und schon sitzt die Zarge passend.

Wenn das mal praktisch auch so schnell ginge, ich habe da schon mal Stunden verbracht! 
 
26.03.2018  
 




HofK
Der Ausstellungsraum ist zwar noch im Rohbau, aber schon wurden die ersten Exponate angeliefert.

Und gleich zwei Königinnen!

Also müssen sie testweise platziert werden.



Das Foto der "Königin der Nacht" hat mit der Methode wie für die Zarge ganz schnell einen passenden Rahmen bekommen.
[ 4.91,0.25, 1.21,2.89, 7.09,0.25, 1.21,2.89, 1 ]

Die letzte 1 schließt den Rahmen. Das Bild selbst wird wie eine dünne Wand generiert. Das Foto dient als Textur.
<!-- Bilder -->
[ 7,0.26, 1.3,2.8, 5,0.26, 1.3,2.8 ],


Unsere Königin blüht immer Ende Juni. Nach dem Abendbrot geht sie langsam auf und wenn man nicht ganz früh aufsteht, ist sie schon wieder verwelkt. So gegen 5:00-6:00 Sommerzeit kann man nochmal schauen.

Die Nofretete wird von @author bhouston / http ://clara.io [...]  kostenlos zur Verfügung gestellt. Ben Houston ist auch einer der Mitentwickler von three.js.



Das Modell liegt im JSON Format (JavaScript Object Notation) vor.
var objectLoader = new THREE.ObjectLoader();
objectLoader.load( "nefertiti.json", loadNefertiti );

function loadNefertiti( obj ) {
obj.scale.set( 0.1, 0.1, 0.1 );
obj.position.set( 7, 1, 2 );
obj.rotation.y = 2.1;
room.add( obj );
}

In meiner Ausstellung sieht die altägyptische Königin im Gegensatz zum Original bei clara.io etwas blass aus. Es fehlt noch die passende Farbzuordnung/Beleuchtung - Rohbau!

Übrigens kann man die JSON Datei mit Firefox laden. Etwas warten, die Datei ist recht groß. Das verzögert auch den Seitenaufbau bei meinem Schauraum.

Beim Bilderrahmen kann man erkennen, dass die linke untere Ecke sich farblich etwas abhebt. Hier leuchtet ein Farbspot.

var spotLight = new THREE.SpotLight( 0xccffcc,1.0,16,0.2,0.5,1.2 );
spotLight.position.set( 5, 3.4, 4 );
scene.add( spotLight );

spotLight.target = frameMeshes[ 1 ];
 
27.03.2018  
 




HofK
Einige (Kunst)blumen machen den Raum gleich freundlicher.

Zum Test habe ich eine Blume von Hitesh Sahu (free)  [...]  in zwei Formaten (JSON und OBJ/MTL) heruntergeladen.

Die Einbindung der JSON Datei:

new THREE.ObjectLoader().load( "flower.json", loadFlower );
function loadFlower( obj ) {
obj.scale.set( 0.01, 0.01, 0.01 ); // Original hat anderen Maßstab!
obj.position.set( 7, 0.0001, 3 );
room.add( obj );
}


brachte eine Überraschung für mich.

Nicht nur das reine Modell, sondern auch die Beleuchtung steckt in der .json Datei.



Diese kommt zu meiner bereits vorhandenen Beleuchtung hinzu und der Raum ist stark überbeleuchtet. Man erkennt am Blumentopf, dass Licht aus verschiedenen Richtungen kommt.

Bringt nun jedes Modell sein eigenes Licht mit, gibt das die totale Lichtverschmutzung.

JSON Dateien sind lesbar und so findet man fast am Anfang die Lichtvoreinstellung (light preset).



Hier einfach für alle Lichter (gesamter Block) "visible" auf false gesetzt und das Extralicht geht aus. Natürlich kann man auch den Block an lassen und einzelne Lichtquellen, z.B. das Sonnenlicht ausschalten.



Nun die identische Blume als OBJ/MTL Dateien importiert. Dazu muss man im Gegensatz zu JSON zusätzlich zu three.js noch die (sehr kleinen) Scripte

<script src="OBJLoader.js"></script>
<script src="MTLLoader.js"></script>


einbinden.

new THREE.MTLLoader( ).load("flower.mtl", loadMtlObjFlower );
function loadMtlObjFlower( materials ) {
materials.preload( );
var objLoader = new THREE.OBJLoader( ).setMaterials( materials );
objLoader.load( "flower.obj", function ( obj ) {
obj.scale.set( 0.01, 0.01, 0.01 ); // Original hat anderen Maßstab!
obj.position.set( 6.6, 0.0001, 3 );
room.add( obj );
} );
}


Durch die Trennung von Geometrie (.obj) und Material (.mtl) ist die Sache aufwändiger.



Hier kam kein Licht mit.

Die Blumen werden nicht identisch dargestellt. Da spielt das Beleuchtungsmodell, die Beziehung von Licht/Material/Geometrie mit.

Wenn ich für meinen Bilderrahmen statt THREE.MeshLambertMaterial (flatShading ändert nichts)



THREE.MeshPhongMaterial mit flatShading: true nehme, sieht es auch deutlich anders aus.



Es gibt sooooooooooooo viele Möglichkeiten und damit kann man eben tolle Effekte erzielen, es braucht etwas Zeit, das halbwegs zu überschauen.
 
28.03.2018  
 




Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

332.789 Betrachtungen

Unbenanntvor 0 min.
HofK vor 23 Tagen
Rschnett24.08.2024
Michael W.28.03.2024
Thomas Zielinski17.02.2024
Mehr...

Themeninformationen



Admins  |  AGB  |  Anwendungen  |  Autoren  |  Chat  |  Datenschutz  |  Download  |  Eingangshalle  |  Hilfe  |  Händlerportal  |  Impressum  |  Mart  |  Schnittstellen  |  SDK  |  Services  |  Spiele  |  Suche  |  Support

Ein Projekt aller XProfaner, die es gibt!


Mein XProfan
Private Nachrichten
Eigenes Ablageforum
Themen-Merkliste
Eigene Beiträge
Eigene Themen
Zwischenablage
Abmelden
 Deutsch English Français Español Italia
Übersetzungen

Datenschutz


Wir verwenden Cookies nur als Session-Cookies wegen der technischen Notwendigkeit und bei uns gibt es keine Cookies von Drittanbietern.

Wenn du hier auf unsere Webseite klickst oder navigierst, stimmst du unserer Erfassung von Informationen in unseren Cookies auf XProfan.Net zu.

Weitere Informationen zu unseren Cookies und dazu, wie du die Kontrolle darüber behältst, findest du in unserer nachfolgenden Datenschutzerklärung.


einverstandenDatenschutzerklärung
Ich möchte keinen Cookie