Frage zu Ray-Picking mit JOGL

chrysipp

Mitglied
Ich versuche gerade Ray-Picking zu implementieren.und stecke leider schon bei gluUnproject fest. Dieses habe ich wie hier verwendet. Beim Click berechne ich mir die Position in Weltkoordinaten für 2 verschiedene Z Werte (near und far plane) um daraus dann einen Vektor zu erstellen.

Mein Code sieht so aus:
Java:
public void picking(GL gl,int mouseX, int mouseY){
        gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
        gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, mvmatrix, 0);
        gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, projmatrix, 0);
        
        realY = viewport[3] - (int) mouseY - 1;
        System.out.println("Coordinates at cursor are (" + mouseX + ", " + realY);
        glu.gluUnProject((double) mouseX, (double) realY, 1.0, 
            mvmatrix, 0,
            projmatrix, 0, 
            viewport, 0, 
            worldCoord, 0);
        System.out.println("World coords at z=1.0 are ( " 
                           + worldCoord[0] + ", " + worldCoord[1] + ", " + worldCoord[2]
                           + ")");
        glu.gluUnProject((double) mouseX, (double) realY, 20.0, 
            mvmatrix, 0,
            projmatrix, 0,
            viewport, 0, 
            worldCoord, 0);
        System.out.println("World coords at z=20.0 are (" 
                           + worldCoord[0] + ", " + worldCoord[1] + ", " + worldCoord[2]
                           + ")");
.........
.........
}

Die ausgegebenen Weltkoordianten kommen mir aber etwas seltsam vor. Für die Objekte die auf den Z Positionen liegen müssten doch eigentlich die korrekten x und y Werte rauskommen, oder nicht? Ich habe ein Element bei -1/-1/1, wenn ich dieses anklicke liefert gluUnProject mit Z Wert 1 die Koordinaten -0.2/-0.2/3.9
Das kommt mir etwas seltsam vor. Läuft da etwas falsch oder verstehe ich da nur etwas falsch?
 
Moin,

der dritte Parameter bei gluUnProject() muss zwischen 0 (near plane) und 1 (far plane) liegen. Das sind nicht die z Werte die Du z.B. bei gluPerspective() angibst.

Du kannst auch direkt den z Wert aus dem Tiefenpuffer auslesen und erhältst dann direkt die richtige xyz Koordinate des Punktes den Du getroffen hast.

Java:
import java.awt.Frame;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.nio.FloatBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;

import com.sun.opengl.util.Animator;
import com.sun.opengl.util.BufferUtil;

public class Pick implements GLEventListener {

    private final FloatBuffer mouseZ = BufferUtil.newFloatBuffer(1);

    private int               mouseX;
    private int               mouseY;

    private GL                gl;
    private GLU               glu;


    @Override
    public void init(final GLAutoDrawable drawable) {

        gl = drawable.getGL();
        glu = new GLU();

        gl.glEnable(GL.GL_DEPTH_TEST);

    }


    public void pick() {

        final int[] vp = new int[4];
        final double[] mv = new double[16];
        final double[] p = new double[16];
        final double[] result = new double[3];

        gl.glGetIntegerv(GL.GL_VIEWPORT, vp, 0);
        gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, mv, 0);
        gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, p, 0);

        gl.glReadPixels(mouseX, mouseY, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, mouseZ);

        glu.gluUnProject(mouseX, mouseY, mouseZ.get(0), mv, 0, p, 0, vp, 0, result, 0);

        System.out.println("mouse: " + mouseX + ", " + mouseY + ", " + mouseZ.get(0));
        System.out.println("world: " + result[0] + ", " + result[1] + ", " + result[2]);

    }


    @Override
    public void display(final GLAutoDrawable drawable) {

        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        gl.glColor3f(1.0f, 0.0f, 0.0f);

        gl.glBegin(GL.GL_TRIANGLES);
        gl.glVertex3f(-1.0f, -1.0f, -5.0f);
        gl.glVertex3f(+1.0f, -1.0f, -5.0f);
        gl.glVertex3f(+0.0f, +1.0f, -5.0f);
        gl.glEnd();

        pick();

    }


    @Override
    public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, int height) {

        if (height <= 0)
            height = 1;

        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(45.0f, (float) width / (float) height, 1.0, 20.0);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

    }


    @Override
    public void displayChanged(final GLAutoDrawable drawable, final boolean modeChanged, final boolean deviceChanged) {

    }


    public static void main(final String[] args) throws IOException {

        final Pick pick = new Pick();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);

        canvas.addGLEventListener(pick);
        canvas.addMouseMotionListener(new MouseMotionAdapter() {

            @Override
            public void mouseMoved(final MouseEvent e) {

                pick.mouseX = e.getX();
                pick.mouseY = canvas.getHeight() - e.getY() - 1;

            }

        });

        frame.add(canvas);
        frame.setSize(800, 600);
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(final WindowEvent e) {

                new Thread(new Runnable() {
                    public void run() {

                        animator.stop();
                        System.exit(0);

                    }

                }).start();
            }
        });

        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        animator.start();

    }

}

