2017-01-20 2 views
1

Ich versuche, den Vertex-Shader-Code zu implementieren, um das "Billboard" -Verhalten für ein bestimmtes Vertex-Mesh zu erreichen. Ich möchte das Gitter normalerweise (wie ein 3D-Objekt) definieren und es dann immer der Kamera zugewandt haben. Ich brauche es auch, um immer die gleiche Größe (Bildschirm-weise) zu haben. Diese beiden „Effekte“ passieren sollte:So transformieren Sie Vertices im Vertex-Shader, um ein 3D-Billboard zu erhalten

Billboard in which the size is preserved despite the camera being far awayBillboard in which the rotation is fixed despite rotating the camera

Der einzige Unterschied in meinem Fall ist, dass anstelle einer 2-D-Bar, ich ein 3D-Objekt haben wollen.

Um dies zu tun, versuche ich, die Alternative 3 in this tutorial (das gleiche, wo die Bilder stammen) zu folgen, aber ich kann nicht viele der Annahmen, die sie gemacht (wahrscheinlich aufgrund meines Mangels an Erfahrung in Grafik und OpenGL).

Mein Shader wendet die gemeinsame Transformation Stapel Ecken, d.h .:

gl_Position = project * view * model * position; 

Wo position ist das Eingangs Attribut mit dem Scheitelpunkt Lage in Welt-Raum. Ich möchte in der Lage sein, Modelltransformationen (wie Translation, Skalierung und Drehung) anzuwenden, um die Ausrichtung des Objekts in Bezug auf die Kamera zu ändern. Ich verstehe die im Tutorial erklärten Konzepte, aber ich kann nicht verstehen, dass ich sie in meinem Fall anwenden kann.

Was ich versucht habe, ist die folgende (aus dieser answer extrahiert und ähnlich dem Tutorial):

uniform vec4 billbrd_pos; 
... 
gl_Position = project * (view * model * billbrd_pos + vec4(position.xy, 0, 0)); 

Aber was ich bekommen, ist eine Form, deren Größe größer ist, wenn näher an das ist Kamera und ansonsten kleiner. Habe ich etwas vergessen?

Ist es möglich, dies im Vertex-Shader zu tun?

+0

Was ich tun würde, ist die Modellmatrix um '(view * center) .z' zu skalieren, so dass die Größe auf dem Bildschirm immer gleich ist. Für die tatsächliche Orientierungsmatrix sollte es die Transponierte der Ansichtsmatrix sein (also beide ausgleichen). – pleluron

Antwort

2
uniform vec4 billbrd_pos; 
... 
vec4 view_pos = view * model * billbrd_pos; 
float dist = -view_pos.z; 
gl_Position = project * (view_pos + vec4(position.xy*dist,0,0)); 

diese Weise die Fragment Tiefen noch richtig sind (bei billbrd_pos Tiefe), und Sie müssen das Seitenverhältnis des Bildschirms nicht zu verfolgen (wie das verlinkte Tutorial tut). Es hängt jedoch von der Projektionsmatrix ab.

+1

Danke, dass das Problem gelöst hat. Ich frage mich jedoch, was ist die zugrunde liegende Mathematik dieser Operation. Warum muss die Entfernung zur Kamera (was ich denke, dass die 'dist' Variable darstellt) mit den Koordinaten ___x___ und ___y___ jedes Eckpunkts multipliziert werden? –

+2

Perspektive macht Objekte in der Ferne kleiner, also müssen Sie sie relativ zu dieser Entfernung skalieren. Es könnte auch 'vec4 (position.xyz * dist, 0)' sein, wie Sie sagten, Sie haben ein 3D-Objekt zu rendern. – pleluron

Verwandte Themen