Hello Guest

Unable to get glDrawElements to work.

  • 13 Replies
  • 10421 Views
Unable to get glDrawElements to work.
« on: June 10, 2015, 16:54:48 »
My shader works fine, and I can draw with glDrawArrays, but am having a hard time getting glDrawElements to work. The clearcolor is showing up across the whole window, but nothing else is working. I'm using scala, which supports java libraries natively. I've tried looking for similar errors to no avail. Code:

Code: [Select]
    import org.lwjgl.Sys
    import org.lwjgl.glfw._
    import org.lwjgl.opengl._
    import java.nio.ByteBuffer
    import java.nio.FloatBuffer
    import  org.lwjgl.glfw.Callbacks._
    import  org.lwjgl.glfw.GLFW._
    import  org.lwjgl.opengl.GL11._
    import  org.lwjgl.opengl.GL15._
    import  org.lwjgl.opengl.GL20._
    import  org.lwjgl.opengl.GL30._
    import  org.lwjgl.system.MemoryUtil._
    import  org.lwjgl.BufferUtils._
    import hands._
    import javafx.scene.shape.CullFace
   
   
    class Test {
       
        val vertex_positions:  Array[Float] = Array(
         -1.0f, -1.0f, 0.0f, 
         1.0f, -1.0f, 0.0f,
         -1.0f, 1.0f, 0.0f
        )
       
        val vertex_indices: Array[Int] = Array(
          0, 1, 2   
        )
   
        // We need to strongly reference callback instances.
        val errorCallback: GLFWErrorCallback = Callbacks.errorCallbackPrint();
        val keyCallback: GLFWKeyCallback = new GLFWKeyCallback() {
          @Override
          def invoke(window: Long , key: Int, scancode: Int , action: Int , mods: Int) {
            if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
              glfwSetWindowShouldClose(window, GL_TRUE) // We will detect this in our rendering loop
          }
        }
       
        val WIDTH = 800
        val HEIGHT = 600
   
        def run(): Unit = {
        System.out.println("Hello LWJGL " + Sys.getVersion() + "!") 
   
        try {
   
        val vertBuffer = hands.createFlippedBuffer(vertex_positions)
        val indexBuffer = hands.createFlippedBuffer(vertex_indices)
   
        // Setup an error callback. The default implementation
        // will print the error message in System.err.
        glfwSetErrorCallback(errorCallback)
   
        // Initialize GLFW. Most GLFW functions will not work before doing this.
        if ( glfwInit() != GL_TRUE )
        throw new IllegalStateException("Unable to initialize GLFW")
   
        // Configure our window
        glfwDefaultWindowHints() // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GL_FALSE) // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GL_TRUE) // the window will be resizable
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)
   
        // Create the window
        val window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL)
        if ( window == NULL )
        throw new RuntimeException("Failed to create the GLFW window")
   
        // Setup a key callback. It will be called every time a key is pressed, repeated or released.       
        glfwSetKeyCallback(window, keyCallback)
   
        // Get the resolution of the primary monitor
        val vidmode: ByteBuffer = glfwGetVideoMode(glfwGetPrimaryMonitor())
        // Center our window
        glfwSetWindowPos(
        window,
        (GLFWvidmode.width(vidmode) - WIDTH) / 2,
        (GLFWvidmode.height(vidmode) - HEIGHT) / 2)
     
      // Make the OpenGL context current
      glfwMakeContextCurrent(window)
      // Enable v-sync
      glfwSwapInterval(1)
     
      // Make the window visible
      glfwShowWindow(window)
     
      // This line is critical for LWJGL's interoperation with GLFW's
      // OpenGL context, or any context that is managed externally.
      // LWJGL detects the context that is current in the current thread,
      // creates the ContextCapabilities instance and makes the OpenGL
      // bindings available for use.
      GLContext.createFromCurrent()
     
                                //create shader, and use it as program
                                val shader = new Shader()
        glUseProgram(shader.program)
             
        val vao = glGenVertexArrays()
        glBindVertexArray(vao)
       
        val vbo = glGenBuffers()
        glBindBuffer(GL_ARRAY_BUFFER, vbo)
                                //http://javadoc.lwjgl.org/org/lwjgl/opengl/GL15.html#glBufferData%28int,%20java.nio.FloatBuffer,%20int%29
        glBufferData(GL_ARRAY_BUFFER,  vertBuffer, GL_STATIC_DRAW)
             
                                 //this function accepts false instead of GL_FALSE
        glVertexAttribPointer(0, 3, GL_FLOAT, false , 0, 0)
                                glEnableVertexAttribArray(0)
             
        val ebo = glGenBuffers()
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
                                 //http://javadoc.lwjgl.org/org/lwjgl/opengl/GL15.html#glBufferData%28int,%20java.nio.ShortBuffer,%20int%29
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW)
   
   
        // Set the clear color
        glClearColor(0, 0, 0.4f, 1)
        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
                               //glfwWindowShouldClose produces a GL_FALSE, instead of a boolean value
        while ( glfwWindowShouldClose(window) == GL_FALSE ) {
   
        glClear(GL_COLOR_BUFFER_BIT) // clear the framebuffer
   
        glBindVertexArray(vao)
        glEnableVertexAttribArray(0)
   
                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
               
                   
             GL11.glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0)
             //glDrawArrays(GL_TRIANGLES, 0, 9)
       
                            glfwSwapBuffers(window); // swap the color buffers
       
                              // Poll for window events. The key callback above will only be
              // invoked during this call.
             glfwPollEvents();
            }
     
                // Release window and window callbacks           
                glfwDestroyWindow(window)
                keyCallback.release()
            } finally {
                // Terminate GLFW and release the GLFWerrorfun
                glfwTerminate()
                errorCallback.release()
            }
        }
       
    }
   
    object main{
         
          def main( args: Array[String] ) = {
              new Test().run();
          }
        }