Gruß,
Fancy
 
Die 3D Koordinaten sind vor allem dann sinnvoll wenn man wissen will, wo exakt man ein Dreieck getroffen hat. Interessiert hingegen nur welches Objekt getroffen wurde, bieten sich andere Verfahren an, z.B. color picking. Sinnvoll kann auch eine Kombination aus beidem sein. Dann wird mit color picking zuerst das getroffene Objekt bestimmt und anschließend über Strahl- / Dreieck- Schnitte welches Dreieck und wo exakt innerhalb des Dreiecks getroffen wurde.

Color picking sähe z.B. so aus (das ist jetzt jogl2 oben das war jogl1):

Java:
import java.awt.Frame;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;

import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLBuffers;


public class Pick implements GLEventListener {

    private static final float[] TRIANGLE_XY = { -0.5f, -0.5f, +0.5f, -0.5f, +0.5f, +0.5f, -0.5f, -0.5f, +0.5f, +0.5f, -0.5f, +0.5f };

    private final FloatBuffer    vaXY        = GLBuffers.newDirectFloatBuffer(TRIANGLE_XY);
    private final ByteBuffer     color       = GLBuffers.newDirectByteBuffer(4);

    private int                  mouseX;
    private int                  mouseY;

    private GL2                  gl;
    private GLU                  glu;


    @Override
    public void init(final GLAutoDrawable drawable) {

        gl = drawable.getGL().getGL2();
        glu = new GLU();

        gl.glEnable(GL.GL_DEPTH_TEST);
        gl.glDisable(GL.GL_DITHER);

        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);

    }


    private void box(final float x, final float y, final float z, final float size) {

        gl.glPushMatrix();
        gl.glLoadIdentity();
        gl.glTranslatef(x, y, z);
        gl.glScalef(size, size, size);

        gl.glVertexPointer(2, GL2.GL_FLOAT, 0, vaXY);
        gl.glDrawArrays(GL2.GL_TRIANGLES, 0, vaXY.capacity() / 2);

        gl.glPopMatrix();

    }


    @Override
    public void display(final GLAutoDrawable drawable) {

        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();

        // picking pass
        gl.glEnable(GL.GL_SCISSOR_TEST);
        gl.glScissor(mouseX, mouseY, 1, 1);
        gl.glClear(GL.GL_COLOR_BUFFER_BIT);

        int i = 0;
        for (float y = -0.75f; y <= +0.75f; y += 0.5)
            for (float x = -0.75f; x <= +0.75f; x += 0.5) {

                i += 1;

                gl.glColor3ub((byte) ((i >> 0) & 0xff), (byte) ((i >> 8) & 0xff), (byte) ((i >> 16) & 0xff));
                box(x, y, -3.0f, 0.25f);

            }

        gl.glDisable(GL.GL_SCISSOR_TEST);
        gl.glReadPixels(mouseX, mouseY, 1, 1, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, color);
        final int selected = color.getInt(0);


        // color pass
        gl.glClear(GL.GL_COLOR_BUFFER_BIT);
        gl.glColor3f(1.0f, 0.0f, 0.0f);

        i = 0;
        for (float y = -0.75f; y <= +0.75f; y += 0.5)
            for (float x = -0.75f; x <= +0.75f; x += 0.5) {

                i += 1;

                if (i == selected)
                    gl.glColor3f(1.0f, 1.0f, 0.0f);

                else
                    gl.glColor3f(1.0f, 0.0f, 0.0f);

                box(x, y, -3.0f, 0.25f);

            }

    }


    @Override
    public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, int height) {

        if (height <= 0)
            height = 1;

        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(45.0f, (float) width / (float) height, 1.0, 20.0);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();

    }


    @Override
    public void dispose(final GLAutoDrawable arg0) {

    }


    public static void main(final String[] args) throws IOException {

        final Pick pick = new Pick();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);

        canvas.addGLEventListener(pick);
        canvas.addMouseMotionListener(new MouseMotionAdapter() {

            @Override
            public void mouseMoved(final MouseEvent e) {

                pick.mouseX = e.getX();
                pick.mouseY = canvas.getHeight() - e.getY() - 1;

            }

        });

        frame.add(canvas);
        frame.setSize(800, 600);
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(final WindowEvent e) {

                new Thread(new Runnable() {
                    public void run() {

                        animator.stop();
                        System.exit(0);

                    }

                }).start();
            }
        });

        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        animator.start();

    }

}

