# OpenGL - Transparenz



## BattleMaster246 (8. Jun 2010)

Wie kann man Polygone undurchsichtig machen. Denn wenn ich ein Polygon zeichne und danach eins, das hinter dem ersten liegt, legt dieses sich vor das erste.
Ich habs schon mit glColor4f() versucht, wo das 4. Argument auf 1.0f gestellt ist.


----------



## Evil-Devil (8. Jun 2010)

Du müsstest entweder die Reihenfolge in der du deine Polygone zeichnest entsprechend anpassen, also von hinten nach vorne und sonst den Tiefenpuffer kurzzeitig deaktivieren. Aber ich würde empfehlen die Objekte entsprechend zu sortieren, dann kannst du auch direkt sagen das verdeckte Objekte überhaupt nicht gezeichnet werden müssen.


----------



## Guest2 (8. Jun 2010)

Moin,



BattleMaster246 hat gesagt.:


> [..]Denn wenn ich ein Polygon zeichne und danach eins, das hinter dem ersten liegt, legt dieses sich vor das erste.[..]



auf die Schnelle, kann es sein, das Du eigentlich gl.glEnable(GL2.GL_DEPTH_TEST) suchst?

Gruß,
Fancy


----------



## BattleMaster246 (8. Jun 2010)

@Evil-Devil: Das mit dem sortieren geht leider nicht so gut, da sich die Kamera dreht.
@Guest:


```
gl.glEnable(GL.GL_DEPTH_TEST);
```

Dabei werden irgentwie Teile der Polygone bei der Kamerafahrt weiß und wenn die Kamera steht ist alles weiß.


----------



## Guest2 (8. Jun 2010)

Steht in Deiner display() ziemlich am Anfang gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);?

Hintergrund ist, in OpenGL ist der depth test default aus. Dadurch werden die Dreiecke in der Reihenfolge gezeichnet in der sie an OpenGL übergeben werden. Machst Du den Test mit glEnable an, wird die Tiefeninformation zur Verdeckungsberechnung genutzt. Damit das funktioniert muss der dazugehörige Z-Buffer jedes Frame gelöscht werden (dafür das glClear).
Wenn es dann immer noch nicht geht, fehlt irgendwo noch etwas anderes.  (Dann währe wohl ein bisschen Code hilfreich)

Gruß,
Fancy


----------



## BattleMaster246 (8. Jun 2010)

Es funktionier nun 


```
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
```

hab ich zu


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

gemacht. 




Hab aber noch ne Frage. Ich habe in einem Tutorial gelsen, wie man für einen gluSphere eine Textur erstellt. Den Code habe ich jedoch ein wenig umgeschrieben.


```
File va = new File("vav2.png");
        try {
            mcnet = TextureIO.newTexture(va, false);
        } catch (IOException ex) {
            System.out.println("# Texture loading failed: "+ex.getMessage()); System.exit(0);
        } catch (GLException ex) {
            System.out.println("# Texture loading failed: "+ex.getMessage()); System.exit(0);
        }
```

Das lässt sich auf einen gluSphere anwenden und funktioniert bei mir auch. Doch wie lässt sich das auf einen glVertex3f anwenden. Auf Englischen Tutorial seiten hatten die da "demos.common.GLDisplay" als Import, jedoch existiert dies nicht bei mir.


----------



## Guest2 (8. Jun 2010)

glVertex beschreibt die Koordinate eines einzelnen Vertex (Eckpunkt). Deine Fläche spannst Du ja aus mehreren Vertices (Eckpunkten) auf. Wenn Du die Fläche nun mit einer Textur beziehen willst, musst Du jedem Vertex auch eine Texturkoordinate zuweisen. Dies geht z.B. mit glTexCoord2f.

Grob sieht das dann für ein Dreieck etwa so aus:


```
gl.glBegin(GL.GL_TRIANGLES);
            
            gl.glTexCoord2f(0, 0);
            gl.glVertex3f(0, 0, 0);
            
            gl.glTexCoord2f(1, 0);
            gl.glVertex3f(1, 0, 0);
            
            gl.glTexCoord2f(1, 1);
            gl.glVertex3f(1, 1, 0);
            
            gl.glEnd();
```

Wichtig ist, dass glTexCoord immer vor glVertex aufgerufen wird.

Statt die Texturkoordinaten direkt als float anzugeben, kannst Du auch die utility Funktionen aus der Texture Klasse nutzen:


```
TextureCoords textureCoords = texture.getImageTexCoords();
            
            // [..]
            
            gl.glTexCoord2f(textureCoords.left(),  textureCoords.bottom());
            gl.glVertex3f(-1.0f, -1.0f, 1.0f);
            
            // usw.
```


(und wenn die Textur noch nicht gebunden ist, texture.bind() nicht vergessen)

(und ja, man kann auch alle Textur- und Vertextkoordinaten gesammelt als ein großes Array (Buffer) übergeben und damit tausende glTexCoord / glVertex Aufrufe einsparen, aber ka. ob Du das schon wissen willst )

Gruß,
Fancy


----------