Sorry about the weird formatting towards the bottom, something is going on with my tabs.
Thank you for your help.
« Last Edit: June 10, 2015, 16:56:24 by Teracon »

*

Kai

Re: Unable to get glDrawElements to work.
« Reply #1 on: June 10, 2015, 17:10:12 »
Hm... cannot see any obvious error.
The only thing I can think of is hands.createFlippedBuffer() not working as expected when being called with an int array.
Make sure that this method overload really creates a direct ByteBuffer (or an IntBuffer view) with native byte order and that it is filled with integers (i.e. via a IntBuffer view or via the putInt() methods on the ByteBuffer) and that this buffer is really flipped. Preferably use LWJGL's BufferUtils utility class to do that.
I do not expect it, but if you are unsure about possible GL errors occurring, you can enable debug outputs like how it's done in the Gears Demo.
Other than that you have a few redundant GL calls, such as the glEnableVertexAttribArray in line 130 and the glBindBuffer below that in line 132.
Note that vertex attribute enable status and the buffer bindings are part of the VAO state, which you initially set in line 112 and 115, respectively.
Oh and that glDrawArrays, which is currently commented, should use 3 instead of the 9.

Re: Unable to get glDrawElements to work.
« Reply #2 on: June 10, 2015, 17:36:43 »
This is the Int overload for hands:
Code: [Select]
    def createFlippedBuffer(bufferArray: Array[Int]) = {
   
    val byteBuffer = createIntBuffer(bufferArray.length)
    byteBuffer.put(bufferArray)
    byteBuffer.flip()
    byteBuffer
   
  }

Which leads me to believe I'm not actually loading the Ints correctly, but it appears to be using the same logic used in other programs I've seen for defining indices. I'll set up the debug info and see if that generates something.

Edit: I believe I set up the debug correctly, (context.setupDebugMessageCallback(System.err)), but it's not putting out any errors.
« Last Edit: June 10, 2015, 17:49:19 by Teracon »

