2016-04-27 20 views
2

Ich rendere einige LineLoops auf einer Kugel (grenzt an einen Planeten) und möchte sie zu kürzeren Linien zusammenfügen, um zu verhindern, dass lange Linien in die Kugel einschneiden. Beispiel: enter image description hereZeichnen von verteilten LineLoops in OpenGL/GLSL

Hier ist meine aktuelle Quellcode: C++ Aufruf zeichnen:

void Border::Draw() const 
{ 
    glBindVertexArray(_vao); 

    glPatchParameteri(GL_PATCH_VERTICES, 2); 
    glDrawArrays(GL_PATCHES, 0, _size); 

    glBindVertexArray(0); 
} 

Vertex Shader:

#version 400 

in layout(location = 0) vec3 position; 

void main() 
{ 
    gl_Position = vec4(position, 1.0); 
} 

Tessallation Steuerung Shader:

#version 400 

layout (vertices = 2) out; 

void main() 
{ 
    if(gl_InvocationID == 0) 
    { 
     //get the distance between two points 
     float dist = length(gl_in[0].gl_Position - gl_in[1].gl_Position); 
     gl_TessLevelOuter[0] = 1; 
     //divide line in segments of size 1.0 
     gl_TessLevelOuter[1] = abs(dist); 
    } 

    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; 
} 

Tessallati zur Bewertung Shader

#version 400 

layout (isolines, equal_spacing) in; 

uniform float planetRadius; 
uniform mat4 view; 
uniform mat4 projection; 

void main() 
{ 
    vec4 p = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x); 

    //offset point so it is on the spheres surface 
    p = normalize(p); 
    p *= planetRadius; 

    gl_Position = projection * view * p; 
} 

Fragment Shader:

#version 400 

out vec4 outColor; 

void main() 
{ 
    outColor = vec4(1.0, 1.0, 1.0, 1.0); 
} 

Die Tessallation scheint nicht zu funktionieren, wie ich es erwartet zu arbeiten (auch schlechte Dokumentation auf isolines ist). Diese

ist, wie es aussah, als ich es mit LineLoops ziehen und nur Vertex/Fragment Shader:

enter image description here

und das ist, wie es aussieht, nachdem ich meine Tessallation umgesetzt:

enter image description here

Auch die Linien sehen nicht so aus und haben die gleiche Länge wie zuvor.

Grüße Jhonny

Edit: die Lösung selbst gefunden. Schauen Sie im Antwortabschnitt unten nach, um es zu sehen.

+1

Sind Sie sicher, dass Sie auf Normalisieren Sie den gesamten 'vec4 p' und nicht nur seinen' .xyz' Teil? Auch haben Sie möglicherweise die Verwendung von Isolinien falsch, hier ist eine gute Quelle: [http://www.informit.com/articles/article.aspx?p=2120983](http://www.informit.com/articles/article. aspx? p = 2120983) – aslg

+0

Danke die Normalisierung war Teil des Problems. – Jhonny007

Antwort

1

Ich fand die Lösung. Das Problem liegt in der Unfähigkeit des Installationssaders, Linienstreifen zu zeichnen.Wenn Sie also einen Leitungsstreifen durch die Punkte hava {p1, p2, p3, p4, p5, p6} es Linien zwischen:
p1 -> p2
p3 -> p4
p5 -> p6

fixierte ich es durch den Shader gibt jeden Punkt 2 mal , so meine Liste sieht wie folgt aus:
{p1, p2, p2, p3, p3, p4, p4, p5, p5, p6, p6, p1}
Der Tessallation Shader folgenden Zeilen erzeugt:
p1 -> p2
p2 -> p3
p3 -> p4
p4 -> p5
p5 -> p6
p6 -> p1

Mein Shadern nun so aussehen:

TessControl:

#version 430 

layout (vertices = 2) out; 

void main() 
{ 
    if(gl_InvocationID == 0) 
    { 
     float dist = length(gl_in[0].gl_Position.xyz - gl_in[1].gl_Position.xyz); 

     gl_TessLevelOuter[0] = 1; 
     gl_TessLevelOuter[1] = dist; 
    } 

    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; 
} 

TessEval:

#version 430 

layout (isolines, equal_spacing) in; 

uniform float planetRadius; 
uniform mat4 view; 
uniform mat4 projection; 

void main() 
{ 
    //only interpolate and normalize xyz coordinates. Thanks to @aslg 
    vec3 p = mix(gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, gl_TessCoord.x); 

    p = normalize(p); 
    p *= planetRadius; 

    gl_Position = projection * view * vec4(p, 1.0); 
}