(This is the second time I am asking this question. Last time I got one answer that didn't solve it (the answer there referred a bit of code that was left accidentally from one of my attempts at fixing this). I also changed the question itself slightly - I changed the order of code to put the part where I believe the mistake higher is and added that I am using macOS, which might be the reason that it doesn't work).
So, I just started learning LWJGL 3 and I used a mixture of a couple of tutorials and example code to make something that should render a rectangle to a magenta screen using VAOs and VBOs. There are no errors but the rectangle doesn't appear on screen (all I can see is a magenta screen). I tried using the old LWJGL pipeline (glBegin() and glEnd()) and it does work so I tried changing random things in the rendering code and the loading to VAOs and VBOs. I also tried to bind the VBO too but it didn't change anything. I also tried debugging and it seems like there is a VAO and a VBO that is created.
Can someone take a look at my code and see if something looks wrong? Here it is (sorry if its a bit messy. Like I said, I don't think the problem is in the Main or Window class but I have no idea about LWJGL so I wanted to put it here anyways. If you have time, please also look at them. Otherwise I would really appreciate it if you could look at the Loader and Renderer classes):
(Btw, I am using macOS, and I do have -XstartOnFirstThread on).
The Raw Model class:
package engine.io;
public class RawModel {
private int vaoID;
private int vertexCount;
public RawModel(int vaoID, int vertexCount) {
this.vaoID = vaoID;
this.vertexCount = vertexCount;
}
public int getVaoID() {
return vaoID;
}
public int getVertexCount() {
return vertexCount;
}
}
The loader class:
package engine.io;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.BufferUtils;
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;
public class Loader {
private List<Integer> vaos = new ArrayList<Integer>();
private List<Integer> vbos = new ArrayList<Integer>();
public RawModel loadToVAO(float[] positions) {
int vaoID = createVAO();
storeDataInAttributeList(0, positions);
unbindVAO();
return new RawModel(vaoID, positions.length/3);
}
private int createVAO() {
int vaoID = GL30.glGenVertexArrays();
vaos.add(vaoID);
GL30.glBindVertexArray(vaoID);
return vaoID;
}
private void storeDataInAttributeList(int attributeNumber, float[] data) {
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private void unbindVAO() {
GL30.glBindVertexArray(0);
}
private FloatBuffer storeDataInFloatBuffer(float[] data) {
FloatBuffer buffer = MemoryUtil.memAllocFloat(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
public void cleanUp() {
for (int vao : vaos) {
GL30.glDeleteVertexArrays(vao);
}
for (int vbo : vbos) {
GL15.glDeleteBuffers(vbo);
}
}
}
The renderer class:
package engine.io;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Renderer {
public void prepare() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glClearColor(1f, 0f, 1f, 1f);
}
public void render(RawModel model) {
GL30.glBindVertexArray(model.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, model.getVertexCount());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
}
Here is the Main class:
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;
import engine.io.Loader;
import engine.io.RawModel;
import engine.io.Renderer;
import engine.io.Window;
import java.nio.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
public class Main {
private Window window;
Loader loader = new Loader();
Renderer renderer = new Renderer();
float[] vertices = {
// Left bottom triangle
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
// Right top triangle
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f
};
RawModel model;
public void run() {
setup();
loop();
loader.cleanUp();
glfwFreeCallbacks(window.getWindowNum());
glfwDestroyWindow(window.getWindowNum());
glfwTerminate();
glfwSetErrorCallback(null).free();
}
private void loop() {
while ( !glfwWindowShouldClose(window.getWindowNum()) ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
renderer.render(model);
glfwSwapBuffers(window.getWindowNum()); // swap the color buffers
glfwPollEvents();
}
}
public void setup() {
window = new Window(900, 300, "Flappy Bird");
window.create();
GL.createCapabilities();
GLFW.glfwMakeContextCurrent(window.getWindowNum());
model = loader.loadToVAO(vertices);
renderer.prepare();
GL11.glViewport(0, 0, 900, 300);
}
public static void main(String[] args) {
new Main().run();
}
}
Here is the window class:
package engine.io;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.*;
import java.nio.IntBuffer;
//import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.system.MemoryStack;
public class Window {
private int width, height;
private String title;
private long window;
public Window(int width, int height, String title) {
this.width = width;
this.height = height;
this.title = title;
}
public void create() {
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit())
throw new IllegalStateException("Unable to initialize GLFW");
// Configure GLFW
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable
// Create the window
window = glfwCreateWindow(width, height, "Flappy Bird", NULL, NULL);
if (window == NULL)
throw new RuntimeException("Failed to create the GLFW window");
// Get the thread stack and push a new frame
try (MemoryStack stack = stackPush()) {
IntBuffer pWidth = stack.mallocInt(1); // int*
IntBuffer pHeight = stack.mallocInt(1); // int*
// Get the window size passed to glfwCreateWindow
glfwGetWindowSize(window, pWidth, pHeight);
// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center the window
glfwSetWindowPos(window, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2);
} // the stack frame is popped automatically
// Setup a key callback. It will be called every time a key is pressed, repeated
// or released.
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
});
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
}
public long getWindowNum() {
return window;
}
}
Since you are on MacOS, I recommend to set up a 3.2 core profile OpenGL Context. See OpenGL Development on OS X:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create the window
window = glfwCreateWindow(width, height, "Flappy Bird", NULL, NULL);
Related
i am trying to learn usinf opengl and lwjgl with java and i have amde a program and am trying to render some mesh but the class handling the Vaos and Vbos is faulty.After doing some research , i have learnt that this may be cause because of the position of my calling the method relative to the MakecontextCurrent(); method but i got no luck there.
Warning
Alot of code ahead
The faulty class
package renderEngine;
import java.nio.FloatBuffer;
import java.util.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;
public class Loader {
private List<Integer>vaos = new ArrayList<Integer>();
private List<Integer>vbos = new ArrayList<Integer>();
public RawModel loadToVao(float[] positions) {
int vaoID = createVAO();
storeDataInAttributeList(0, positions);
unbind();
return new RawModel(vaoID,positions.length/3);
}
public void cleanup() {
for(int vao : vaos) {
GL30.glDeleteVertexArrays(vao);
}
for(int vbo : vbos) {
GL30.glDeleteVertexArrays(vbo);
}
}
public int createVAO() {
int vaoID = GL30.glGenVertexArrays();
vaos.add(vaoID);
GL30.glBindVertexArray(vaoID);
return vaoID;
}
public void storeDataInAttributeList(int attributeNumber , float [] data) {
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER,buffer,GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(attributeNumber, 3,GL11.GL_FLOAT,false,0,0);
GL30.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
public void unbind() {
GL30.glBindVertexArray(0);
}
private FloatBuffer storeDataInFloatBuffer(float[] data) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
this is the class which handles the gameloop
package renderEngine;
import org.lwjgl.glfw.GLFW;
public class MainGameLoop implements Runnable{
public Loader loader;
public Thread gamethread;
public DisplayManager display;
public RawModel model;
Renderer renderer;
public static void main(String[] args) {
new MainGameLoop().start();
}
private void start() {
gamethread = new Thread(this , "game");
gamethread.start();
}
#Override
public void run() {
init();
while (!display.shouldClose()) {
update();
render();
}
loader.cleanup();
}
private void render() {
renderer.prepare();
renderer.renderModel(model);
display.render();
}
private void update() {
display.update();
}
private void init() {
float[] vertices = new float[] {
0.5f , 0.5f , 0.0f , -0.5f , 0.5f , 0.0f , -0.5f , -0.5f , 0.0f , 0.5f , -0.5f , 0.0f
};
loader = new Loader();
display = new DisplayManager(900, 500, "Our Game",GLFW.glfwGetPrimaryMonitor());
display.createDisplay();
model = loader.loadToVao(vertices);
renderer = new Renderer();
}
}
Class handling the window creating
package renderEngine;
import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
public class DisplayManager {
public int width , height;
public String title;
public long monitor = 0;
private long window;
public DisplayManager(int width , int height , String title , long monitor) {
this.width = width;
this.title = title;
this.height = height;
this.monitor = monitor;
}
public void createDisplay() {
if(glfwInit()) {
//handle initialization error
System.err.println("Error001:FailedInitialization");
}
//create window
window = glfwCreateWindow(width, height, title,monitor , 0);
if (window == 0) {
//handle window creation error
System.err.println("Error002:FailedDisplayCreation");
}
//create vidmode
GLFWVidMode vm = glfwGetVideoMode(glfwGetPrimaryMonitor());
int xpos = vm.width()/2-width/2, ypos = vm.height()/2-height/2;
//set position to center
glfwSetWindowPos(window, xpos, ypos);
glfwMakeContextCurrent(ypos);
GL.createCapabilities();
//show window
glfwShowWindow(window);
}
public void destroyWindow() {
glfwDestroyWindow(window);
glfwTerminate();
}
public void render() {
glfwSwapBuffers(window);
}
public void update() {
glfwPollEvents();
}
public boolean shouldClose() {
return glfwWindowShouldClose(window);
}
}
The renderer
package renderEngine;
import org.lwjgl.opengl.*;
public class Renderer {
public void prepare() {
GL11.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GL11.glClear(GL15.GL_ARRAY_BUFFER);
}
public void renderModel(RawModel model) {
GL30.glBindVertexArray(model.getVaoID());
GL30.glEnableVertexAttribArray(0);
GL11.glDrawArrays(GL11.GL_TRIANGLES,0, model.getVertexCount());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
}
the raw model
package renderEngine;
import org.lwjgl.opengl.*;
public class Renderer {
public void prepare() {
GL11.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GL11.glClear(GL15.GL_ARRAY_BUFFER);
}
public void renderModel(RawModel model) {
GL30.glBindVertexArray(model.getVaoID());
GL30.glEnableVertexAttribArray(0);
GL11.glDrawArrays(GL11.GL_TRIANGLES,0, model.getVertexCount());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
}
The error
FATAL ERROR in native method: Thread[game,5,main]: No context is current or a function that is not
available in the current context was called. The JVM will abort execution.
at org.lwjgl.opengl.GL30C.nglGenVertexArrays(Native Method)
at org.lwjgl.opengl.GL30C.glGenVertexArrays(GL30C.java:2420)
at org.lwjgl.opengl.GL30.glGenVertexArrays(GL30.java:2369)
at renderEngine.Loader.createVAO(Loader.java:28)
at renderEngine.Loader.loadToVao(Loader.java:13)
at renderEngine.MainGameLoop.init(MainGameLoop.java:47)
at renderEngine.MainGameLoop.run(MainGameLoop.java:21)
at java.lang.Thread.run(java.base#11.0.8/Thread.java:834)
Your error is juste a simple mistake in declaration order.
Reorder these line in your MainGameLoop class :
loader = new Loader();
display = new DisplayManager(900, 500, "Our Game",GLFW.glfwGetPrimaryMonitor());
display.createDisplay();
Like this :
display = new DisplayManager(900, 500, "Our Game",GLFW.glfwGetPrimaryMonitor());
display.createDisplay();
loader = new Loader();
Because in your Loader class you call OpenGL function (GL30.glGenVertexArrays();) but you cannot call OpenGL function if no context have been already setup.You setup an OpenGL context with GL.createCapabilities();, and this line is in your DisplayManager class.So the GL.createCapabilities(); is executed after the call to OpenGL function in your MainGameLoop class (in reality is never executed because the JVM will crash before).
I've been trying to get into OpenGL with LWJGL and I've run into an issue that I cannot find a solution to. When trying to draw a triangle with the code below, the window opens correctly and begins flashing a shape that isn't necessarily the intended triangle (sometimes it appears briefly, but often there are rectangles in one of the quadrants of the window).
Part of my hesitation is in how OpenGL, by my reading of various posts and docs online, has changed within recent memory to use a less functional and more an object-oriented approach (VBOs and GLSL?) with GL4. Am I correct in this understanding and what are the preferred resources for learning this newer OpenGL for LWJGL?
Thank you in advance!
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;
import java.nio.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
public class Main {
private long windowID;
private float[] tri = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f};
public static void main(String[] args) {
new Main().run();
}
public void run() { // Useful for making an instance class as opposed to a static main class?
init();
loop();
glfwFreeCallbacks(windowID);
glfwDestroyWindow(windowID);
glfwTerminate();
glfwSetErrorCallback(null).free();
}
public void init() { // Initializes all LWJGL components
GLFWErrorCallback.createPrint(System.err).set(); // Create error callback route for GL
if (!glfwInit()) { // Init GLFW
throw new IllegalStateException("Failed to initialize GLFW!");
} else {
System.out.println("GLFW successfully initialized!");
}
windowID = glfwCreateWindow(640, 480, "Creating Window", NULL, NULL);
if (windowID == NULL) { // Verify window creation
throw new IllegalStateException("Failed to create window!");
} else {
System.out.println("Successfully created window!");
}
glfwDefaultWindowHints(); // Set window Proporties
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwSetKeyCallback(windowID, (window, key, scancode, action, mods) -> { // Key callback for closing the window
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
glfwSetWindowShouldClose(window, true);
});
try (MemoryStack stack = stackPush()) { // Center the window
IntBuffer pWidth = stack.mallocInt(1);
IntBuffer pHeight = stack.mallocInt(1);
glfwGetWindowSize(windowID, pWidth, pHeight);
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos( // Center the window
windowID,
(vidmode.width() - pWidth.get(0)) / 2,
(vidmode.height() - pHeight.get(0)) / 2
);
}
glfwMakeContextCurrent(windowID); // Make the window current
glfwSwapInterval(0); // Sets the min num of pushed frames before buffers are swaped (Likely prevents horizontal tearing)
glfwShowWindow(windowID); // Unhides the window
}
private void loop() {
GL.createCapabilities();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // The color to clear the buffers with
while(!glfwWindowShouldClose(windowID)) { // If the window is allowed to live
glClear(GL_COLOR_BUFFER_BIT); // The OR is nessesary for some reason
FloatBuffer vBuff = BufferUtils.createFloatBuffer(6);
vBuff.put(tri);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vBuff);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_VERTEX_ARRAY);
glfwSwapBuffers(windowID);
glfwPollEvents();
}
}
}
You missed vBuff.flip() after the buffer was crated and filled.
vBuff.put(tri) transfers the the data to the buffer, beginning at the current position (which is the start of the buffer in this case). The buffer position is incremented by the size of the data. So the new buffer position is at the end of the new data.
flip() sets the limit (length) of the buffer to the current position and then the position is set to zero.
Further, it is not necessary to create and fill the buffer continuously in the loop, it would be sufficient to do that once before the loop:
FloatBuffer vBuff = BufferUtils.createFloatBuffer(6);
vBuff.put(tri);
vBuff.flip();
while(!glfwWindowShouldClose(windowID)) {
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vBuff);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_VERTEX_ARRAY);
glfwSwapBuffers(windowID);
glfwPollEvents();
}
The problem
I am having trouble rendering absolutely anything with LWJGL 3.
It will not render anything, whilst creating the GLFW display and clearing the
color successfully.
The tools
Eclipse Neon (Java IDE)
LWJGL 3.1.1 build 16 with GLFW, JAWT and OPENGL bindings, natives.
The code
package init;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.nio.IntBuffer;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.MemoryStack;
import exception.ExceptionHandler;
import util.Time;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
public class DisplayInstance {
public String title = "The SuperMatrix";
public GraphicsDevice gd;
public Game game;
public Config conf;
private long display;
private GLFWErrorCallback glfwerrorcallback;
public DisplayInstance(Game game) {
this.gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
this.game = game;
this.conf = Config.returnConfig(this);
this.glfwerrorcallback = GLFWErrorCallback.createPrint(System.err);
this.glfwerrorcallback.set();
this.start();
}
public void start() {
if (!glfwInit())
ExceptionHandler.handleException(new IllegalStateException("Cannot initialize GLFW"));
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
this.display = glfwCreateWindow(this.conf.width, this.conf.height, this.title, 0, 0);
if (this.display == 0L) {
ExceptionHandler.handleException(new RuntimeException("Cannot create GLFW window"));
}
System.out.println(this.display);
try (MemoryStack stack = stackPush()) {
IntBuffer pWidth = stack.mallocInt(1);
IntBuffer pHeight = stack.mallocInt(1);
glfwGetWindowSize(this.display, pWidth, pHeight);
GLFWVidMode mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(this.display,
(mode.width()-pWidth.get(0))/2,
(mode.height()-pHeight.get(0))/2
);
} catch (Exception e) {
ExceptionHandler.handleException(e);
}
glfwMakeContextCurrent(this.display);
glfwSwapInterval(1);
glfwShowWindow(this.display);
this.loop();
}
public void loop() {
GL.createCapabilities();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,this.conf.width, 0, this.conf.height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
Time time = new Time();
while(!glfwWindowShouldClose(this.display)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwSwapBuffers(this.display);
glfwPollEvents();
glPushMatrix();
glBegin(GL_QUADS);
glColor3f(1,0,1);
glVertex2f(0, 0);
glVertex2f(0, 64);
glVertex2f(64, 64);
glVertex2f(64, 0);
glEnd();
glPopMatrix();
float deltaSeconds = time.getDelta()/Time.SECOND;
float fps = deltaSeconds;
System.out.println(fps);
}
this.destroy();
}
public void destroy() {
glfwFreeCallbacks(this.display);
glfwDestroyWindow(this.display);
glfwTerminate();
this.glfwerrorcallback.free();
this.game.stopGame();
}
}
Thank you. Absolutely any help would be appreciated.
Alright, I finally found the answer.
The cause of the problem
The problem was that I called glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) right before I called glfwSwapBuffers(this.display):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwSwapBuffers(this.display);
This essentially means that I clear the buffers right before I show them.
The fix
To fix this, all I had to do is move glfwSwapBuffers(this.display) down to after the glPopMatrix() call. Here is how the loop() function looks like now:
GL.createCapabilities();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,this.conf.width, 0, this.conf.height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
Time time = new Time();
while(!glfwWindowShouldClose(this.display)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwPollEvents();
glPushMatrix();
glBegin(GL_QUADS);
glColor3f(1,0,1);
glVertex2f(0, 0);
glVertex2f(0, 64);
glVertex2f(64, 64);
glVertex2f(64, 0);
glEnd();
glPopMatrix();
glfwSwapBuffers(this.display);
float deltaSeconds = time.getDelta()/Time.SECOND;
float fps = deltaSeconds;
System.out.println(fps);
}
this.destroy();
Everybody, have a great day!
P.S. Please don't mind the FPS system, I'm still trying to figure it out.
I'm new to OpenGL and LWJGL3 and I'm trying to render a triangle. However, it isn't showing up, only the white, empty window. I guess it's a pretty small piece that I somehow forgot or where I just made a mistake. I don't find it after searching for hours now though. Here's the code:
MainLoop:
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.glfw.GLFW.*;
public class MainLoop {
private DisplayManager displayManager;
private Shader shader;
public MainLoop() {
displayManager = new DisplayManager();
displayManager.createDisplay();
shader = new Shader("src/shader.vert", "src/shader.frag");
}
private void start() {
float positions[] = {
-0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f
};
int vao = glGenVertexArrays();
glBindVertexArray(vao);
int positionVbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, positionVbo);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(positions), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
while(!displayManager.isCloseRequested()) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
render();
update();
displayManager.swapBuffers();
}
shader.cleanUp();
displayManager.destroyDisplay();
}
private void update() {
glfwPollEvents();
}
private void render() {
shader.bind();
//rendering stuff
glDrawArrays(GL_TRIANGLES, 0, 3);
shader.unbind();
}
public static void main(String[] args) {
new MainLoop().start();
}
}
Shader:
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL20.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Shader {
private int program;
public Shader(final String vertexShaderFilePath, final String fragmentShaderFilePath) {
int vertexShader = createShader(loadShaderSource(vertexShaderFilePath), GL_VERTEX_SHADER);
int fragmentShader = createShader(loadShaderSource(fragmentShaderFilePath), GL_FRAGMENT_SHADER);
program = glCreateProgram();
glAttachShader(vertexShader, program);
glAttachShader(fragmentShader, program);
glLinkProgram(program);
glValidateProgram(program); //just during development
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
private String loadShaderSource(final String shaderFilePath) {
String shaderSourceString = "";
try {
shaderSourceString = new String(Files.readAllBytes(Paths.get(shaderFilePath)));
} catch (IOException e) {
e.printStackTrace();
}
return shaderSourceString;
}
private int createShader(final String shaderSourceString, final int type) {
int shader = glCreateShader(type);
glShaderSource(shader, shaderSourceString);
glCompileShader(shader);
checkShaderCompileError(shader);
return shader;
}
private void checkShaderCompileError(int shader) {
if(glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Could not compile shader.");
System.err.println(glGetShaderInfoLog(program));
System.exit(-1);
}
}
public void bind() {
glUseProgram(program);
}
public void unbind() {
glUseProgram(0);
}
public void cleanUp() {
glDeleteProgram(program);
}
}
BufferUtils:
import java.nio.FloatBuffer;
public class BufferUtils {
public static FloatBuffer createFloatBuffer(float[] array) {
FloatBuffer buffer = org.lwjgl.BufferUtils.createFloatBuffer(array.length);
buffer.put(array);
buffer.flip();
return buffer;
}
}
shader.vert:
#version 410 core
layout (location = 0) in vec3 vertex_position;
void main(void)
{
gl_Position = vec4(vertex_position, 1.0);
}
shader.frag:
#version 410 core
out vec4 frag_color;
void main(void)
{
frag_color = vec4(1.0, 0.0, 1.0, 1.0);
}
EDIT: and here's the DisplayManager:
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryUtil.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GLContext.*;
import java.nio.ByteBuffer;
import org.lwjgl.glfw.GLFWvidmode;
public class DisplayManager {
private static final int WIDTH = 1280;
private static final int HEIGHT = 800;
private long window;
private Keyboard keyCallback;
public void createDisplay() {
// initialize GLFW
if(glfwInit() != GL_TRUE) {
System.err.println("GLFW failed to initialize.");
System.exit(-1);
}
// set window hints
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, 4); //16 for production
// create window
window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL", NULL, NULL);
if(window == NULL) {
System.err.println("GLFW window failed to create.");
glfwTerminate();
System.exit(-1);
}
ByteBuffer videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (GLFWvidmode.width(videoMode) - WIDTH) / 2, (GLFWvidmode.height(videoMode) - HEIGHT) / 2);
// set callback mechanisms
glfwSetKeyCallback(window, setKeyCallback(new Keyboard()));
// set context and show window
glfwMakeContextCurrent(window);
createFromCurrent();
glfwSwapInterval(1); // v-sync
glfwShowWindow(window);
// openGL functions
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH);
}
public void destroyDisplay() {
glfwDestroyWindow(window);
glfwTerminate();
}
public boolean isCloseRequested() {
if(glfwWindowShouldClose(window) == GL_TRUE) {
return true;
}
return false;
}
public void swapBuffers() {
glfwSwapBuffers(window);
}
public Keyboard getKeyCallback() {
return keyCallback;
}
public Keyboard setKeyCallback(Keyboard keyCallback) {
this.keyCallback = keyCallback;
return keyCallback;
}
}
Does anybody spot what's going wrong?
Thanks in advance!
I finally found the error, the order of parameters for the call glAttachShader(shader, program); were mixed up. You first have to pass the program and then the shader id like so: glAttachShader(program, shader);. Thank you for your answers though!
Whenever i try to populate a VAO, i get a null pointer exception
Error
Hello LWJGL 3.0.0a!
2.1 INTEL-10.0.86
Exception in thread "main" java.lang.NullPointerException
at org.lwjgl.opengl.GL30.nglGenVertexArrays(GL30.java:3265)
at org.lwjgl.opengl.GL30.glGenVertexArrays(GL30.java:3294)
at javaapplication73.Loader.createVAO(Loader.java:35)
at javaapplication73.Loader.loadToVao(Loader.java:27)
at javaapplication73.HelloWorld.initial(HelloWorld.java:139)
at javaapplication73.HelloWorld.loop(HelloWorld.java:120)
at javaapplication73.HelloWorld.run(HelloWorld.java:32)
at javaapplication73.HelloWorld.main(HelloWorld.java:154)
Java Result: 1
The code that throws this exception is the createVAO method in this Loader class.
package javaapplication73;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Loader {
private List<Integer> vaos = new ArrayList<Integer>();
private List<Integer> vbos = new ArrayList<Integer>();
public RawModel loadToVao(float[] positions){
int vaoID = this.createVAO();
this.storeDataInAttributeList(0, positions);
this.unbindVAO();
return new RawModel(1, positions.length/3);
}
private int createVAO(){
int vaoID = GL30.glGenVertexArrays();
vaos.add(vaoID);
GL30.glBindVertexArray(vaoID);
return vaoID;
}
public void storeDataInAttributeList(int attributeNumber, float[] data){
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer =storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
public void unbindVAO(){
//unbind the array
GL30.glBindVertexArray(0);
}
private FloatBuffer storeDataInFloatBuffer(float[] data){
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
//need to flip between wright and read
buffer.flip();
return buffer;
}
public void cleanUp(){
for (Integer vao : this.vaos) {
GL30.glDeleteVertexArrays(vao);
}
for(Integer vbo : this.vbos){
GL15.glDeleteBuffers(vbo);
}
}
}
I don't think that this class is really needed, but this is my main class
package javaapplication73;
import org.lwjgl.Sys;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import java.nio.ByteBuffer;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
public class HelloWorld {
// We need to strongly reference callback instances.
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
// The window handle
private long window;
private final int fpsCap = 120;
Loader loader = new Loader();
Renderer renderer = new Renderer();
private RawModel model;
public void run() {
System.out.println("Hello LWJGL " + Sys.getVersion() + "!");
try {
init();
loop();
// Release window and window callbacks
glfwDestroyWindow(window);
keyCallback.release();
} finally {
// Terminate GLFW and release the GLFWerrorfun
glfwTerminate();
errorCallback.release();
}
}
private void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
glfwSetErrorCallback(errorCallback = errorCallbackPrint(System.err));
// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( glfwInit() != GL11.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
int WIDTH = 1200;
int HEIGHT = 800;
// Create the window
window = glfwCreateWindow(WIDTH, HEIGHT, "Not so Still Life", 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 = new GLFWKeyCallback() {
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, GL_TRUE); // We will detect this in our rendering loop
cleanUp();
}
});
// Get the resolution of the primary monitor
ByteBuffer vidmode = 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);
}
private void loop() {
// 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();
// Set the clear color
glClearColor(.3243f,0,.83251234f,0);
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
// Clear the screen and depth buffer
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
initial();
Render();
glfwSwapBuffers(window); // swap the color buffers
glfwPollEvents();
}
}
public void initial(){
System.out.println(glGetString(GL_VERSION));
//Pre game stuff
float[] verticies = {
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f,
};
model = loader.loadToVao(verticies);
}
public void Render(){
renderer.prepare();
renderer.Render(model);
}
public void cleanUp(){
System.out.println("CleanUp");
this.loader.cleanUp();
}
public static void main(String[] args) {
System.setProperty("org.lwjgl.librarypath", "/Users/Bayjose/LWJGL/lwjgl/native");
new HelloWorld().run();
}
}
The computer that I am codeing this on is a Macbook Pro 2014 model, running osx Yosemite 10.10.1
Dont know if that has anything to do with the error or not