*

Kai

Re: Unable to get glDrawElements to work.
« Reply #3 on: June 10, 2015, 17:58:46 »
Added a simple demo showcasing the use of glDrawElements. This effectively really does not do anything else than what you did, but works perfectly for me, though.
Could you send/attach the .class files generated by the Scala compiler for your demo and for that hand method? There we can check what Scala really is doing.
« Last Edit: June 10, 2015, 18:08:59 by Kai »

Re: Unable to get glDrawElements to work.
« Reply #4 on: June 10, 2015, 18:39:04 »
I copy/pasted your code and scalafied it, and it works. Scala for some reason didn't like (FloatBuffer) BufferUtils.createFloatBuffer(vertices.length).put(vertices).flip() and the similar line; I broke them out as three lines and it accepted; I'm thinking it was a type error (along the functions pushing things up). Looks like I need to diff some things, because I don't even know. Mass type checking I guess. Thank you! Would you be interested in seeing the scalafied copy/paste I did?

Edit:
More strangeness: removing wsCallback and referenced items from my copy/pasted code causes the error, but adding it to my code does not fix it.
« Last Edit: June 10, 2015, 18:44:03 by Teracon »

*

Kai

Re: Unable to get glDrawElements to work.
« Reply #5 on: June 10, 2015, 18:40:25 »
I would be quite interested in the original (non-working) .class files, to see what exactly Scala was doing there. Thanks!

Re: Unable to get glDrawElements to work.
« Reply #6 on: June 10, 2015, 18:49:24 »
Here they are, I didn't see you ask for them the first time around.

*

Kai

Re: Unable to get glDrawElements to work.
« Reply #7 on: June 10, 2015, 18:51:30 »
Could you please also attach the test class, of which you showed the Scala code above?

*

Kai

Re: Unable to get glDrawElements to work.
« Reply #8 on: June 10, 2015, 18:55:38 »
More strangeness: removing wsCallback and referenced items from my copy/pasted code causes the error, but adding it to my code does not fix it.
Ah, then it was probably the glViewport which you was missing in your code. This method is needed when you resize the window to tell OpenGL about the changed viewport size.
Because, you did realize that this window size callback was setting the instance fields "width" and "heigh" which were being used by glViewport?
« Last Edit: June 10, 2015, 19:02:35 by Kai »

Re: Unable to get glDrawElements to work.
« Reply #9 on: June 10, 2015, 19:10:27 »
Attached the files. At some point in time I did add a viewport, and was using the WIDTH and HEIGHT constants. I did not have width/height aside from those constants. I got my version to work, and think maybe it was a strange ordering of setting up the buffers?

Edit: Upon further finagalling, this appears to not be the case. Thank you so much for your help, whatever it was that did it. Maybe the last zero in glVertexAttribPointer wasn't properly casting as a long?
« Last Edit: June 10, 2015, 19:14:41 by Teracon »

*

Kai

Re: Unable to get glDrawElements to work.
« Reply #10 on: June 10, 2015, 19:20:21 »
Now slow down... :)
That test classes which you attached in your last post ARE NOT the compile of your original test class from your very first post, which I asked about. They are the result of my demo class being translated to Scala by you. If we are ever going to find the error, I conjure you to use your non-working Scala code of your very first post again, and attach THOSE class files. :)
I mean there is no use in trying to dissect a "working" code...

Re: Unable to get glDrawElements to work.
« Reply #11 on: June 10, 2015, 19:24:49 »
Aw crap, sorry. I've been working on this for two days and been utterly confused past the first two hours.

Interesting note: I copied the original code from this post, and it works now. I don't even.


Re: Unable to get glDrawElements to work.
« Reply #13 on: June 10, 2015, 19:31:52 »
On the one hand, I'm glad it's working now. On the other, I'm reasonably sure that this is going to generate an even more mind boggling error close to release >_> Thank you so much for your help! Whatever form that came in.