Prinzipielle Frage an den TE: Wieso werden die vier kleineren Texturen nicht gleich direkt als eine große abgespeichert und zb. via glTexSubImage verwendet?
Warte mal bis Fancy vorbeischaut, der schüttelt dir das aus dem Ärmel![]()
Nett gemeintaber ich brauche das reale kopieren in eine neue Textur. Ich habe gedacht das geht einfach irgendwie mit Pixel-Copy innerhalb der Grafikkarte mit GL Befehlen.
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.FloatBuffer;
import java.nio.IntBuffer;
import javax.imageio.ImageIO;
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 Merge implements GLEventListener {
    private static final String  IMAGES[]       = { "test.png", "test2.png" };
    private static final float[] QUAD_XYZ       = new float[] { -0.5f, -0.5f, 0f, +0.5f, -0.5f, 0f, +0.5f, +0.5f, 0f, -0.5f, +0.5f, 0f };
    private static final float[] QUAD_ST        = new float[] { 0f, 0f, 1f, 0f, 1f, 1f, 0f, 1f };
    private final FloatBuffer    vaXYZ          = GLBuffers.newDirectFloatBuffer(QUAD_XYZ);
    private final FloatBuffer    vaST           = GLBuffers.newDirectFloatBuffer(QUAD_ST);
    private final IntBuffer      buffer         = GLBuffers.newDirectIntBuffer(1);
    private final int[]          textureHandles = new int[IMAGES.length + 1];
    private GL2                  gl;
    private GLU                  glu;
    private int createTexture(final String resource) {
        try {
            final BufferedImage image = ImageIO.read(getClass().getClassLoader().getResourceAsStream(resource));
            final byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
            final ByteBuffer texture = GLBuffers.newDirectByteBuffer(data);
            gl.glGenTextures(1, buffer);
            final int textureHandle = buffer.get(0);
            gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
            gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);
            gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGB, image.getWidth(), image.getHeight(), 0, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, texture);
            return textureHandle;
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }
    private int merge(final int textureHandle1, final int textureHandle2, final int width, final int height) {
        gl.glGenFramebuffers(1, buffer);
        final int frameBufferHandle = buffer.get(0);
        gl.glGenRenderbuffers(1, buffer);
        final int renderBufferHandle = buffer.get(0);
        gl.glGenTextures(1, buffer);
        final int textureHandle = buffer.get(0);
        gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferHandle);
        gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, renderBufferHandle);
        gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle);
        gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGB, width, height, 0, GL2.GL_RGB, GL2.GL_UNSIGNED_BYTE, null);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
        gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER, GL2.GL_COLOR_ATTACHMENT0, GL2.GL_TEXTURE_2D, textureHandle, 0);
        gl.glRenderbufferStorage(GL2.GL_RENDERBUFFER, GL2.GL_DEPTH_COMPONENT24, width, height);
        gl.glFramebufferRenderbuffer(GL2.GL_FRAMEBUFFER, GL2.GL_DEPTH_ATTACHMENT, GL2.GL_RENDERBUFFER, renderBufferHandle);
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glPushMatrix();
        gl.glLoadIdentity();
        gl.glOrthof(-1f, 1f, -1f, 1f, -1f, 1f);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glPushMatrix();
        gl.glLoadIdentity();
        gl.glViewport(0, 0, width, height);
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        gl.glScalef(1f, 2f, 1f);
        gl.glTranslatef(-0.5f, 0.0f, 0.0f);
        gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle1);
        gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, vaST);
        gl.glVertexPointer(3, GL2.GL_FLOAT, 0, vaXYZ);
        gl.glDrawArrays(GL2.GL_QUADS, 0, vaXYZ.capacity());
        gl.glTranslatef(1.0f, 0.0f, 0.0f);
        gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle2);
        gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, vaST);
        gl.glVertexPointer(3, GL2.GL_FLOAT, 0, vaXYZ);
        gl.glDrawArrays(GL2.GL_QUADS, 0, vaXYZ.capacity());
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glPopMatrix();
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glPopMatrix();
        gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, 0);
        gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
        buffer.put(0, renderBufferHandle);
        gl.glDeleteRenderbuffers(GL2.GL_RENDERBUFFER, buffer);
        buffer.put(0, frameBufferHandle);
        gl.glDeleteFramebuffers(GL2.GL_FRAMEBUFFER, buffer);
        return textureHandle;
    }
    @Override
    public void init(final GLAutoDrawable drawable) {
        gl = drawable.getGL().getGL2();
        glu = new GLU();
        gl.glEnable(GL2.GL_DEPTH_TEST);
        gl.glEnable(GL2.GL_TEXTURE_2D);
        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
        for (int i = 0; i < IMAGES.length; i++)
            textureHandles[i] = createTexture(IMAGES[i]);
        textureHandles[IMAGES.length] = merge(textureHandles[0], textureHandles[1], 1024, 1024);
    }
    @Override
    public void display(final GLAutoDrawable drawable) {
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();
        gl.glTranslatef(-3f, 0.0f, -5.0f);
        for (int i = 0; i < IMAGES.length + 1; i++) {
            gl.glTranslatef(+1.5f, 0.0f, 0.0f);
            gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandles[i]);
            gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, vaST);
            gl.glVertexPointer(3, GL2.GL_FLOAT, 0, vaXYZ);
            gl.glDrawArrays(GL2.GL_QUADS, 0, vaXYZ.capacity());
        }
    }
    @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 Merge base = new Merge();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);
        canvas.addGLEventListener(base);
        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();
    }
}
	theoretisch könnte man das auch per shader machen den man das asci alphabet (für adavnced das unicode) mithilfe on uniforms übergibt ^^ der das dann selber auf den fragmentshader berechnet. Wäre mal nen interessantes Projekt, aber wie über mir schon gesagt, text ist eigentlich nicht das problem. Ich empfehle halt alle befelhe als Displaylist zu speichern, dann gehen die aufrufe auch super schnellPerformance Probleme bei 2-3k zeichen wenn du die als eigene texture hast entstehen nur durch die von dir manuell aufgerufenen draw calls und texturestate changes.
