All, Having difficulty with glGenVertexArrays(). I get the following error:
Exception in thread "main" java.lang.IllegalStateException: This functionality is not available.
at org.lwjgl.system.Checks.checkFunctionality(Checks.java:57)
at org.lwjgl.opengl.GL30.getInstance(GL30.java:667)
at org.lwjgl.opengl.GL30.getInstance(GL30.java:662)
at org.lwjgl.opengl.GL30.nglGenVertexArrays(GL30.java:2789)
at org.lwjgl.opengl.GL30.glGenVertexArrays(GL30.java:2816)
at renderEngine.Loader.createVAO(Loader.java:26)
at renderEngine.Loader.loadToVAO(Loader.java:19)
at renderEngine.MainGameLoop.main(MainGameLoop.java:27)
Here is my Main Game Loop (I call GL.createCapabilities() from the createDisplay() method.)
package renderEngine;
import static org.lwjgl.glfw.GLFW.*;
public class MainGameLoop {
public static DisplayManager dm = new DisplayManager();
public static void main(String[] args) {
//Create Display
dm.createDisplay();
Loader loader = new Loader();
Renderer renderer = new Renderer();
float[] vertices = {
-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
};
RawModel model = loader.loadToVAO(vertices);
//Game Loop
while (glfwWindowShouldClose(dm.getWindowID()) != GLFW_TRUE) {
renderer.prepare();
renderer.render(model);
dm.updateDisplay();
}
//Destroy Display
dm.destroyWindow();
loader.cleanUp();
}
}
As referenced above, here is the Display Manager class:
package renderEngine;
import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;
public class DisplayManager {
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
private long windowID;
//Constructor
public DisplayManager(){
init();
}
private void init(){
if(glfwInit() != GLFW_TRUE){
throw new IllegalStateException("Unable to initiate GLFW");
}
}
public long createDisplay(){
windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
if(windowID == 0){
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
GLFW.glfwSetWindowTitle(windowID, "GLFW Window");
setErrorCallback();
setKeyCallback();
glfwMakeContextCurrent(windowID);
GL.createCapabilities();
return windowID;
}
public long getWindowID(){
return this.windowID;
}
private void setErrorCallback(){
errorCallback = GLFWErrorCallback.createPrint(System.err);
glfwSetErrorCallback(errorCallback);
}
private void setKeyCallback(){
keyCallback = new GLFWKeyCallback(){
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
}
};
glfwSetKeyCallback(windowID, keyCallback);
}
public void updateDisplay(){
GLFW.glfwSwapInterval(1);
glfwSwapBuffers(windowID);
glfwPollEvents();
}
public void destroyWindow(){
glfwDestroyWindow(windowID);
keyCallback.release();
glfwTerminate();
errorCallback.release();
}
}
If would seem the above mentioned error is with the loader class:
package renderEngine;
import java.util.List;
import java.nio.FloatBuffer;
import java.util.ArrayList;
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 = 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); //0 un-binds currently bound VAO
}
public void cleanUp(){
for(int vao:vaos){
GL30.glDeleteVertexArrays(vao);
}
for(int vbo:vbos){
GL15.glDeleteBuffers(vbo);
}
}
private FloatBuffer storeDataInFloatBuffer(float[] data){
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
In Particular this line of code:
GL30.glBindVertexArray(vaoID);
As far as I can see this is the correct method to do it, and the GL capabilities/context have been set/called from the main thread (main game loops main method, utilising the display manager)
For completeness, here are the RawModel and Renderer Classes, do not suspect an issue these these:
package renderEngine;
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;
}
}
And here is the Renderer Class:
package renderEngine;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Renderer {
public void prepare(){
GL11.glClearColor(1, 0, 0, 1);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
}
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);
}
}
Any assistance you can give me regarding my implementation of 'glGenVertexArrays' would be much appreciated.
I have now added the following
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
However, am now getting the following error:
Exception in thread "main" java.lang.RuntimeException: Failed to create the GLFW window
at renderEngine.DisplayManager.createDisplay(DisplayManager.java:37)
at renderEngine.MainGameLoop.main(MainGameLoop.java:12)
The specific implementation of my createDisplay() is as follows:
public long createDisplay(){
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
if(windowID == 0){
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
GLFW.glfwSetWindowTitle(windowID, "GLFW Window");
setErrorCallback();
setKeyCallback();
glfwMakeContextCurrent(windowID);
GL.createCapabilities();
return windowID;
}
UPDATE
If have removed the error callbacks, as thought they might be causing an issue. The resulting error is:
Exception in thread "main" java.lang.RuntimeException: Failed to create the GLFW window
at renderEngine.DisplayManager.createDisplay(DisplayManager.java:40)
at renderEngine.MainGameLoop.main(MainGameLoop.java:12)
It seems the RuntimeException is being thrown, and is displaying my custom error message if the glfw window cannot be created. Could this be todo with the order in which I run this? I have played around with the placement of the 'init' method with noluck. There has got to be something I am overlooking?... Thanks.
Updated code for the Display Manager:
package renderEngine;
import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;
public class DisplayManager {
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
private long windowID;
//Constructor
public DisplayManager(){
init();
}
private void init(){
if(glfwInit() != GLFW_TRUE){
throw new IllegalStateException("Unable to initiate GLFW");
}
}
public long createDisplay(){
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
System.out.println(windowID);
if(windowID == 0){
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
glfwMakeContextCurrent(windowID);
GL.createCapabilities();
GLFW.glfwSetWindowTitle(windowID, "GLFW Window");
//setErrorCallback();
//setKeyCallback();
return windowID;
}
public long getWindowID(){
return this.windowID;
}
private void setErrorCallback(){
errorCallback = GLFWErrorCallback.createPrint(System.err);
glfwSetErrorCallback(errorCallback);
}
private void setKeyCallback(){
keyCallback = new GLFWKeyCallback(){
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
}
};
glfwSetKeyCallback(windowID, keyCallback);
}
public void updateDisplay(){
GLFW.glfwSwapInterval(1);
glfwSwapBuffers(windowID);
glfwPollEvents();
}
public void destroyWindow(){
glfwDestroyWindow(windowID);
keyCallback.release();
glfwTerminate();
errorCallback.release();
}
}
Many Thanks and Kind Regards,
Jake
The glGenVertexArrays function requires OpenGL 3.0 or higher. You have to explicitly tell GLFW this. Before calling glfwCreateWindow:
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.CONTEXT_VERSION_MINOR, 0);
You can check that you have OpenGL 3.0 or higher by calling GL11.glGetString(GL11.GL_VERSION) or by looking at the GL.getCapabilities().OpenGL30 flag.
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 was on lwjgl, just coding my engine as I'm gonna reuse it for other projects. But as i was coding my shaders, and tested, it gave this error.
FATAL ERROR in native method: Thread[main,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.GL20C.glCreateShader(Native Method)
at org.lwjgl.opengl.GL20.glCreateShader(GL20.java:253)
at bengine.shaders.ShaderProgram.loadShader(ShaderProgram.java:51)
at bengine.shaders.ShaderProgram.<init>(ShaderProgram.java:13)
at bengine.shaders.StaticShader.<init>(StaticShader.java:10)
at Main.jav$1.init(jav.java:53)
at bengine.window.CustomWindow.gameloop(CustomWindow.java:54)
at bengine.window.WindowRunner.runWindow(WindowRunner.java:7)
at Main.jav.main(jav.java:59)
Process finished with exit code 1
I need answers please do give answers, and tell if this has been a shut down topic.
Heres my code:
ShaderProgram.java:
package bengine.shaders;
import org.lwjgl.opengl.GL20;
import java.io.*;
public abstract class ShaderProgram {
private int shadersID;
private int vertexShaderID;
private int fragmentShaderID;
public ShaderProgram(String vertFile, String fragFile) {
vertexShaderID = ShaderProgram.loadShader(vertFile, GL20.GL_VERTEX_SHADER);
fragmentShaderID = ShaderProgram.loadShader(fragFile, GL20.GL_FRAGMENT_SHADER);
shadersID = GL20.glCreateProgram();
GL20.glAttachShader(shadersID, vertexShaderID);
GL20.glAttachShader(shadersID, fragmentShaderID);
GL20.glLinkProgram(shadersID);
GL20.glValidateProgram(shadersID);
}
public void start() { GL20.glUseProgram(shadersID); }
public void stop() { GL20.glUseProgram(0); }
public void clear() {
stop();
GL20.glDetachShader(shadersID, vertexShaderID);
GL20.glDetachShader(shadersID, fragmentShaderID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
GL20.glDeleteProgram(shadersID);
}
protected void bindAttribute(int attribute, String variableName) {
GL20.glBindAttribLocation(shadersID, attribute, variableName);
}
protected abstract void bindAttributes();
private static int loadShader(String file, int type) {
StringBuilder shaderSource = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine()) != null) {
shaderSource.append(line).append("\n");
}
} catch(IOException e) {
e.printStackTrace();
}
int shaderID = GL20.glCreateShader(type);
GL20.glShaderSource(shaderID, shaderSource);
GL20.glCompileShader(shaderID);
return shaderID;
}
}
StaticShader.java:
package bengine.shaders;
import org.lwjgl.glfw.GLFW;
public class StaticShader extends ShaderProgram {
private static final String VERTEX_FILE = "src/bengine/shaders/vertShader.glsl";
private static final String FRAGMENT_FILE = "src/bengine/shaders/fragmentShader.glsl";
public StaticShader() {
super(VERTEX_FILE, FRAGMENT_FILE);
}
#Override
protected void bindAttributes() {
super.bindAttribute(0, "position");
}
}
both shaders:
fragment shader:
#version 400 core
in vec3 colour;
out vec4 col;
void main(void) {
col = vec4(colour, 1.0);
}
vertex shader:
#version 400 core
in vec3 position;
out vec3 colour;
void main(void) {
gl_Position = vec4(position, 1.0);
colour = vec3(position.x, position.y, position.z);
}
And the window.
package bengine.window;
import bengine.math.Vector4;
import bengine.shaders.ShaderProgram;
import bengine.shaders.StaticShader;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import static org.lwjgl.glfw.GLFW.*;
public abstract class CustomWindow {
private long window;
public StaticShader shader;
public CustomWindow(int w, int h, String name) {
if(!glfwInit()) {
System.err.println("Bengi engine failure: GLFW initialization failed, this is a internal error, can't be fixed.");
}
glfwDefaultWindowHints();
this.window = glfwCreateWindow(w, h, name, 0, 0);
if(this.window == 0) {
System.err.println("Bengi engine failure: Window is 0.");
}
System.out.println("Window created.");
glfwMakeContextCurrent(window);
System.out.println("Context was made.");
}
public abstract void render();
public abstract void update();
public abstract void init();
public void swapBuffers() {
glfwSwapBuffers(this.window);
}
public void enableGLClearWith(int mode, Vector4 color) {
GL11.glClearColor(color.getX(), color.getY(), color.getZ(), color.getW());
GL11.glClear(mode);
}
public void runTask(Task task) {
task.runTask();
}
protected void gameloop() {
glfwInit(); // to avoid null pointer
//glfwMakeContextCurrent(window);
init();
GL.createCapabilities(true);
while(!glfwWindowShouldClose(this.window)) {
//swapBuffers();
render();
update();
glfwPollEvents();
}
}
}
Main.java:
package Main;
import bengine.math.Vector4;
import bengine.window.*;
import bengine.CONSTANTS;
import bengine.window.WindowRunner;
import bengine.math.Vector3;
import bengine.renderer.Mesh;
import bengine.renderer.Renderer;
import bengine.renderer.Vertex;
import bengine.shaders.StaticShader;
//import org.lwjgl.opengl.GL11;
public class jav {
public static CustomWindow window;
public static void main(String[] args) {
Mesh mesh = new Mesh(
new Vertex[] {
new Vertex(new Vector3(-0.5f, -0.5f, -0.5f)),
new Vertex(new Vector3(-0.5f, 0.5f, -0.5f)),
new Vertex(new Vector3(0.5f, -0.5f, -0.5f)),
new Vertex(new Vector3(0.5f, 0.5f, -0.5f)),
new Vertex(new Vector3(0.0f, 0.6f, -0.5f)),
},
new int[] {
0, 1, 2, 1, 3, 2, 1, 4, 3
}
);
Renderer renderer = new Renderer();
window = new CustomWindow(1200, 800, "hello world") {
#Override
public void render() {
swapBuffers();
enableGLClearWith(CONSTANTS.COLOR, new Vector4(0f, 0f, 0f, 1f));
shader.start();
renderer.renderMesh(mesh, CONSTANTS.TRI_RENDER);
shader.stop();
}
#Override
public void update() {
}
#Override
public void init() {
shader = new StaticShader();
}
};
WindowRunner runner = new WindowRunner();
runner.runWindow(window);
}
}
and the window runner(deprecated later)
package bengine.window;
import org.jetbrains.annotations.NotNull;
public class WindowRunner {
public static void runWindow(#NotNull CustomWindow window) {
window.gameloop();
}
}
I don't know why its happening, all my other packages in the renderer and others had the context. Please answer.
GL.createCapabilities(true); has to be called before init(). Note in the is an abstract method. It is overridden and the StaticShader object is constructed in init. Therefore, the OpenGL capability must be ensured beforehand:
protected void gameloop() {
GL.createCapabilities(true);
init();
while(!glfwWindowShouldClose(this.window)) {
//swapBuffers();
render();
update();
glfwPollEvents();
}
}
I can not solve the problem in question. I tried several solutions to this error but without any positive result. If i try to remove glCreateProgram() method the error move to glCreateShader() method.
Error
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalStateException: No GLCapabilities instance set for the current thread. Possible solutions:
a) Call GL.createCapabilities() after making a context current in the current thread.
b) Call GL.setCapabilities() if a GLCapabilities instance already exists for the current context.
at org.lwjgl.opengl.GL.getCapabilities(GL.java:238)
at org.lwjgl.opengl.GL20.glCreateProgram(GL20.java:209)
at ms.shaders.ShaderProgram.<init>(ShaderProgram.java:18)
at ms.shaders.Shaders.<init>(Shaders.java:8)
at ms.renderer.Renderer.<init>(Renderer.java:13)
at ms.main.MainGame.<clinit>(MainGame.java:16)
ShaderProgram
package ms.shaders;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public abstract class ShaderProgram {
private int programID;
private int vShaderID;
private int fShaderID;
public ShaderProgram(String vShader, String fShader) {
programID = glCreateProgram(); //Error line
String vertexShaderSource = loadShader(vShader);
vShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vShaderID, vertexShaderSource);
glCompileShader(vShaderID);
if (glGetShaderi(vShaderID, GL_COMPILE_STATUS) == GL_FALSE) {
throw new RuntimeException("Error creating vertex shader\n"
+ glGetShaderInfoLog(vShaderID, glGetShaderi(vShaderID, GL_INFO_LOG_LENGTH)));
}
glAttachShader(programID, vShaderID);
String fragmentShaderSource = loadShader(vShader);
fShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fShaderID, fragmentShaderSource);
glCompileShader(fShaderID);
if (glGetShaderi(fShaderID, GL_COMPILE_STATUS) == GL_FALSE) {
throw new RuntimeException("Error creating vertex shader\n"
+ glGetShaderInfoLog(fShaderID, glGetShaderi(fShaderID, GL_INFO_LOG_LENGTH)));
}
glAttachShader(programID, vShaderID);
}
protected abstract void bindAttribute();
protected void bindAttribute(int attribute, String name) {
glBindAttribLocation(programID, attribute, name);
}
public void link() {
glLinkProgram(programID);
if(glGetProgrami(programID, GL_LINK_STATUS) == GL_FALSE) {
throw new RuntimeException("Failed to link program: ");
}
}
public void validate() {
glValidateProgram(programID);
if(glGetShaderi(programID, GL_VALIDATE_STATUS) == GL_FALSE) {
throw new RuntimeException("Failed to validate program: ");
}
}
public void bind() {
glUseProgram(programID);
}
public void unbind() {
glUseProgram(0);
}
public void dispose() {
unbind();
glDetachShader(programID, vShaderID);
glDetachShader(programID, fShaderID);
glDeleteShader(vShaderID);
glDeleteShader(fShaderID);
glDeleteProgram(programID);
}
private static String loadShader(String file) {
StringBuilder shaderSource = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine()) != null) {
shaderSource.append(line).append("//\n");
}
reader.close();
} catch(IOException e){
e.printStackTrace();
System.exit(-1);
}
return shaderSource.toString();
}
}
Renderer
package ms.renderer;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import ms.renderer.VertexArrayObject.Vertex;
import ms.shaders.Shaders;
public class Renderer {
VertexArrayObject vertex = new VertexArrayObject();
Shaders shaders = new Shaders();
public void prepare() {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
public void render(Vertex vertex) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaders.bind();
glBindVertexArray(vertex.getVaoID());
glEnableVertexAttribArray(0);
glDrawElements(GL_TRIANGLES, vertex.getVertexCount(), GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
shaders.unbind();
}
public void clear() {
shaders.dispose();
vertex.cleanUp();
}
}
MainGame
package ms.main;
import static org.lwjgl.glfw.GLFW.*;
import ms.input.KeyboardInput;
import ms.renderer.Renderer;
import ms.renderer.VertexArrayObject;
import ms.renderer.VertexArrayObject.Vertex;
import ms.utils.FinalVariables;
public class MainGame implements Runnable {
private Thread thread;
private static Display display = new Display();
private static Renderer renderer = new Renderer();
private static VertexArrayObject loader = new VertexArrayObject();
private static int WIDTH = FinalVariables.WIDTH;
private static int HEIGHT = FinalVariables.HEIGHT;
private static String TITLE = FinalVariables.TITLE;
private boolean isRunning = false;
public static void main(String[] args) {
MainGame game = new MainGame();
display = new Display(WIDTH, HEIGHT, TITLE);
game.start();
}
public void start() {
isRunning = true;
thread = new Thread(this, "MainThread");
thread.start();
}
public void run() {
display.init();
display.libVersion();
float[] positions = 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,
};
int[] indices = new int[]{
0, 1, 3, 3, 1, 2
};
Vertex vertex = loader.loadToVAO(positions, indices);
while(isRunning) {
update();
renderer.prepare();
renderer.render(vertex);
if(glfwWindowShouldClose(display.window)) {
isRunning = false;
}
}
renderer.clear();
}
public void update() {
if(KeyboardInput.isKeyDown(GLFW_KEY_ESCAPE)) {
isRunning = false;
}
glfwSwapBuffers(display.window);
glfwPollEvents();
}
}
Display Where i call createCapabilities method
package ms.main;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWVidMode;
import ms.input.KeyboardInput;
public class Display {
#SuppressWarnings("unused")
private GLFWKeyCallback keyCallback;
private int width;
private int height;
private String title;
public long window;
public Display() {
}
public Display(int width, int height, String title) {
this.width = width;
this.height = height;
this.title = title;
}
public void init() {
glfwInit();
if(!glfwInit()) {
System.err.println("Failed to initialize GLFW");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_VISIBLE, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(width, height, title, NULL, NULL);
if(window == NULL) {
System.err.println("Failed to create Window");
}
keyCallback = glfwSetKeyCallback(window, keyCallback = new KeyboardInput());
GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window,
(vidMode.width() - width) / 2,
(vidMode.height() - height) / 2);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
createCapabilities();
}
public void libVersion() {
System.out.println("LWJGL Version: " + glfwGetVersionString());
System.out.println("OpenGL Version: " + glGetString(GL_VERSION));
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
The problem I think is in the createCapabilities() method position but I do not know how to solve.
State that I am a beginner and I'm getting closer now to the creation of video games.
Thanks in advance for any solutions.
I'm following the OpenGL 3D Game Tutorial series by ThinMatrix and everything seems to work fine except nothing appears in the window. I got to the 5th video.
My Loader Class
package org.voxsim;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
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 Models loadToVao(float[] pos, int[] ind) {
int vaoId = createVao();
bindIndBuffer(ind);
storeData(0,pos);
unbind();
return new Models(vaoId, ind.length);
}
public void cleanUp() {
for (int vao:vaos) {
GL30.glDeleteVertexArrays(vao);
}
for (int vbo:vbos) {
GL15.glDeleteBuffers(vbo);
}
}
private int createVao() {
int VaoId = GL30.glGenVertexArrays();
vaos.add(VaoId);
GL30.glBindVertexArray(VaoId);
return VaoId;
}
private void storeData(int num, float[] data) {
int VboId = GL15.glGenBuffers();
vbos.add(VboId);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VboId);
FloatBuffer buffer = storeInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(num,3,GL11.GL_FLOAT,false,0,0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private void unbind() {
GL30.glBindVertexArray(0);
}
private void bindIndBuffer(int[] ind) {
int vboId = GL15.glGenBuffers();
vbos.add(vboId);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboId);
IntBuffer buffer = storeInIntBuffer(ind);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
}
private IntBuffer storeInIntBuffer(int[] data) {
IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
private FloatBuffer storeInFloatBuffer(float[] data) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
My Render Class
package org.voxsim;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Render {
public void render(Models model) {
GL11.glColor4f(0.5f, 0.9f, 0.2f, 1.0f);
GL30.glBindVertexArray(model.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
}
My Model Class
package org.voxsim;
public class Models {
private int vaoID;
private int vaoNum;
public Models(int vaoID, int vaoNum) {
this.vaoID = vaoID;
this.vaoNum = vaoNum;
}
public int getVaoID() {
return vaoID;
}
public int getVertexCount() {
return vaoNum;
}
}
My Main Class
package org.voxsim;
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
import static org.lwjgl.opengl.GL11.GL_FALSE;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GLCapabilities;
import org.voxsim.game.Block;
import org.voxsim.shaders.Shader;
import org.voxsim.shaders.Static;
public class Game {
static public int width = 600;
static public int height = 400;
static public int vsync = 1;
static public String title = "VoxSim";
static private Loader loader = new Loader();
static private Render render = new Render();
private static void loop() {
Shader shader = new Static();
float[] v = {
-0.5f,0.5f,0,
-0.5f,-0.5f,0,
0.5f,-0.5f,0,
0.5f,0.5f,0
};
int[] ind = {
0,1,3,
3,1,2
};
Models model = loader.loadToVao(v, ind);
while (glfwWindowShouldClose(DisplayManager.windowID) == GL_FALSE) {
DisplayManager.updateDisplay();
shader.start();
render.render(model);
shader.stop();
}
shader.cleanUp();
}
public static void main(String[] args) {
DisplayManager.createDisplay();
DisplayManager.updateDisplay();
loop();
loader.cleanUp();
}
}
I followed the tutorial exactly but I don't know what's wrong. I am running an intel 4th gen i3 with intel hd graphics 4400 with 4GB of ram on windows 10 with
OpenGL Version 4.3,
OpenCL Version 1.2, and
Shader Model Version 5
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!