Bonjour à tous.

En train de toucher à des shaders avec jogl, j'ai eu envie d'ajouter (pour que ça aille le plus vite possible, comme toujours) l'utilisation des VBOs.

J'ai trouvé quelques exemples qui en parlent et les utilisent, mais je n'arrive pas à afficher quoi que ce soit à l'heure actuelle... (http://www.game-lab.com/index.php?se...showtut&id=244 ou le tutorial de raptor, très bon, mais ça ne marche pas chez moi...)

Je suis alors tombé sur un exemple de vertex arrays qui ressemble beaucoup à une implémentation pour des vbos, sauf que... la transcription ne passe pas.

Voici le programme qui fonctionne (mais n'est pas optimisé) affichant un simple cube :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
import com.sun.opengl.util.Animator;
import com.sun.opengl.util.BufferUtil;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.FloatBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;
 
/*
 * Pour utiliser Opengl notre classe doit implémenter l'interface
 * GLEventListener. Cela va nous permettre d'utiliser les fonctionalités 
 * d'OpenGl avec le JPanel.
 * L'interface oblige a redefinir 4 méthodes:
 *  -- init() // Cette methode est appelée une fois ,elle va contenir l'initialisation
 *    -- display() 
 *        // Cette methode sera appélé en boucle et contiendra 
 *        // toute la partie affichage
 *    -- reshape() 
 *        // Cette methode est appelé quand il ya un redimensionnement de la fenêtre
 *        // afin d'eviter un affichage diforme
 *    -- displayChanged() 
 */
public class TestJogl2 implements GLEventListener {
 
    private int large;
    private float rotateT = 0.0f;
    private static final GLU glu = new GLU();
    /*pour resoudre le probleme du buffer*/
    private float vertices[];
    private float couleurs[];
    private FloatBuffer verticesBuff = BufferUtil.newFloatBuffer(24 * 3);
    private FloatBuffer couleursBuff = BufferUtil.newFloatBuffer(24 * 3);
 
    /**
     * GLEventListener renvoie un contexte (drawable)
     * Qui va nous permettre d'instancier un objet
     * de type GL à partir du quel on utilisera
     * les fonctions OpenGL.
     * */
    public void init(GLAutoDrawable drawable) {
        // Instanciation de l'objet GL 
        final GL gl = drawable.getGL();
 
        /*
         * Désactive la synchronisation verticale
         * indépendement de la plate forme utilisée
         */
        gl.setSwapInterval(1);
 
 
        //gl.glShadeModel(GL.GL_SMOOTH);
 
        /* Methode qui etablit vers quel couleur la fenetre sera 
         * vidé en l'occurence le noir 
         */
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
 
        /*
         * indique la valeur de profondeur (entre 0.0 et 1.0) 
         * utilisée par glClear pour effacer le tampon de profondeur
         */
        gl.glClearDepth(1.0f);
 
        gl.glEnable(GL.GL_DEPTH_TEST);
 
        gl.glDepthFunc(GL.GL_LEQUAL);
        /*Really Nice Perspective Calculations*/
        gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
 
        //Tableau avec les coordonnées des sommets
        vertices = new float[]{
            0.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f
        };
        couleurs = new float[]{
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f,
            1.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 1.0f,
            0.0f, 1.0f, 1.0f,
            0.0f, 1.0f, 1.0f,
            0.0f, 1.0f, 1.0f,
            1.5f, 0.5f, 0.0f,
            1.5f, 0.5f, 0.0f,
            1.5f, 0.5f, 0.0f,
            1.5f, 0.5f, 0.0f
        };
 
        gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL.GL_COLOR_ARRAY);
 
 
        gl.glVertexPointer(3, GL.GL_FLOAT, 0, verticesBuff);
        gl.glColorPointer(3, GL.GL_FLOAT, 0, couleursBuff);
 
 
 
    }
 
    public void reshape(GLAutoDrawable drawable, int x, int y, int width,
            int height) {
        final GL gl = drawable.getGL();
        if (height <= 0) {
            height = 1;
        }
        final float h = (float) width / (float) height;
 
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(50.0f, h, 2.0, 1000.0);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
    }
 
    public void display(GLAutoDrawable drawable) {
 
        GL gl = drawable.getGL();
 
        /*  glClear()
         *  efface les tampons à l'intérieur du "viewport
         *  glClear prend un seul argument qui est
         *  un masque de bits de plusieurs valeurs,
         *  chacune indiquant un tampon à effacer.
         *  
         *  GL_COLOR_BUFFER_BIT ==> Indique les tampons de couleurs 
         *                          actuellement utilisés en écriture.
         *  
         *  GL_DEPTH_BUFFER_BIT ==> Indique le tampon de profondeur 
         */
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
 
        // remplace la matrice courante par la matrice d'identité
        gl.glLoadIdentity();
 
        /*
         *Déplace l'origine du système de coordonnées au point spécifié 
         * La matrice courante est multipliée par cette matrice de translation
         * Si la matrice courante est soit GL_MODELVIEW soit GL_PROJECTION, tous 
         * les objets dessinés après l'appel à glTranslate subissent
         * cette translation.
         */
        gl.glTranslatef(0.0f, 0.0f, -5.0f);
 
        /*
         * calcule une matrice qui réalise la rotation d'angle degrés 
         * dans le sens trigonométrique autour du vecteur (x, y, z).
         * Meme principe que glTranslate
         */
        gl.glRotatef(300.0f, 250.0f, -155.0f, 115.0f);
        gl.glRotatef(rotateT, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
        gl.glRotatef(rotateT, 0.0f, 0.0f, 1.0f);
        gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
 
 
        /*forcé sinon les buffer sont vide*/
        verticesBuff.put(vertices);
        couleursBuff.put(couleurs);
        verticesBuff.rewind();
        couleursBuff.rewind();
        // La ligne magique
        gl.glDrawArrays(GL.GL_QUADS, 0, 24);
        /*
         * Force l'execution des commandes non encore achevées
         */
        gl.glFlush();
        rotateT += 0.4f * large / 300;
 
 
 
    }
 
    public void displayChanged(GLAutoDrawable drawable,
            boolean modeChanged, boolean deviceChanged) {
    }
 
    public static void main(String[] args) {
 
        /*Creation d'une fenetre
         * Utilisation d'un composant swing
         */
        JFrame frame = new JFrame("Esssai de java openGl");
 
 
        /*Creation d'un paneau
         * Utilisation d'un composant swing plutot qu'awt(GLCanvas)
         * C'est le paneau sur lequel on dessine
         */
        GLJPanel panel = new GLJPanel();
 
        /* On attache un "ecouteur" a la surface dessinable qui va capturer 
         * les évenements de la classe TestJOGL
         */
        TestJogl2 tmp = new TestJogl2();
        tmp.setLarge(400);
        panel.addGLEventListener(tmp);
        panel.repaint();
 
        /*
         * On ajoute le panneau a la fenetre
         * (layout par defaut (BorderLayout))
         */
        frame.add(panel);
 
 
        /*Creation de l'animator 
         * Il va gérer l'appel en boucle de la méthode display(), 
         * qui s'occupe de la creation de l'image 
         * L'animator crée un thread dans lequel les appels a display() 
         * sont effectués.Il va aussi se charger de faire 
         * une pause entre chaque rafraichissement de l'image pour 
         * permettre aux autres threads ou processus de s'executer.
         * On peut reduire la pause avec cette methode setRunAsFastAsPossible(true); 
         * Il possède deux méthodes principales : start() et stop()
         * pour lancer et arreter l'animation.
         */
        final Animator animator = new Animator(panel);
 
        /*
         * Bout de code habituel qui permet de fermer
         * la fenetre.Voir cours sur les api Graphiques
         */
        frame.addWindowListener(new WindowAdapter() {
 
            public void windowClosing(WindowEvent e) {
 
 
                // Creation d'un thread que se charge d'arreter l'annimator
                // avant l'arret du programme
                new Thread(new Runnable() {
 
                    public void run() {
                        animator.stop(); // stop l'affichage
                        System.exit(0);  // quite le programme
                    }
                }).start();
            }
        });
 
        /* 
         * Modifie la resolution de la fenetre
         */
        frame.setSize(400, 400);
 
        /*
         *Rend la fenetre visible 
         */
        frame.setVisible(true);
 
        /* 
         * Lance le thread qui se charge de l'affichage
         */
        animator.start();
    }
 
    public void setLarge(int large) {
        this.large = large;
    }
}
Ca marche bien, et tant mieux. Sauf que si je traduis ça en VBO, ça ne passe plus... (je dois en faire une traduction trop naïve...)

Voici le changement (dans la partie init / display ) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public void init(GLAutoDrawable drawable) {
        // Instanciation de l'objet GL 
        final GL gl = drawable.getGL();
 
        ...
 
        //Tableau avec les coordonnées des sommets
        vertices = new float[]{
            ...
        };
        System.out.format("%d vertex\n", vertices.length / 3);
        couleurs = new float[]{
            ...
        };
 
        float[] grid = new float[vertices.length + couleurs.length];
        for (int i = 0; i < grid.length; i++) {
            int x = i / 6;
            int y = i % 3;
            boolean flag = i % 6 <= 2;
            grid[i] = flag ? couleurs[x + y] : vertices[x + y];
        }
 
        int[] index = new int[vertices.length];
        for (int i = 0; i < index.length; i++) {
            index[i] = i;
        }
 
        // génération des deux buffers
        int[] buffer = new int[2];
        gl.glGenBuffers(2, buffer, 0);
 
        // buffer des vertices
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, buffer[0]);
        gl.glBufferData(GL.GL_ARRAY_BUFFER, grid.length, FloatBuffer.wrap(grid), GL.GL_STATIC_DRAW);
 
        // buffer des indices
        gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, buffer[1]);
        gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, index.length, IntBuffer.wrap(index), GL.GL_STATIC_DRAW);
 
        // enregistrement des buffers
        vboBuffer = buffer;
 
        // acceptation de l'état
        gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL.GL_COLOR_ARRAY);
    }
    private int[] vboBuffer;
 
    public void reshape(GLAutoDrawable drawable, int x, int y, int width,
            int height) {
        ...
    }
 
    public void display(GLAutoDrawable drawable) {
 
        GL gl = drawable.getGL();
 
        ...
        gl.glRotatef(300.0f, 250.0f, -155.0f, 115.0f);
        gl.glRotatef(rotateT, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
        gl.glRotatef(rotateT, 0.0f, 0.0f, 1.0f);
        gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
 
        // utilisation des données des buffers
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboBuffer[0]);
        gl.glVertexPointer(3, GL.GL_FLOAT, 6 * BufferUtil.SIZEOF_FLOAT, 3);
        gl.glColorPointer(3, GL.GL_FLOAT, 6 * BufferUtil.SIZEOF_FLOAT, 0);
 
        // liaison du buffer
        gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, vboBuffer[1]);
 
        // rendu de la géométrie
        gl.glDrawElements(GL.GL_TRIANGLES, vertices.length / 3, GL.GL_UNSIGNED_INT, 0);
        rotateT += 0.4f * large / 300;
    }
Je crée simplement un tableau contenant les couleurs + vertices par groupes de 6 (1 couleur + 1 vertice = 6 floats).

Puis je crée un bête tableau des indices qui liste bêtement les indices des vertices.

Ensuite, j'envoie ça à opengl. Et je l'affiche... mais... non, ça bloque fortement et j'ai l'erreur suivante (pas jolie du tout) :

#
# An unexpected error has been detected by Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0xb5360a80, pid=9281, tid=3041479568
#
# Java VM: Java HotSpot(TM) Client VM (10.0-b19 mixed mode, sharing linux-x86)
# Problematic frame:
# C 0xb5360a80
#
# An error report file with more information is saved as:
# /home/xion/.netbeans/workspace/JoglTest/hs_err_pid9281.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
Java Result: 134
Que fais-je de faux ?