Hat jemand dafür eine Lösung?Wenn ich das obige Beispiel unter LWJGL laufen lassen möcht... was ist die Alternative zu "GLBuffers" ?
Du hast doch nur eine Textur und deinen Text. Auf der Textur liegen die Buchstaben und Zahlen und Sonderzeichen herum. Mittels derer Position kannst du dir die gewünschten Texel nehmen und auf einem Quad zeichnen.Aber ist es nicht performanter, wenn die Grafikkarte nur 1 Textur mit dem ganzen Text darstellen muss? Da spart man sich doch den ganzen Darstelleungskram von 2-3K Buchstaben die durch die Grafikkarte sausen müssten. Man stelle sich eine Textverarbeitung in OpenGL vor. Ich denke da ist es mit einer Textur besser.
jeden Buchstaben ein Rechteck auf dem Screen zeichnen. Das geht natürlich bei langem Text nicht. Denn bei spätestens 2.500-5.000 wirds eng (jedenfalls bei meinem Rechner).
Kann mir einer einen Link zu aktuellen compilierten JOGL 2 (July 2010) Dateien geben (Mac)?
Wenn ich das obige Beispiel unter LWJGL laufen lassen möcht... was ist die Alternative zu "GLBuffers" ?
FloatBuffer     vaXYZ          = GLBuffers.newDirectFloatBuffer(QUAD_XYZ);
	FloatBuffer vaXYZ = ByteBuffer.allocateDirect(Float.SIZE / Byte.SIZE * QUAD_XYZ.length).order(ByteOrder.nativeOrder()).asFloatBuffer();
