Hello everyone,
This is my very first post in here about JOGL so sorry in advance if I missed a step before posting in here. The problem I'm facing deals with VAO/VBO comprehension. As an example, I'd like to render a square in very specific (and not optimized) way : I would like to render two triangles with two different VAOs. The structure of my code looks like this : INIT :
// creation of two VAOs
My code for the rendering part is the following :
int[] tempVertexArrayObject = new int[2]; gl3.glGenVertexArrays(2, tempVertexArrayObject, 0); vaoId1 = tempVertexArrayObject[0]; vaoId2 = tempVertexArrayObject[1]; // creation of three VBOs IntBuffer idArray = GLBuffers.newDirectIntBuffer(3); gl3.glGenBuffers(3, idArray); positionBufferId = idArray.get(0); colorBufferId = idArray.get(1); indexBufferId = idArray.get(2); // binding and buffering the first VAO gl3.glBindVertexArray(vaoId1); // buffering positions gl3.glBindBuffer(GL.GL_ARRAY_BUFFER, positionBufferId); gl3.glBufferData(GL.GL_ARRAY_BUFFER, positionBuffer.capacity() * Buffers.SIZEOF_FLOAT, positionBuffer, GL.GL_STATIC_DRAW); gl3.glEnableVertexAttribArray(positionHandler); gl3.glVertexAttribPointer(positionHandler, 3, GL.GL_FLOAT, false, 0, 0); gl3.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); // buffering colors gl3.glBindBuffer(GL.GL_ARRAY_BUFFER, colorBufferId); gl3.glBufferData(GL.GL_ARRAY_BUFFER, colorBuffer.capacity() * Buffers.SIZEOF_FLOAT, colorBuffer, GL.GL_STATIC_DRAW); gl3.glEnableVertexAttribArray(colorHandler); gl3.glVertexAttribPointer(colorHandler, 4, GL.GL_FLOAT, false, 0, 0); gl3.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); // buffering indices gl3.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBufferId); gl3.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Buffers.SIZEOF_INT, indexBuffer, GL.GL_STATIC_DRAW); // binding and buffering the second VAO + buffering positions + ... // same as before, but gl.glBindVertexArray(vaoId2) instead of gl.glBindVertexArray(vaoId1), and with other buffers // that contain data for the other triangle
// Drawing the first triangle
Of course, I didn't put the part where I clear my background, I enable depth test, ...gl3.glBindVertexArray(vaoId1); gl3.glDrawElements(GL3.GL_TRIANGLES, 3, GL3.GL_UNSIGNED_INT, 0); gl3.glBindVertexArray(0); // Drawing the second triangle gl3.glBindVertexArray(vaoId2); gl3.glDrawElements(GL3.GL_TRIANGLES, 3, GL3.GL_UNSIGNED_INT, 0); gl3.glBindVertexArray(0); My problem is that only the second triangle is drawn, as if buffering data when VAO #2 is binded buffers data for VAO #1. Another strange behavior I can see is that when I only call the Drawing the first triangle instructions, I can see my second triangle. Any advice on something I misunderstood or on something I may do wrong ? Thanks in advance for your help. |
Administrator
|
Just had a look at this one :
https://wiki.jogamp.org/git/?p=jogl-demos.git;a=blob;f=src/demos/es2/RawGL2ES2demo.java;hb=HEAD but I'm not sure that it's the example you were talking about because I didn't find any glBindVertexArray call inside the source code. I searched for other examples from Xerxes (through the wiki and through his website) but I didn't find any occurence of glBindVertexArray either... |
Hope this sample can help, it's been a few years since I ran it so you need to change the import lines from the 'javax...' to jogamp and so on but it will show how to bind a VAO and a VBO. It should be rather straight forward to extend to bind several VBOs to the same VAO.
/* DO WHAT THE F*CK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 Copyright (C) 2014 Johan Maasing Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. DO WHAT THE F*CK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE F*CK YOU WANT TO. http://en.wikipedia.org/wiki/WTFPL */ package nu.zoom.corridors.client; import com.jogamp.common.nio.Buffers; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.FloatBuffer; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.opengl.DebugGL4; import javax.media.opengl.GL; import javax.media.opengl.GL4; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.TraceGL4; /** * * @author Johan Maasing <johan@zoom.nu> */ public class TriangleSample { // http://www.opengl.org/wiki/Vertex_Specification final int[] vas = new int[1]; final int[] vbos = new int[1]; private int shaderPosition; private int flatColorShaderProgram = 0; private Animator animator; private GLWindow glWindow; private boolean windowDestroyed = false; private static final float[] two_triangles = new float[]{ -1.0f, -1.0f, 0.1f, 1.0f, 1.0f, 0.1f, 0.0f, 1.0f, 0.1f, 1.0f, -1.0f, 0.7f, 0.0f, 1.0f, 0.7f, -1.0f, 1.0f, 0.7f }; private final String vertShader = "#version 410 core\n" + "in vec3 position;\n" + "out vec2 uv ;\n" + "void main(void)\n" + "{" + " uv = (position.xy + 1.0f)/2.0f;" + " gl_Position = vec4(position, 1.0f) ; \n" + "}"; private final String flatColorfragShader = "#version 410 core\n" + "in vec2 uv;\n" + "layout(location = 0) out vec4 fragColor ;\n" + "void main(void)\n" + "{" + " fragColor = vec4(gl_FragCoord.z,gl_FragCoord.z,gl_FragCoord.z, 1.0) ; \n" + "}"; public static void main(String[] args) throws Exception { TriangleSample app = new TriangleSample(); app.run(); } private void stop(String msg) { if (this.animator != null) { this.animator.stop(); } if (this.glWindow != null) { this.windowDestroyed = true; this.glWindow.destroy(); } System.out.println(msg); } private void run() throws Exception { final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL4)); caps.setBackgroundOpaque(true); caps.setDoubleBuffered(true); caps.setDepthBits(8); caps.setSampleBuffers(false); this.glWindow = GLWindow.create(caps); this.glWindow.setTitle("FBO Test"); this.glWindow.setSize(640, 480); this.glWindow.setUndecorated(false); this.glWindow.setPointerVisible(true); this.glWindow.setVisible(true); this.glWindow.setFullscreen(false); this.glWindow.setDefaultCloseOperation(WindowClosingProtocol.WindowClosingMode.DISPOSE_ON_CLOSE); this.glWindow.addWindowListener(new WindowAdapter() { @Override public void windowDestroyNotify(WindowEvent we) { if (!windowDestroyed) { stop("Window destroyed"); } } }); this.glWindow.addGLEventListener(new GLEventListener() { @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL gl = drawable.getGL(); gl.glViewport(x, y, width, height); } @Override public void init(GLAutoDrawable drawable) { GL gl = drawable.getGL(); if (gl.isGL4core()) { drawable.setGL(new TraceGL4(new DebugGL4(gl.getGL4()), System.out)); GL4 gL4 = drawable.getGL().getGL4(); try { TriangleSample.this.init(gL4); } catch (IOException ex) { stop(ex.getLocalizedMessage()); } } else { stop("Not a GL4 core context"); } } @Override public void dispose(GLAutoDrawable drawable) { } @Override public void display(GLAutoDrawable drawable) { GL4 gL4 = drawable.getGL().getGL4(); TriangleSample.this.display(gL4); } }); this.animator = new Animator(glWindow); this.animator.start(); } private void init(GL4 gl) throws IOException { gl.glClearColor(1.0f, 0.0f, 1.0f, 1.0f); gl.glClearDepthf(1.0f); gl.glEnable(GL4.GL_CULL_FACE); gl.glCullFace(GL4.GL_BACK); gl.glFrontFace(GL4.GL_CCW); gl.glEnable(GL4.GL_DEPTH_TEST); gl.glDepthFunc(GL4.GL_LEQUAL); // Compile and link the shader then query the shader for the location of the vertex input variable final ShaderCode vertexShader = compileShader(gl, vertShader, GL4.GL_VERTEX_SHADER); final ShaderCode flatColorFragmentShader = compileShader(gl, flatColorfragShader, GL4.GL_FRAGMENT_SHADER); this.flatColorShaderProgram = linkShader(gl, vertexShader, flatColorFragmentShader); this.shaderPosition = gl.glGetAttribLocation(this.flatColorShaderProgram, "position"); // Create the mesh createBuffer(gl, shaderPosition, two_triangles, 3); } public ShaderCode compileShader(final GL4 gl4, final String source, final int shaderType) throws IOException { final String[][] sources = new String[1][1]; sources[0] = new String[]{source}; ShaderCode shaderCode = new ShaderCode(shaderType, sources.length, sources); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final boolean compiled = shaderCode.compile(gl4, System.err); if (!compiled) { System.err.println("Unable to compile " + source); System.exit(1); } return shaderCode; } private int linkShader(GL4 gl, final ShaderCode vertexShader, final ShaderCode textureFragmentShader) throws GLException { ShaderProgram program = new ShaderProgram(); program.init(gl); program.add(vertexShader); program.add(textureFragmentShader); program.link(gl, System.out); final boolean validateProgram = program.validateProgram(gl, System.out); if (!validateProgram) { System.err.println("Unable to link shader"); System.exit(1); } return program.program(); } private void display(GL4 gl) { // Clear the default framebuffer gl.glBindFramebuffer(GL4.GL_DRAW_FRAMEBUFFER, 0); gl.glClear(GL4.GL_COLOR_BUFFER_BIT | GL4.GL_DEPTH_BUFFER_BIT); gl.glUseProgram(this.flatColorShaderProgram); gl.glBindVertexArray(this.vas[0]); gl.glEnableVertexAttribArray(this.shaderPosition); gl.glDrawArrays(GL4.GL_TRIANGLES, 0, 6); } public void createBuffer(final GL4 gl, final int shaderAttribute, float[] values, final int valuesPerVertex) { gl.glGenVertexArrays(this.vas.length, this.vas, 0); gl.glBindVertexArray(this.vas[0]); gl.glGenBuffers(this.vbos.length, this.vbos, 0); gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, this.vbos[0]); FloatBuffer fbVertices = Buffers.newDirectFloatBuffer(values); final int bufferSizeInBytes = values.length * Buffers.SIZEOF_FLOAT; gl.glBufferData(GL4.GL_ARRAY_BUFFER, bufferSizeInBytes, fbVertices, GL4.GL_STATIC_DRAW); gl.glVertexAttribPointer(shaderAttribute, valuesPerVertex, GL4.GL_FLOAT, false, 0, 0); } } |
Hi John, thanks a lot for your code.
I managed to change the import so that it uses the JOGL librairies and it works like a charm (pink background with 2 grey triangles). Then I tried to change a bit the way it works so that it would run with 2 differents VAOs. The changes I made are the following :
private static final float[] first_triangle = new float[]{
Two triangles to render = two calls to createBuffer like this :
-1.0f, -1.0f, 0.1f, 1.0f, 1.0f, 0.1f, 0.0f, 1.0f, 0.1f }; private static final float[] second_triangle = new float[]{ 1.0f, -1.0f, 0.7f, 0.0f, 1.0f, 0.7f, -1.0f, 1.0f, 0.7f };
// Create the mesh
The final parameter I added to the createBuffer method is used to know what VAO must be binded :
createBuffer(gl, shaderPosition, first_triangle, 3, 0); createBuffer(gl, shaderPosition, second_triangle, 3, 1);
public void createBuffer(final GL4 gl, final int shaderAttribute, float[] values, final int valuesPerVertex, int n) {
A last modification is made in the display method, to render not anymore 1 but 2 VAOs :
if (!vasSet) { gl.glGenVertexArrays(this.vas.length, this.vas, 0); vasSet = true; } gl.glBindVertexArray(this.vas[n]); // ... and so on
gl.glUseProgram(this.flatColorShaderProgram);
gl.glBindVertexArray(this.vas[0]); gl.glEnableVertexAttribArray(this.shaderPosition); gl.glDrawArrays(GL4.GL_TRIANGLES, 0, 3); gl.glBindVertexArray(this.vas[1]); gl.glEnableVertexAttribArray(this.shaderPosition); gl.glDrawArrays(GL4.GL_TRIANGLES, 0, 3); So now, I think I have a good example on which I can rely on to understand why I couldn't render properly multiple VAOs. Thank you so much, that thing was starting to drive me crazy... Nice copyright, by the way ^^ |
Free forum by Nabble | Edit this page |