2010-11-29 7 views
11

ich nach einem Weg suchen ziehen etwas Ähnliches wie diese „Knöpfe“ mit einem GLSL ShaderopenGL GLSL Shader: Zeichnen Sie einen Kreis auf einem flachen Polygon

alt text

Ich möchte nur die farbige ziehen Kreise, und meine Anwendung ist nicht für einen Knopf eher eine funky Fortschrittsanzeige. Ist es möglich, mit einem Shader Kreise (oder genauer gesagt Bögen) auf einem flachen Polygon zu zeichnen? Und wie würde man den Prozess beginnen?

Antwort

8

Ja, es ist möglich! Markieren Sie dieses GLSL-Skript, das mehrere verschiedene Bögen zieht:


#define between(v,x1,x2) (v>= x1 && v<=x2) 
#define pi 3.141592653589793238462643383279 

uniform sampler2D tex; 

void main() 
{ 
    vec2 pnt = vec2(0.5,0.5); 
    float dr = 0.005; 
    float fr = 0.15; 
    float r1 = fr; 
    float r2 = 1.5*fr; 
    float r3 = 2.0*fr; 
    float r4 = 2.5*fr; 
    float r5 = 3.0*fr; 
    float rp = distance(pnt,gl_TexCoord[0].xy); 
    vec4 col1 = vec4(0.4,0.1,0.,1.); 
    vec4 col2 = vec4(1.,1.,1.,1.); 
    float angle = atan(gl_TexCoord[0].y,gl_TexCoord[0].x); 
    vec4 rezcol; 
    rezcol = (between(rp,r1-dr,r1+dr) && between(angle,-pi,pi))? col1:col2; 
    rezcol = (between(rp,r2-dr,r2+dr) && between(angle,-pi,pi/3.1) && rezcol==col2)? col1:rezcol; 
    rezcol = (between(rp,r3-dr,r3+dr) && between(angle,-pi,pi/4.6) && rezcol==col2)? col1:rezcol; 
    rezcol = (between(rp,r4-dr,r4+dr) && between(angle,-pi,pi/8.8) && rezcol==col2)? col1:rezcol; 
    rezcol = (between(rp,r5-dr,r5+dr) && between(angle,-pi,pi/22.8) && rezcol==col2)? col1:rezcol; 
    gl_FragColor = rezcol; 
} 

die in einem solchen Bild ergibt:

alt text

+0

Nicht die eleganteste Ansatz von allen, ich würde sagen,) Sie einführen ein Zweig (:) pro Kreis, was sicherlich vermieden werden kann. Auch könnte mit etwas Glättung erweitert werden. (Noch, +1) – Kos

+0

Oyoyoy. Werfen Sie einen sanften Schritt, um Antialiasing zu ermöglichen. Auch sollten Ihre Kreise mit einer Tangente abgeschnitten werden, sie sollten mit einer Linie abgeschnitten werden, die den Kreismittelpunkt kreuzt (die Enden der Kreise sollten Winkel von 90 Grad haben, anders als in Ihrem Fall, besonders die obersten). –

11

Ja, es ist möglich. Legen Sie Texturkoordinaten für das Polygon fest, damit Sie auf die relativen Koordinaten im Shader zugreifen können (z. B. von -1, -1 bis 1,1, um die Mitte des Polygons 0,0 zu bestimmen). Ermitteln Sie im Fragment-Shader den Abstand zum Zentrum mit Pythagoran. Wenn die Entfernung kleiner als der Radius des Kreises ist, befindet sich das Pixel innerhalb des Kreises. Sie können dann den Radius für zwei Kreise angeben und das Pixel färben, wenn es sich innerhalb des äußeren Kreises und außerhalb des inneren Kreises befindet.

Wenn Sie nur einen Bogen färben möchten, ermitteln Sie den Winkel mit atan (y, x) und prüfen Sie, ob er innerhalb eines bestimmten Bereichs liegt.

Sie können die Kreise auch glätten, indem Sie die Interpolation (Schritt, Glätten usw.) anstelle eines einfachen Falls verwenden, wenn Sie bestimmen, ob der Punkt innerhalb eines Kreises liegt.

Auch als Optimierung müssen Sie die Quadratwurzel nicht berechnen, wenn Sie den Abstand zum Mittelpunkt berechnen, wenn Sie stattdessen einen Radius^2 überprüfen.