vaXYZ.put(QUAD_XYZ);
vaXYZ.rewind();
	theoretisch könnte man das auch per shader machen
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.FloatBuffer;
import java.nio.IntBuffer;
import javax.imageio.ImageIO;
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 Text implements GLEventListener {
    private static int           WIDTH       = 10;
    private static int           HEIGHT      = 1;
    private static final String staticVS = "" +
    "#version 130\n" +
    "uniform int text[" + WIDTH * HEIGHT + "];" +
    "out vec2 st;" +
    "void main(void) " +
    "{" +
    "  int i = text[gl_VertexID / 6];" +
    "  float s1 = i * (1 / 26.0) - 0.002;" +
    "  float s2 = s1 + (1 / 26.0 - 0.002);" +
    "  st = vec2(s1, 1);" +
    "  if((gl_VertexID % 6) == 1) st = vec2(s2, 1);" +
    "  else if((gl_VertexID % 6) == 2) st = vec2(s2, 0);" +
    "  else if((gl_VertexID % 6) == 3) st = vec2(s1, 1);" +
    "  else if((gl_VertexID % 6) == 4) st = vec2(s2, 0);" +
    "  else if((gl_VertexID % 6) == 5) st = vec2(s1, 0);" +
    "  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" +
    "}";
    private static final String staticFS = "" +
    "uniform sampler2D tex;" +
    "in vec2 st;" +
    "void main (void)" +
    "{" +
    "  gl_FragColor = texture2D(tex, st);" +
    "}";
    private static final String  IMAGE       = "abc.png";
    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 IntBuffer      buffer      = GLBuffers.newDirectIntBuffer(1);
    private final IntBuffer      text        = GLBuffers.newDirectIntBuffer(WIDTH * HEIGHT);
    private final FloatBuffer    va;
    private int                  shaderHandle;
    private int                  textureHandle;
    private int                  textHandle;
    private GL2                  gl;
    private GLU                  glu;
    public Text() {
        va = GLBuffers.newDirectFloatBuffer(TRIANGLE_XY.length * WIDTH * HEIGHT);
        for (int y = 0; y < HEIGHT; y++)
            for (int x = 0; x < WIDTH; x++)
                for (int i = 0; i < TRIANGLE_XY.length; i++)
                    if (i % 2 == 0)
                        va.put((TRIANGLE_XY[i] + x + 0.5f - WIDTH / 2.0f) / WIDTH);
                    else
                        va.put((TRIANGLE_XY[i] + y + 0.5f - HEIGHT / 2.0f) / HEIGHT);
        va.rewind();
    }
    private int createTexture(final String resource) {
        try {
            final BufferedImage image = ImageIO.read(getClass().getClassLoader().getResourceAsStream(resource));
            final byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
            final ByteBuffer texture = GLBuffers.newDirectByteBuffer(data);
            gl.glGenTextures(1, buffer);
            final int textureHandle = buffer.get(0);
            gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
            gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);
            gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGBA, image.getWidth(), image.getHeight(), 0, GL.GL_RGBA, GL2.GL_UNSIGNED_INT_8_8_8_8, texture);
            return textureHandle;
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }
    private int createShader() {
        final int vHandle = gl.glCreateShader(GL2.GL_VERTEX_SHADER);
        gl.glShaderSource(vHandle, 1, new String[] { staticVS }, new int[] { staticVS.length() }, 0);
        gl.glCompileShader(vHandle);
        final int fHandle = gl.glCreateShader(GL2.GL_FRAGMENT_SHADER);
        gl.glShaderSource(fHandle, 1, new String[] { staticFS }, new int[] { staticFS.length() }, 0);
        gl.glCompileShader(fHandle);
        final int spHandle = gl.glCreateProgram();
        gl.glAttachShader(spHandle, vHandle);
        gl.glAttachShader(spHandle, fHandle);
        gl.glLinkProgram(spHandle);
        gl.glValidateProgram(spHandle);
        gl.glUseProgram(spHandle);
        textHandle = gl.glGetUniformLocation(spHandle, "text");
        return spHandle;
    }
    @Override
    public void init(final GLAutoDrawable drawable) {
        gl = drawable.getGL().getGL2();
        glu = new GLU();
        gl.glEnable(GL2.GL_DEPTH_TEST);
        gl.glEnable(GL2.GL_TEXTURE_2D);
        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
        shaderHandle = createShader();
        textureHandle = createTexture(IMAGE);
    }
    private void setText(final String value) {
        for (int i = 0; i < value.length() && i < text.capacity(); i++)
            text.put(i, value.charAt(i) - 'A');
        gl.glUseProgram(shaderHandle);
        gl.glUniform1iv(textHandle, value.length(), text);
    }
    @Override
    public void display(final GLAutoDrawable drawable) {
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();
        gl.glTranslatef(0f, 0.0f, -2.0f);
        gl.glScalef(1f, 0.2f, 1f);
        setText("HELLOWORLD");
        gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle);
        gl.glVertexPointer(2, GL2.GL_FLOAT, 0, va);
        gl.glDrawArrays(GL2.GL_TRIANGLES, 0, va.capacity());
    }
    @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 Text base = new Text();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);
        canvas.addGLEventListener(base);
        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();
    }
}
	
	Moin,
