2017-12-06 25 views
0

Ich erstelle eine Mathematik-App, die OpenGL verwendet, um mehrere geometrische 3D-Formen anzuzeigen. In einigen Fällen schneiden sich diese Formen und wenn dies geschieht, möchte ich den Schnittpunkt jeder Form innerhalb des anderen zeigen. Da die beiden Formen durchscheinend sind, was ich brauche, ist mehr oder weniger so etwas wie dieses:Zeige den gemeinsamen Teil von 2 halbtransparenten Objekten?

Perfect intersection

jedoch mit 2 durchscheinend Sphären bekomme ich dieses Ergebnis statt:

With depth testing

Ich weiß, Um einen korrekten Transparenzeffekt zu erzielen, sollte die Tiefenprüfung deaktiviert werden, bevor die transparenten Formen gezeichnet werden. Aber dies einen weiteren Nebeneffekt bewirken, wenn eine transparente Form über eine andere nicht transparent Form ist:

Without depth testing

So ist es eine Möglichkeit, korrekt den schneidenden Teil von 2 Volumen Formen zu zeigen, die jeweils in der anderen, ohne zu brechen der Tiefentest?

Antwort

1

So ist es eine Möglichkeit, (...) volumetrische Formen

OpenGL (von selbst) zu zeigen, nicht wissen, über "Volumes". Es kennt flache Dreiecke, Linien und Punkte, was bei reinem Zufall auch Nebeneffekte wie die Tiefensortierung durch einen Tiefenpuffertest verursachen kann.

Technisch ist es möglich, eine Reihe von Zeichen- und Schablonenpufferoperationen zu verketten, um CSG durchzuführen (konstruktive Festkörpergeometrie); Details siehe ftp://ftp.sgi.com/opengl/contrib/blythe/advanced99/notes/node22.html.

Was Sie jedoch tun möchten, wird einfacher durch einen Raytracer implementiert, der im Fragment-Shader ausgeführt wird. Raytracing allein ist ein weites Thema und Sie können Bücher darüber füllen (tatsächlich wurden viele Bücher zu diesem Thema geschrieben). Es ist wahrscheinlich am besten, sich auf ein Beispiel zu beziehen. In diesem Fall beziehe ich mich auf die folgende ShaderToy https://www.shadertoy.com/view/ldS3DW - eine leicht abgespeckte Version dieser Shader, um die Art von intersectional Geometrie zeichnet Sie interessiert sind:

float sphere(vec3 ray, vec3 dir, vec3 center, float radius) 
{ 
    vec3 rc = ray-center; 
    float c = dot(rc, rc) - (radius*radius); 
    float b = dot(dir, rc); 
    float d = b*b - c; 
    float t = -b - sqrt(abs(d)); 
    float st = step(0.0, min(t,d)); 
    return mix(-1.0, t, st); 
} 


void mainImage(out vec4 fragColor, in vec2 fragCoord) 
{ 
    vec2 uv = (-1.0 + 2.0*fragCoord.xy/iResolution.xy) * 
     vec2(iResolution.x/iResolution.y, 1.0); 

    vec3 ro = vec3(0.0, 0.0, -3.0); 
    vec3 rd = normalize(vec3(uv, 1.0)); 

    vec3 p0 = vec3(0.5, 0.0, 0.0); 
    float t0 = sphere(ro, rd, p0, 1.0); 

    vec3 p1 = vec3(-0.05, 0.0, 0.0); 
    float t1 = sphere(ro, rd, p1, 1.0); 

    fragColor = vec4(step(0.0,t0)*step(0.0,t1)*rd, 1.0); 
} 
+0

ok, so gibt es keine „magische Weise“ zu tun, , dh durch Aktivieren oder Deaktivieren einer Option in OpenGL. Gute Idee, das im Shader zu machen, aber in meinem Fall habe ich mehrere Formen jenseits der einfachen Sphären, so dass mein Shader auf diese Weise sehr viel komplizierter wird. Vielleicht ist es der bessere Weg für mich, endlich Schablonenpuffer zu verwenden. Wie auch immer, danke für die Antwort (und Entschuldigung für den Fehler über die OpenGL-Volumes :-)) –

Verwandte Themen