Gruß,
Fancy
 
Sehr gut 😀

Wie viele Boxen kann man damit unterscheiden? Normalerweise geht ja das pro Byte nur bis 255 oder (jedenfalls so wie der obere Quellcode her gibt) ?


Doch was machen diese Zeilen hier genau:

// picking pass
gl.glEnable(GL.GL_SCISSOR_TEST);
gl.glScissor(mouseX, mouseY, 1, 1);
gl.glClear(GL.GL_COLOR_BUFFER_BIT);


Appropos Scissor... ich benutze das um im 2D Screen Layer zu begrenzen, damit 2D Boxen in diesem Layer nicht über den Layerrand hinaus gezeichnet werden.

Kannst Du mir sagen wie ich das mit einem 3D-Box Layer mache?
Also ich lege eine 3D Box in den 3D Raum (als 3D Layer mit der Größe 20x20x20) mit einer Wireframe Alpha Textur. Nun platziere ich weitere 1x1x1 3D Boxen in diesen 3D Box Layer. Wenn eine 3D Box aus dem 3D Layer Raum hinaus geht, soll sie nicht mehr gezeichnet werden. Geht das auch mit Scissor und wie mache ich eine 3D Box Textur durchsichtig (alleine mit Alpha Kanal scheint das nicht zu gehen).
 
Zuletzt bearbeitet:
Wie viele Boxen kann man damit unterscheiden? Normalerweise geht ja das pro Byte nur bis 255 oder (jedenfalls so wie der obere Quellcode her gibt) ?

Oben werden aber drei Bytes genutzt (RGB). Mit knapp 16.7 Millionen identifizierbaren Objekten sollte das normalerweise reichen.


gl.glEnable(GL.GL_SCISSOR_TEST);

Schaltet den Scissor Test ein.


gl.glScissor(mouseX, mouseY, 1, 1);

Legt die Scissorbox exakt unter den Mauszeiger. Dadurch wird nur das eine Fragment unter dem Mauszeiger weiterverarbeitet. Andere Fragmente werden nach dem Scissor Test verworfen, so dass das Verfahren etwas schneller laufen kann.

(Ein 1x1 Test kann mit Kantenglättung zu Problemen führen da die Farben dabei interpoliert werden. In diesem Fall muss z.B. ein 3x3 Feld ausgelesen werden und bestimmt werden welche Farbe überwiegt.)


gl.glClear(GL.GL_COLOR_BUFFER_BIT);

Löscht die Farbinformation aus dem Framebuffer.