Gruß,
Fancy
Das Ergebnis ist dann:
![]()
(Man sieht, ich habe mir beim erstellen der ABC Textur nicht sonderlich viel Mühe gegeben.Unter anderem auch nur Großbuchstaben und kein Leerzeichen. Wollte man das ordentlich machen, werden insbesondere nicht monospace Schriftarten schwierig.)
Wer es trotzdem ausprobieren möchte, hier die abc.png
Gruß,
Fancy
zum Merge Code:
Da bekomme ich das was Du auf dem Screenshot siehst (ein zerstörtes Bild). Woran könnte das liegen? Ich habe zwei 1024x1024 PNG's verwendet.
Auch beim 2. Beispiel "Text" sehe ich nur Schwarz (leer).
   private void printShaderError(final int handle) {
        gl.glGetShaderiv(handle, GL2.GL_COMPILE_STATUS, buffer);
        if (buffer.get(0) != 1) {
            gl.glGetShaderiv(handle, GL2.GL_INFO_LOG_LENGTH, buffer);
            final ByteBuffer byteBuffer = GLBuffers.newDirectByteBuffer(buffer.get(0));
            gl.glGetShaderInfoLog(handle, byteBuffer.capacity(), buffer, byteBuffer);
            System.err.println("\nshader compile error: " + handle);
            for (int i = 0; i < buffer.get(0); i++)
                System.err.print((char) byteBuffer.get(i));
        }
    }
    private int createShader() {
        final int vHandle = gl.glCreateShader(GL2.GL_VERTEX_SHADER);
        gl.glShaderSource(vHandle, 1, new String[] { staticVS }, new int[] { staticVS.length() }, 0);
        gl.glCompileShader(vHandle);
        printShaderError(vHandle);
        final int fHandle = gl.glCreateShader(GL2.GL_FRAGMENT_SHADER);
        gl.glShaderSource(fHandle, 1, new String[] { staticFS }, new int[] { staticFS.length() }, 0);
        gl.glCompileShader(fHandle);
        printShaderError(fHandle);
        final int spHandle = gl.glCreateProgram();
        gl.glAttachShader(spHandle, vHandle);
        gl.glAttachShader(spHandle, fHandle);
        gl.glLinkProgram(spHandle);
        gl.glValidateProgram(spHandle);
        gl.glUseProgram(spHandle);
        textHandle = gl.glGetUniformLocation(spHandle, "text");
        return spHandle;
    }
	Anbei die 2 PNG's für "Merge" (im Original sind diese 1024x1024)
