2016-03-21 8 views
0

Ich zeichne Kreise/Ellipsen in WebGL mit einem einzigen Quad und einem Fragment - Shader, um sie in a zu zeichnen auflösungsunabhängige Art und Weise (Randabstand Anti-Aliasing)Wie kann ich dem WebGL - Shader gezeichnete Kreise/Ellipsen (gezeichnet mit Kanten -/Distanz - Antialiasing) einen einheitlichen Breitenumriss hinzufügen

Hier ist mein Fragment-Shader zur Zeit:

'#extension GL_OES_standard_derivatives : enable', 
'precision mediump float;', 
'varying vec2 coord;', 
'vec4 circleColor = vec4(1.0, 0.5, 0.0, 1.0);', 
'vec4 outlineColor = vec4(0.0, 0.0, 0.0, 1.0);', 

'uniform float strokeWidth;',   
'float outerEdgeCenter = 0.5 - strokeWidth;', 

'void main(void){', 

     'float dx = 0.5 - coord.x;', 
     'float dy = 0.5 - coord.y;', 
     'float distance = sqrt(dx*dx + dy*dy);', 

     'float delta = fwidth(distance);', 
     'float alpha = 1.0 - smoothstep(0.45 - delta, 0.45, distance);', 
     'float stroke = 1.0 - smoothstep(outerEdgeCenter - delta, outerEdgeCenter + delta, distance);', 

     'gl_FragColor = vec4(mix(outlineColor.rgb, circleColor.rgb, stroke), alpha);',     

'}' 

Dies schafft einen orangefarbenen Kreis mit einem schwarzen Umrisse, die perfekt antialiased ist unabhängig von der Größe.

enter image description here

aber sobald ich das Quad (skalieren), um verwandeln den Kreis in eine Ellipse zu drehen, die distance Berechnung transformiert mit ihm zusammen, so dass die Kontur auch skalieren. Mein Verständnis ist, dass ich irgendwie die Transformation des Vierecks erklären müsste, indem ich es umkehre.

enter image description here

Was würde ich ist wie für die distance einheitlich zu bleiben, auch wenn das Quad umgewandelt wird, in der Tat eine konstante Breite Umriss um den gesamten Kreis/Ellipse zu erzeugen.

Jede Hilfe würde sehr geschätzt werden.

Antwort

1

Das Problem ist, Ihr Fragment-Shader (FS) ist eine Art Blackbox jetzt (weil der Code ist Mangel an Informationen).

Ihr FS wird geschrieben, um innerhalb des quadratischen Raumes zu arbeiten. Es wird also immer ein Kreis im Raum dargestellt, in dem x und y die gleiche Größe haben (-1.0; 1.0 Intervall).

Während Quad ist außerhalb (in VS oder anderswo) transformiert und es gibt keine Möglichkeit, wie diese Transformation in FS noch widerspiegeln.

Um das Problem zu lösen, schlage ich vor, eine zusätzliche Information in FS über die Skalierung zu schieben. So etwas wie Shadertoy bietet in Shader-Eingänge:

uniform vec3 iResolution; // viewport resolution (in pixels) 

außer dies wird nicht die Auflösung der Bildschirmgröße, aber die Informationen über Quad-Transformation, so etwas wie:

varying vec2 trans; 
// where value (1.0, 1.0) mean no transformation 

Dann können Sie diesen Wert verwenden um einen anderen Schlag zu berechnen. Anstatt die Transformation für den aktuellen Strich zu invertieren, würde ich stattdessen eindeutige dx- und dy-Werte dafür berechnen.

Es gibt mehrere Möglichkeiten, die Arbeitslösung zu erreichen, und es hängt davon ab, wie Sie es später verwenden möchten (welche Arten von Transformationen sollten möglich sein usw.). Also präsentiere ich nur die einfache aber die einfachste Lösung.

+0

Danke, ich glaube, ich verstehe, was Sie sagen. Vorausgesetzt, ich habe die Breite und Höhe der Ellipse als Uniformen durchlaufen. Wie würde ich den Schlaganfall berechnen? – gordyr

+0

Nun, wenn du stattdessen Breite und Höhe drückst und du es nicht von außen transformierst, dann ist es jetzt ein anderes Spiel. Sie müssen wirklich entscheiden, was Sie wollen: Ellipsen und benutzerdefinierte Formen im Fragment-Shader zeichnen? Oder machen Sie Transformationen von außen? Die Frage beginnt zu groß zu werden. –

+0

Falls Sie mit Fragment Shader arbeiten wollen, empfehle ich dringend sharttoy. Es ist kleiner als webgl und einfacher zu verstehen.Diese Demo, die ich richtig geschrieben habe, könnte ein Hinweis für dich sein: https://www.shadertoy.com/view/4scSWr –

Verwandte Themen