[Beware: Highly Noobish question incoming!]
Hello folks!
So I'm just starting with OpenGL or graphics programming in general. I wanted to use a higher-order language such as Scala and figured I could use lwjgl (version 3) to learn about all this stuff.
I started coding and after a few bugs I mentioned in another thread, I was advised to open another one, because some of my problems were obviously my own faults, coming from me being a noob. (http://forum.lwjgl.org/index.php?topic=4800.msg29804#msg29804)
So, here I am, sitting in front of my PC, trying to figure out what I am doing wrong. I'm not a native speaker so maybe that's it, but spasi said that it's not the actual code in my main rendering-loop, but the actual order of rendering, which seems to be a contradiction to me.
Anyway, here is what I think I'm doing/trying to do:
At first I create a window, set my callbacks and some glfw hints.
Then I create a new Loader. A Loader may "load" some kind of information into VertexArrayObjects which consists of VertexBufferObjects, currently basically the positions of the vertices and the indices to save memory and returns a Model, which holds the id of the VAO.
Then I update my window as long as it's not closed. That means I prepare my renderer (Clearing the window), swap the buffers, poll events and render my model.
I'm not sure where I should place my "swapping", because everything I tried does not work. So, maybe I've got it all wrong and need to start over?
I've attached a copy of my current code, it's just a few basic classes which should've helped me to understand what's going on and render a rectangle on screen. (Oh, and I thought, maybe it's not getting color, so I started with a ShaderProgram, but as soon as I initialize that I get a black screen :()
My advice is: Start small and slowly work your way up to something bigger. At each step test your program to see if it still works.
Can you render something with immediate mode?
If yes, can you render something with drawArrays?
Then, try to render something with a VBO. Only iff you got all of that to work go to a VAO + VBO.
Well, thanks for the advice. I wanted to start OpenGL the modern way and thought that VAOs and VBOs were the way to go.
Quote from: Umami on January 05, 2015, 10:48:46spasi said that it's not the actual code in my main rendering-loop, but the actual order of rendering, which seems to be a contradiction to me.
The code you shared on your first post was doing glfwSwapBuffers() between renderer.prepare() and renderer.render(model). This was wrong and would always result in an empty buffer, regardless of what the rest of your code was doing. Your current code does glfwSwapBuffers() before prepare and render and should work, but it's still weird; glfwSwapBuffers() should be *after* render.
I'll make an attempt to explain this better. OpenGL uses double buffering by default. So, effectively you have two framebuffers, A and B. At any time, one is the back buffer and the other the front buffer. All OpenGL rendering commands go into the back buffer. Your screen displays the front buffer. So, lets say we enter the main loop and A is the current back buffer.
Case 1 (SwapBuffers in-between):A - prepare clears A
A - SwapBuffers, A is displayed (was empty) and B becomes the back buffer
B - render model into B
--------
B - prepare clears B
B - SwapBuffers, B is displayed (was empty) and A becomes the back buffer
A - render model into A
--------
A - prepare clears A
A - SwapBuffers, A is displayed (was empty) and B becomes the back buffer
... etc ...
As you can see, you'll always see an empty buffer.
Case 2 (SwapBuffers first):A - SwapBuffers, A is displayed (was empty) and B becomes the back buffer
B - prepare clears B
B - render model into B
--------
B - SwapBuffers, B is displayed and A becomes the back buffer
A - prepare clears A
A - render model into A
--------
A - SwapBuffers, A is displayed and B becomes the back buffer
... etc ...
As you can see, this is fine, except the very first frame which is always empty.
Case 3 (SwapBuffers last):A - prepare clears A
A - render model into A
A - SwapBuffers, A is displayed and B becomes the back buffer
--------
B - prepare clears B
B - render model into B
B - SwapBuffers, B is displayed and A becomes the back buffer
--------
... etc ...
This is what you want.
Thank you for shedding light on this matter! And sorry I interpreted the wrong code :(
I do the swapping at the end of the loop now, but still no luck with an output. I guess I have to tell my graphicscard to render the model in a certain color then.
I tried to do this with two simple shaders, but as soon as I initialize my shader the whole window is black. You mentioned an easier method in the other thread, so I'll go dig for that one.
Thanks again!
edit: The real interesting thing is, that as soon as I use my shader, the program doesn't poll events anymore, or at least it doesn't react on "escape" and closing the window.
But there is no exception thrown, so it finds the files but when it reads them in, every line is "null" which is really strange since:
while((line = reader.readLine()) != null) {
Predef.println(line)
shaderSource.append(line).append("\n")
}
outprints "null", while it should not be able to be null because of the constraint in the loop oO
Perhaps you should show us your shaders.
Fixed everything. Ah, never do it the Java way, if you can do it the Scala way.
@Cornix: All the code was in the zip file I provided, but I fixed it! :D
Edit: So what did I do to fix it? First I changed the version of my shaders to 330, because I figured 400 would lead to errors further down the line (It does, just tested it. My graphics card does support OpenGL 4 but the open source drivers for it do not at the moment. A price I shall gladly pay for now.)
What else did I do?
I said that the BufferedReader didn't work as expected. It opened the files but the content was "null" and although it was in a loop with the constraint "!= null" the output was still null.
So my fix was the following:
val reader:BufferedReader = new BufferedReader(new FileReader(file))
val lines = Stream.continually(reader.readLine()).takeWhile(_ != null).mkString("\n")
reader.close()
Predef.println(lines)
shaderSource.append(lines)
One could argue about the verbosity of this statement, but it's the Scala way of doing things.
What I do here is the same as I would in Java, but kind of functional style.
edit2: even nicer:
val lines = Source.fromFile(file).getLines().mkString("\n")
shaderSource.append(lines)