## BattleMaster246 (8. Jun 2010)

Ja, das mit den Eckpunkten weis ich, nur habe ich bei gamedev einen ganz anderen Code gefunden.

Irgentwie funktioniert das nicht. Hier mein Code:


```
gl.glBegin(GL.GL_QUADS);
                gl.glEnable(GL.GL_TEXTURE_2D);
                mcnet2.enable();
                mcnet2.bind();
                gl.glColor3f(1,1,1);
                gl.glTexCoord2f(1,1); gl.glVertex3f(x+l-1,y,z);
                gl.glTexCoord2f(1,0); gl.glVertex3f(x+l-1,y+h,z);
                gl.glTexCoord2f(0,0); gl.glVertex3f(x+l-1,y+h,z+b);
                gl.glTexCoord2f(0,1); gl.glVertex3f(x+l-1,y,z+b);
                mcnet2.disable();
            gl.glEnd();
```


----------



## Guest2 (8. Jun 2010)

Das gl.glEnable(GL.GL_TEXTURE_2D) muss vor das glBegin, sinnvollerweise wahrscheinlich sogar in die init(). Dann sollte es gehen.

Gruß,
Fancy


----------



## BattleMaster246 (8. Jun 2010)

Jetzt funktionierts, danke. Aber wenn ich das in die Init()-Funktion schreibe, hat alles diese Textur.
So funktioniert es jetzt richtig:


```
gl.glEnable(GL.GL_TEXTURE_2D);
           mcnet2.enable();
           mcnet2.bind();
            gl.glBegin(GL.GL_QUADS);
                gl.glColor3f(1,1,1);
                gl.glTexCoord2f(1,1); gl.glVertex3f(x+l,y,z);
                gl.glTexCoord2f(1,0); gl.glVertex3f(x+l,y+h,z);
                gl.glTexCoord2f(0,0); gl.glVertex3f(x+l,y+h,z+b);
                gl.glTexCoord2f(0,1); gl.glVertex3f(x+l,y,z+b);
            gl.glEnd();
            mcnet2.disable();
            gl.glDisable(GL.GL_TEXTURE_2D);
```


----------



## Guest2 (9. Jun 2010)

BattleMaster246 hat gesagt.:


> [..]Aber wenn ich das in die Init()-Funktion schreibe, hat alles diese Textur.[..]



Dazu gibt es gl.glBindTexture(GL.GL_TEXTURE_2D, 0).

Allgemein hat die Art, wie Ressourcen in OpenGL geladen und gebunden werden eine ziemlich zentrale Bedeutung. Neben Texturen wirst Du später noch ne ganze Reihe weiterer "Dinge" laden / erstellen / binden. Deshalb kann es imho nicht schaden, auch die Texturen mal ohne Utilityklassen zu laden - meines Erachtens werden dann viele Dinge klarer (zumindest langfristig).

Deshalb, der Vollständigkeit halber:


```
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import javax.imageio.ImageIO;
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 Tex implements GLEventListener {

    private static final String IMAGE = "pic.png";

    private GL                  gl;
    private GLU                 glu;

    private int                 textureID;
    private final ByteBuffer    texture;
    private final int           width;
    private final int           height;


    public Tex() throws IOException {

        final BufferedImage image = ImageIO.read(this.getClass().getClassLoader().getResourceAsStream(IMAGE));

        width = image.getWidth();
        height = image.getHeight();

        final byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        texture = BufferUtil.newByteBuffer(data.length);
        texture.put(data);
        texture.rewind();

    }


    @Override
    public void init(final GLAutoDrawable drawable) {

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

        gl.glEnable(GL.GL_DEPTH_TEST);
        gl.glEnable(GL.GL_TEXTURE_2D);

        final IntBuffer buffer = BufferUtil.newIntBuffer(1);
        gl.glGenTextures(1, buffer);
        textureID = buffer.get(0);

        gl.glBindTexture(GL.GL_TEXTURE_2D, textureID);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
        gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);

        gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, width, height, 0, GL.GL_BGR, GL.GL_UNSIGNED_BYTE, texture);

    }


    @Override
    public void display(final GLAutoDrawable drawable) {

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

        gl.glBindTexture(GL.GL_TEXTURE_2D, textureID);
        gl.glBegin(GL.GL_TRIANGLES);
        gl.glTexCoord2f(1, 1);
        gl.glVertex3f(1, -1, -5);
        gl.glTexCoord2f(1, 0);
        gl.glVertex3f(1, 1, -5);
        gl.glTexCoord2f(0, 0);
        gl.glVertex3f(-1, 1, -5);
        gl.glEnd();
        gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

        gl.glColor3f(0.3f, 0.3f, 0.5f);
        gl.glBegin(GL.GL_TRIANGLES);
        gl.glVertex3f(-1, 1, -5);
        gl.glVertex3f(-1, -1, -5);
        gl.glVertex3f(1, -1, -5);
        gl.glEnd();

    }


    @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 Tex tex = new Tex();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);

        canvas.addGLEventListener(tex);
        frame.add(canvas);
        frame.setSize(500, 500);
        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


----------