Appropos Scissor... ich benutze das um im 2D Screen Layer zu begrenzen, damit 2D Boxen in diesem Layer nicht über den Layerrand hinaus gezeichnet werden.

Kannst Du mir sagen wie ich das mit einem 3D-Box Layer mache?
Also ich lege eine 3D Box in den 3D Raum (als 3D Layer mit der Größe 20x20x20) mit einer Wireframe Alpha Textur. Nun platziere ich weitere 1x1x1 3D Boxen in diesen 3D Box Layer. Wenn eine 3D Box aus dem 3D Layer Raum hinaus geht, soll sie nicht mehr gezeichnet werden. Geht das auch mit Scissor

Der Scissor Test arbeitet auf Fragmentebene. Mit 3D hat dieser nicht zu tun. Seine Parameter sind Fensterkoordinaten.


Dein Problem verstehe ich nicht. Setze doch einfach die Koordinaten so wie sie sein sollen, dann wird auch nichts über irgendwelche Grenzen hinweg gezeichnet.


und wie mache ich eine 3D Box Textur durchsichtig (alleine mit Alpha Kanal scheint das nicht zu gehen).

Ich vermute mal Du meinst keine richtige 3D Textur, sondern eine Textur die Du um deine Box legst? Damit der Alpha Kanal berücksichtigt wird muss das Blending aktiviert sein. Siehe z.B. hier.


Gruß,
Fancy
 
Ok, ich werde mal damit etwas rumspielen.

Oben werden aber drei Bytes genutzt (RGB). Mit knapp 16.7 Millionen identifizierbaren Objekten sollte das normalerweise reichen.
Das wäre ja nur der Fall, wenn man "i" nicht in alle Farb-Bytes kopiert, sondern erst bei i>256 in die höheren Bytes einträgt (vorher 0). Oder wird die Objektnummer schon so richtig in die 3 Bytes zerhackt?


Aber bzgl. des Alpha und 3D Objekte hab ich immer noch ein Problem (siehe Screenshot im Anhang, 3D Kiste ist von der transparenten 3D Box verdeckt, aber ich möchte es genau anders rum, wenn die Kiste innerhalb ist anzeigen, den Rest ausserhalb nicht anzeigen). Zwar kann ich durch die Alpha Textur der 3D Box sehen, doch wenn andere 3D Boxen in eine 3D Box hineinfliegen, dann verschwinden sie, obwohl ja die Textur transparent ist.

Hier ist mein Code:

[Java]


// * GL Init *


GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);


// * Texturen *
GL11.glEnable(GL11.GL_TEXTURE_2D);


GL11.glPushAttrib(GL11.GL_ENABLE_BIT|GL11.GL_TRANSFORM_BIT|GL11.GL_HINT_BIT|GL11.GL_COLOR_BUFFER_BIT|GL11.GL_SCISSOR_BIT|GL11.GL_LINE_BIT|GL11.GL_TEXTURE_BIT);
GL11.glEnable(GL11.GL_BLEND);
//GL11.glEnable(GL11.GL_LINE_SMOOTH);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE_MINUS_SRC_ALPHA);
//GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);

//GL11.glDepthMask(false);


GL11.glViewport(0, 0, 1360, 768);






// * Display Routine:


// * Clear Colorbuffer + Depthbuffer *
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

int cameraDistance = 5;
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45.0f,1.2f, 1.0f, 400.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();

// * Camera Location,
GLU.gluLookAt(0, 0, cameraDistance, 0, 0, 0, 0, 1, 0);




for(int i=0;i<3;i++) { // * die transparente 3D Box "Load Image" wird zuerst gezeichnet! *

// * 3D Boxen zeichnen *

// * Resettet die View *
GL11.glLoadIdentity();
GL11.glPushMatrix();


// * Translatiere in den Screen hinein/heraus um z
GL11.glTranslatef(position.x, position.y, position.z);


GL11.glScalef(boxWidthHalf, boxHeightHalf, boxDepthHalf);


// Apply texture.
GL11.glBindTexture(glTexTypeLWJGL, boxTexturePool.get(useTexturePoolFrame).getTextureID());



GL11.glBegin(GL11.GL_QUADS);

// Vorderseite
GL11.glNormal3f( 0.0f, 0.0f, 1.0f); // Normalenvektor zeigt in Richtung Betrachter
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Punkt 1 (vorne)
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f( 1.0f, -1.0f, 1.0f); // Punkt 2 (vorne)
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f( 1.0f, 1.0f, 1.0f); // Punkt 3 (vorne)
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Punkt 4 (vorne)
.
.
.

GL11.glEnd();

GL11.glPopMatrix();

}