Schalte ich Transparenz bei beien PNG's aus, erhalte ich Screenshot 3
Hier die Ausgabe von "Text":
shader compile error: 1
ERROR: 0:1: '' : Version number not supported by GL2
ERROR: 0:2: 'out' : syntax error syntax error
ERROR: Parser found no code to compile in source strings.
shader compile error: 2
ERROR: 0:1: 'in' : syntax error syntax error
ERROR: Parser found no code to compile in source strings.
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.FloatBuffer;
import java.nio.IntBuffer;
import javax.imageio.ImageIO;
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 Text2 implements GLEventListener {
    private static int           WIDTH       = 5;
    private static int           HEIGHT      = 2;
    private static final String  IMAGE       = "abc.png";
    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 IntBuffer      buffer      = GLBuffers.newDirectIntBuffer(1);
    private final FloatBuffer    vaXY;
    private final FloatBuffer    vaST;
    private int                  textureHandle;
    private GL2                  gl;
    private GLU                  glu;
    public Text2() {
        vaXY = GLBuffers.newDirectFloatBuffer(TRIANGLE_XY.length * WIDTH * HEIGHT);
        vaST = GLBuffers.newDirectFloatBuffer(TRIANGLE_XY.length * WIDTH * HEIGHT);
        for (int y = HEIGHT - 1; y >= 0; y--)
            for (int x = 0; x < WIDTH; x++)
                for (int i = 0; i < TRIANGLE_XY.length; i++)
                    if (i % 2 == 0)
                        vaXY.put((TRIANGLE_XY[i] + x + 0.5f - WIDTH / 2.0f) / WIDTH);
                    else
                        vaXY.put((TRIANGLE_XY[i] + y + 0.5f - HEIGHT / 2.0f) / HEIGHT);
        vaXY.rewind();
    }
    private int createTexture(final String resource) {
        try {
            final BufferedImage image = ImageIO.read(getClass().getClassLoader().getResourceAsStream(resource));
            final byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
            final ByteBuffer texture = GLBuffers.newDirectByteBuffer(data);
            gl.glGenTextures(1, buffer);
            final int textureHandle = buffer.get(0);
            gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
            gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);
            gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGBA, image.getWidth(), image.getHeight(), 0, GL.GL_RGBA, GL2.GL_UNSIGNED_INT_8_8_8_8, texture);
            return textureHandle;
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public void init(final GLAutoDrawable drawable) {
        gl = drawable.getGL().getGL2();
        glu = new GLU();
        gl.glEnable(GL2.GL_DEPTH_TEST);
        gl.glEnable(GL2.GL_TEXTURE_2D);
        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
        textureHandle = createTexture(IMAGE);
    }
    private void setText(final String value) {
        for(int gl_VertexID = 0; gl_VertexID  < value.length() * 6 && gl_VertexID < vaXY.capacity(); gl_VertexID++){
            final int i = value.charAt(gl_VertexID / 6) - 'A';
            final float s1 = (float) (i * (1 / 26.0) - 0.002);
            final float s2 = (float) (s1 + (1 / 26.0 - 0.002));
            float s = s1;
            float t = 1;
            if((gl_VertexID % 6) == 1) { s = s2; t = 1; }
            else if((gl_VertexID % 6) == 2) { s = s2; t = 0; }
            else if((gl_VertexID % 6) == 3) { s = s1; t = 1; }
            else if((gl_VertexID % 6) == 4) { s = s2; t = 0; }
            else if((gl_VertexID % 6) == 5) { s = s1; t = 0; }
            vaST.put(gl_VertexID * 2, s);
            vaST.put(gl_VertexID * 2 + 1, t);
        }
    }
    @Override
    public void display(final GLAutoDrawable drawable) {
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();
        gl.glTranslatef(0f, 0.0f, -2.0f);
        gl.glScalef(1f, 0.2f, 1f);
        setText("HELLOWORLD");
        gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle);
        gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, vaST);
        gl.glVertexPointer(2, GL2.GL_FLOAT, 0, vaXY);
        gl.glDrawArrays(GL2.GL_TRIANGLES, 0, vaXY.capacity());
    }
    @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 Text2 base = new Text2();
        final Frame frame = new Frame();
        final GLCanvas canvas = new GLCanvas();
        final Animator animator = new Animator(canvas);
        canvas.addGLEventListener(base);
        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();
    }
}