// This code example is created for educational purpose // by Thorsten Thormaehlen (contact: www.thormae.de). // It is distributed without any warranty. import java.nio.FloatBuffer; import java.nio.IntBuffer; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; import javax.swing.JFrame; import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.util.FPSAnimator; class Renderer { private GLU glu = new GLU(); public float t = 0.0f; private enum VAOs {Pyramid, Cube, numVAOs}; private enum VBOs {PyramidAll, CubePos, CubeCol, CubeIndices, numVBOs}; private int[] vaoID = new int[VAOs.numVAOs.ordinal()]; private int[] bufID = new int[VBOs.numVBOs.ordinal()]; private int pyramidVertNo = 0; private int cubeIndicesNo = 0; public void init(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL graphics context gl.glEnable(GL2.GL_DEPTH_TEST); // now we create 2 Vertex Array Objects (VAO): // one for a pyramid and one for a cube. // The pyramid uses one interleaved VBO // which is later drawn with "glDrawArrays", // while the cube uses 3 separate VBOs // which are later drawn with "glDrawElements" // create the Vertex Array Objects gl.glGenVertexArrays(VAOs.numVAOs.ordinal(), vaoID, 0); // generating Vertex Buffer Objects (VBO) gl.glGenBuffers(VBOs.numVBOs.ordinal(), bufID, 0); // specifying the pyramid VAO gl.glBindVertexArray(vaoID[VAOs.Pyramid.ordinal()]); float pyramidVertexData[] = { 0.0f, 0.0f, 2.0f, 1.0f, 0.0f, 0.0f, 0.0f, -0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 2.0f, 1.0f, 1.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -0.5f,-0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, }; pyramidVertNo = 12; // assuming the following structure of input vertex data // struct Vertex { // float position[3]; // float color[4]; // }; int floatItems = pyramidVertNo *(3+4); FloatBuffer pyramidVertexFB = Buffers.newDirectFloatBuffer(floatItems); pyramidVertexFB.put(pyramidVertexData); pyramidVertexFB.flip(); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, bufID[VBOs.PyramidAll.ordinal()]); gl.glBufferData(GL2.GL_ARRAY_BUFFER, pyramidVertexFB.capacity()*Buffers.SIZEOF_FLOAT, pyramidVertexFB, GL2.GL_STATIC_DRAW); int stride = (3+4)*Buffers.SIZEOF_FLOAT; int offset = 0; // position gl.glVertexPointer(3, GL2.GL_FLOAT, stride, offset); gl.glEnableClientState(GL2.GL_VERTEX_ARRAY); // color offset = 0 + 3*Buffers.SIZEOF_FLOAT; gl.glColorPointer(4, GL2.GL_FLOAT, stride, offset); gl.glEnableClientState(GL2.GL_COLOR_ARRAY); // specifying the cube VAO gl.glBindVertexArray(vaoID[VAOs.Cube.ordinal()]); float cubePosData[] = { -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f }; FloatBuffer cubePosFB = Buffers.newDirectFloatBuffer(8*3); cubePosFB.put(cubePosData); cubePosFB.flip(); float cubeColorData[] = { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; FloatBuffer cubeColorFB = Buffers.newDirectFloatBuffer(8*3); cubeColorFB.put(cubeColorData); cubeColorFB.flip(); int cubeIndicesData[] = { 0, 1, 2, 3, 0, 4, 5, 1, 4, 7, 6, 5, 2, 6, 7, 3, 1, 5, 6, 2, 3, 7, 4, 0 }; cubeIndicesNo = 24; IntBuffer cubeIndicesFB = Buffers.newDirectIntBuffer(cubeIndicesNo); cubeIndicesFB.put(cubeIndicesData); cubeIndicesFB.flip(); // position gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, bufID[VBOs.CubePos.ordinal()]); gl.glBufferData(GL2.GL_ARRAY_BUFFER, cubePosFB.capacity()*Buffers.SIZEOF_FLOAT, cubePosFB, GL2.GL_STATIC_DRAW); gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0); gl.glEnableClientState(GL2.GL_VERTEX_ARRAY); // color gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, bufID[VBOs.CubeCol.ordinal()]); gl.glBufferData(GL2.GL_ARRAY_BUFFER, cubeColorFB.capacity()*Buffers.SIZEOF_FLOAT, cubeColorFB, GL2.GL_STATIC_DRAW); gl.glColorPointer(3, GL2.GL_FLOAT, 0, 0); gl.glEnableClientState(GL2.GL_COLOR_ARRAY); // indices gl.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, bufID[VBOs.CubeIndices.ordinal()]); gl.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, cubeIndicesFB.capacity()*Buffers.SIZEOF_INT, cubeIndicesFB, GL2.GL_STATIC_DRAW); } public void resize(GLAutoDrawable d, int w, int h) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glViewport(0, 0, w, h); gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); glu.gluPerspective(60.0, (float)w/(float)h, 0.1, 50.0); } public void display(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); // set camera glu.gluLookAt(3.0, -1.0, 4.5, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0); // draw scene gl.glRotatef(t, 0.0f, 0.0f, 1.0f); // bind cube VAO gl.glBindVertexArray(vaoID[VAOs.Cube.ordinal()]); // render data gl.glDrawElements(GL2.GL_QUADS, cubeIndicesNo, GL2.GL_UNSIGNED_INT, 0); gl.glTranslatef(0.0f, 0.0f, 1.0f); // bind pyramid VAO gl.glBindVertexArray(vaoID[VAOs.Pyramid.ordinal()]); // render data gl.glDrawArrays(GL2.GL_TRIANGLES, 0, pyramidVertNo); gl.glFlush(); } } class MyGui extends JFrame implements GLEventListener { private Renderer renderer; public void createGUI() { setTitle("Vertex Array Object (VAO) Demo"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); GLProfile glp = GLProfile.getDefault(); GLCapabilities caps = new GLCapabilities(glp); GLCanvas canvas = new GLCanvas(caps); setSize(320, 320); getContentPane().add(canvas); final FPSAnimator ani = new FPSAnimator(canvas, 60, true); canvas.addGLEventListener(this); setVisible(true); renderer = new Renderer(); ani.start(); } @Override public void init(GLAutoDrawable d) { renderer.init(d); } @Override public void reshape(GLAutoDrawable d, int x, int y, int width, int height) { renderer.resize(d, width, height); } @Override public void display(GLAutoDrawable d) { float offset = 1.0f; renderer.t += offset; renderer.display(d); } @Override public void dispose(GLAutoDrawable d) { } } public class Vao { public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { MyGui myGUI = new MyGui(); myGUI.createGUI(); } }); } }