[/code]


Ausserdem sind nicht alle Seiten der 3D Box durchsichtig (siehe Screenshot 2 mit dem roten X)

.
 
Zuletzt bearbeitet:
Das wäre ja nur der Fall, wenn man "i" nicht in alle Farb-Bytes kopiert, sondern erst bei i>256 in die höheren Bytes einträgt (vorher 0). Oder wird die Objektnummer schon so richtig in die 3 Bytes zerhackt?

Java:
gl.glColor3ub((byte) ((i >> 0) & 0xff), (byte) ((i >> 8) & 0xff), (byte) ((i >> 16) & 0xff));

Es werden die niederwertigsten 8 Bit in R, die nächsten 8 Bit in G und weitere 8 Bit in B gespeichert. Bein Auslesen über den ByteBuffer color werden diese Werte wieder ausgelesen und als int interpretiert.


Aber bzgl. des Alpha und 3D Objekte hab ich immer noch ein Problem (siehe Screenshot im Anhang, 3D Kiste ist von der transparenten 3D Box verdeckt, aber ich möchte es genau anders rum, wenn die Kiste innerhalb ist anzeigen, den Rest ausserhalb nicht anzeigen). Zwar kann ich durch die Alpha Textur der 3D Box sehen, doch wenn andere 3D Boxen in eine 3D Box hineinfliegen, dann verschwinden sie, obwohl ja die Textur transparent ist.

Alpha Blending ist von der Anwendung her nicht ganz so einfach. Siehe z.B. die OpenGL FAQ dazu. Insbesondere Punkt 15.070 und Punkt 15.050.


Ausserdem sind nicht alle Seiten der 3D Box durchsichtig (siehe Screenshot 2 mit dem roten X)

Ohne Dein Problem jetzt genau nachvollziehen zu können (kskb), aber ist Dir bewusst, dass jede Fläche eine Vorder- und eine Rückseite hat? Wenn man auf eine Fläche sieht und die einzelnen Vertices (Eckpunkte) sind gegen den Uhrzeigersinn angeordnet, handelt es sich (normalerweise) um die Vorderseite. Je nach gesetzten OpenGL Parametern wird die Rückseite anders behandelt und kann zu unerwartetem Verhalten führen.


Gruß,
Fancy
 
Alpha Blending ist von der Anwendung her nicht ganz so einfach. Siehe z.B. die OpenGL FAQ dazu. Insbesondere Punkt 15.070 und Punkt 15.050.

Ohne Dein Problem jetzt genau nachvollziehen zu können (kskb), aber ist Dir bewusst, dass jede Fläche eine Vorder- und eine Rückseite hat? Wenn man auf eine Fläche sieht und die einzelnen Vertices (Eckpunkte) sind gegen den Uhrzeigersinn angeordnet, handelt es sich (normalerweise) um die Vorderseite. Je nach gesetzten OpenGL Parametern wird die Rückseite anders behandelt und kann zu unerwartetem Verhalten führen.

Hmmm... ok also muss ich wohl Blending ausschalten und glTexEnv verwenden. Oder wie würdest Du die oben bestehenden Probleme am besten lösen? Ich mein, das sind ja einfache Allerweltsprobleme, die sicherlich schon 100 Mal gelöst wurden, denke ich mal 😀
 
Nö, ich würde ermal das versuchen was in der FAQ empfohlen wird.

http://www.opengl.org/resources/faq/technical/transparency.htm hat gesagt.:
If you're drawing a polygon that's behind another polygon, and depth test is enabled, then the new polygon will typically lose the depth test, and no blending will occur.

-> Tiefentest ausschalten.


http://www.opengl.org/resources/faq/technical/transparency.htm hat gesagt.:
Do I need to render my primitives from back to front for correct rendering of translucent primitives to occur?

If your hardware supports destination alpha, you can experiment with different glBlendFunc() settings that use destination alpha. However, this won't solve all the problems with depth buffered translucent surfaces. The only sure way to achieve visually correct results is to sort and render your primitives from back to front.

-> Mit verschiedenen glBlendFunc() experimentieren, wenn das nicht reicht
-> Dreiecke von hinten nach vorne rendern


Wenn es dann immer noch nicht geht, würde ich dazu ein sinnvolles kskb bauen und es hier in einen neuen Thread mit einer entsprechenden Frage posten. Mit etwas glück würde dann Marco, ich oder einer der anderen, die sich hier mit OpenGL beschäftigen, eine Hilfestellung geben können.

Gruß,
Fancy
 
Mit etwas glück würde dann Marco, ich oder einer der anderen, die sich hier mit OpenGL beschäftigen, eine Hilfestellung geben können.

Hey, 😡 sind wir hier jetzt in einem Zeichentrickfilm wo wir uns die klassische kugelförmige schwarze Bombe mit der brennenden Lunte gegenseitig zuwerfen? 😉

Ich weiß zumindest, dass Transparenzen "schön" zu rendern alles andere als trivial ist. Egal welche BlendFuncs man verwendet, mit irgendeiner Konfiguration sieht's immer sch .. nicht so schön aus 🙁 Allein "die Dreiecke von hinten nach vorne rendern" ist schon nicht so einfach, und kann immernoch zu Artefakten führen. Eigentlich müßte man das auf Pixelebene machen. Bin neulich über Icare3D Blog: Fast and Accurate Single-Pass A-Buffer using OpenGL 4.0+ gestolpert, aber das schreibt man wohl nicht gerade mal an einem verregneten Nachmittag so einfach hin, wenn man nicht "Fancy" heißt (da ist sie wieder, die Bombe 😉 )
 
Hey, 😡 sind wir hier jetzt in einem Zeichentrickfilm wo wir uns die klassische kugelförmige schwarze Bombe mit der brennenden Lunte gegenseitig zuwerfen? 😉

lol 😀


Eigentlich müßte man das auf Pixelebene machen. Bin neulich über Icare3D Blog: Fast and Accurate Single-Pass A-Buffer using OpenGL 4.0+ gestolpert, [..]

Sehr interessanter Artikel! Ich kannte die ganze Seite bisher noch nicht, hab direkt mal ein Bookmark geworfen. 😉

Mir ist das vorher gar nicht eingefallen, aber jetzt wo Du "auf Pixelebene" erwähnst, vielleicht braucht Friedhelm gar kein Blending. Wenn es nur um die Frage transparent ja/nein geht, könnte man das auch relativ elegant mit einem normalen Fragmentshader lösen. Einfach im Shader den Alpha Wert prüfen und dann ggf. das Fragment komplett verwerfen. Das würde dann in etwa so aussehen. Vorteil ist, dass die Reihenfolge der Dreiecke keine Rolle mehr spielt, Nachteil ist, dass es beim Alpha keine Zwischenwerte mehr gibt. Bei Bedarf könnte ich dazu wohl auch ein kskb posten.

Aber eigentlich musste man wissen was Friedhelm am Ende genau haben will, evtl. gibt es noch bessere Lösungen.


[..] aber das schreibt man wohl nicht gerade mal an einem verregneten Nachmittag so einfach hin, wenn man nicht "Fancy" heißt (da ist sie wieder, die Bombe 😉 )

lol 😉. Bei mir würde das schon vorher scheitern, da meine Grafikkarte gar kein GL4 mag. GL3 ist also derzeit das höchste, was ich liefern kann. 😉

Btw. wer hat ne GL4 Grafikkarte? Wer will die Bombe? 😀

Gruß,
Fancy
 

Zurück
Oben