I've been trying OpenGL, following ThinMatrix's tutorials. Only thing I'm doing differently is he was using lwjgl 2 and i'm using 3. I thought it would be a good challenge, and it has definitely proven to be. It say's no glcapabilities have been set but I'm pretty sure I set them already!
Basically the full error I'm getting is
Exception in thread "main" java.lang.IllegalStateException: No GLCapabilities instance has been set for the current thread.
at org.lwjgl.opengl.GL.getCapabilities(GL.java:211)
at org.lwjgl.opengl.GL20.getInstance(GL20.java:378)
at org.lwjgl.opengl.GL20.glCreateShader(GL20.java:464)
at net.robharding.base.shaders.ShaderProgram.loadShader(ShaderProgram.java:67)
at net.robharding.base.shaders.ShaderProgram.<init>(ShaderProgram.java:17)
at net.robharding.base.shaders.StaticShader.<init>(StaticShader.java:9)
at net.robharding.base.engine.Display.init(Display.java:77)
at net.robharding.base.engine.Display.<init>(Display.java:31)
at net.robharding.base.MainComponent.main(MainComponent.java:8)
To me, this makes no sense because I Did do GL.CreateCapabilities();, and I can't find anything online about this error...
package net.robharding.base.engine;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import net.robharding.base.shaders.StaticShader;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryUtil.*;
public class Display {
private String title;
private int width, height;
#SuppressWarnings("unused")
private GLFWErrorCallback errorCallback;
#SuppressWarnings("unused")
private GLFWKeyCallback keyCallback;
private long windowID;
private Loader loader;
private Renderer renderer;
private StaticShader shader;
public Display(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
init();
}
private void keyPressed(int key, int scancode, int mods) {
}
private void keyReleased(int key, int scancode, int mods) {
if(key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(windowID, GLFW_TRUE);
}
private void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
glfwSetErrorCallback(errorCallback = GLFWErrorCallback.createPrint(System.err));
if(glfwInit() != GLFW_TRUE)
throw new IllegalStateException("Unable to initialize GLFW");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
windowID = glfwCreateWindow(width, height, title, NULL, NULL);
if(windowID == NULL)
throw new RuntimeException("Failed to create the GLFW window");
glfwSetKeyCallback(windowID, keyCallback = new GLFWKeyCallback() {
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if(action == GLFW_PRESS)
keyPressed(key, scancode, mods);
else if(action == GLFW_RELEASE)
keyReleased(key, scancode, mods);
}
});
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(windowID, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2);
glfwMakeContextCurrent(windowID);
glfwSwapInterval(1);
loader = new Loader();
renderer = new Renderer();
shader = new StaticShader();
glfwShowWindow(windowID);
}
public void run() {
GL.createCapabilities();
GL11.glViewport(0, 0, width, height);
float[] vertices = {
-0.5f, 0.5f, 0, // V1
-0.5f, -0.5f, 0, // V2
0.5f, -0.5f, 0, // V3
0.5f, 0.5f, 0 // V4
};
int[] indices = {
0, 1, 3,
3, 2, 1
};
RawModel model = loader.loadToVAO(vertices, indices);
while(glfwWindowShouldClose(windowID) == GLFW_FALSE) {
renderer.prepare();
shader.start();
renderer.render(model);
shader.stop();
glfwSwapBuffers(windowID);
glfwPollEvents();
}
shader.cleanUp();
loader.cleanUp();
}
}
Here is the method where it's tracing back to.
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");
}
reader.close();
} catch(IOException e) {
System.err.print("Count not read file!");
e.printStackTrace();
System.exit(-1);
}
int shaderID = GL20.glCreateShader(type);
GL20.glShaderSource(shaderID, shaderSource);
GL20.glCompileShader(shaderID);
if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
System.err.println("Could not compile shader!");
System.exit(-1);
}
return shaderID;
}
Your code tries to use OpenGL before you have created the context.
The init method in which the shader is created is called in the constructor, but the context is created in the begin of the run method. To solve this, move the call of the init method to the run method after GL.createCapabilities();.
Please also note, that OpenGL contexts are always associated with exactly one thread. So all OpenGL commands have to be issued from this one thread.
Related
I'm working on getting familiar with the LWJGL library for java and I've been following a few tutorials online and I can't seem to get a model rendered.
im using OpenGL 2.1(this seems to be very outdated but Im not really sure about how to update that, I know its tied in with the hardware you have, I'm using a MacBook Pro 2017 model if anyone is interested in my specs)
if someone could take a look at my code and tell me what im doing wrong I would really appreciate it! (all that is being rendered right now is a red window)
from the sources I've studied this code should result in a square made up of two triangles coloured in a gradient using a vertex and a fragment shader but instead nothing is being rendered.
public class Main {
private long window;
private int width = 1280, height = 720;
public void run() {
System.out.println("LWJGL " + Version.getVersion() + "!");
init();
loop();
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
glfwTerminate();
glfwSetErrorCallback(null).free();
}
private void init() {
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) throw new IllegalStateException("Unable to initialize GLFW");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
window = glfwCreateWindow(width, height, "TESTING", NULL, NULL);
if (window == NULL) throw new RuntimeException("Failed to create the GLFW window");
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) glfwSetWindowShouldClose(window, true); /
});
try (MemoryStack stack = stackPush()) {
IntBuffer pWidth = stack.mallocInt(1); // int*
IntBuffer pHeight = stack.mallocInt(1); // int*
glfwGetWindowSize(window, pWidth, pHeight);
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
}
private void loop() {
GL.createCapabilities();
GL11.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
Renderer renderer = new Renderer();
Loader loader = new Loader();
StaticShader shader = new StaticShader();
float[] vertices = {
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
};
int[] indicies = {
0,1,3,
3,1,2
};
RawModel model = loader.loadToVAO(vertices, indicies);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwSwapBuffers(window);
renderer.prepare();
shader.start();
renderer.render(model);
shader.stop();
glfwPollEvents();
}
loader.cleanUp();
shader.cleanUp();
}
public static void main(String[] args) {
new Main().run();
}
}
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;
}
}
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);
//System.out.println(model.getVertexCount());
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
}
public class Loader {
private List<Integer> vaos = new ArrayList<Integer>();
private List<Integer> vbos = new ArrayList<Integer>();
public RawModel loadToVAO(float[] positions,int[] indicies) {
int vaoID = createVAO();
bindIndecesBuffer(indicies);
storeDataInAttributeList(0, positions);
unbindVAO();
return new RawModel(vaoID, indicies.length);
}
private void bindIndecesBuffer(int[] indices) {
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboID);
IntBuffer buffer = storeDatainIntBuffer(indices);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
}
private IntBuffer storeDatainIntBuffer(int[] data) {
IntBuffer buffer = BufferUtils.createIntBuffer(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);
}
}
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 = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
public abstract class ShaderProgram {
private int programID;
private int vertexShaderID;
private int fragmentShaderID;
public ShaderProgram(String vertexFile,String fragmentFile){
vertexShaderID = loadShader(vertexFile,GL20.GL_VERTEX_SHADER);
fragmentShaderID = loadShader(fragmentFile,GL20.GL_FRAGMENT_SHADER);
programID = GL20.glCreateProgram();
GL20.glAttachShader(programID, vertexShaderID);
GL20.glAttachShader(programID, fragmentShaderID);
bindAttributes();
GL20.glLinkProgram(programID);
GL20.glValidateProgram(programID);
}
public void start(){
GL20.glUseProgram(programID);
}
public void stop(){
GL20.glUseProgram(0);
}
public void cleanUp(){
stop();
GL20.glDetachShader(programID, vertexShaderID);
GL20.glDetachShader(programID, fragmentShaderID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
GL20.glDeleteProgram(programID);
}
protected abstract void bindAttributes();
protected void bindAttribute(int attribute, String variableName){
GL20.glBindAttribLocation(programID, attribute, variableName);
}
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");
}
reader.close();
}catch(IOException e){
e.printStackTrace();
System.exit(-1);
}
int shaderID = GL20.glCreateShader(type);
GL20.glShaderSource(shaderID, shaderSource);
GL20.glCompileShader(shaderID);
if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS )== GL11.GL_FALSE){
System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
System.err.println("Could not compile shader!");
System.exit(-1);
}
return shaderID;
}
}
public class StaticShader extends ShaderProgram {
private static final String VERTEX_FILE = "src/shaderEngine/vertexShader.txt";
private static final String FRAGMENT_FILE = "src/shaderEngine/fragmentShader.txt";
public StaticShader() {
super(VERTEX_FILE, FRAGMENT_FILE);
}
#Override
protected void bindAttributes() {
super.bindAttribute(0, "position");
}
}
//VERTEX SHADER
#version 120
attribute vec3 position;
varying vec3 colour;
void main(void){
gl_Position = vec4(position,1.0);
colour = vec3(position.x+0.5,0.0,position.y+0.5);
}
//FRAGMENT SHADER
#version 120
varying vec3 colour;
void main(void){
gl_FragColor = vec4(colour,1.0);
}
Your code uses Vertex Array Objects (VAOs) for rendering. As the GL30 syntax of lwjgl already suggests, this is an OpenGL 3.0 feature. Running this code with a GL 2.1 context will only work if your implementation happens to implement the GL_ARB_vertex_array_object OpenGL extension.
im using OpenGL 2.1(this seems to be very outdated but Im not really sure about how to update that, I know its tied in with the hardware you have, I'm using a MacBook Pro 2017 model if anyone is interested in my specs)
YOu are limited to OpenGL 2.1 because you are using a legacy GL context. If you want somewhat modern OpenGL on OSX, you have to request a GL 3.2 core profile context at context creation. Also be warned that the most recent GL version that Apple is going to support is GL 4.1, and Apple actually declared OpenGL as deprecated and might remove it completely from future versions of OSX.
I'm trying to implement a game engine with lwjgl in a fashion that it would suit Android devices. As a consequence I have to use opengles.
So I tried the window creation which worked, I thought it's time to swap the opengl stuff to opengles.
However, on the line
GLES.createCapabilities();
I get an ExceptionInInitializerError:
Exception in thread "GAME_LOOP_THREAD"
java.lang.ExceptionInInitializerError
at engine.Window.init(Window.java:92)
Here is my Window class, where the exception is thrown:
package engine;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengles.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengles.GLES20.GL_FALSE;
import static org.lwjgl.opengles.GLES20.GL_TRUE;
import static org.lwjgl.opengles.GLES20.glClearColor;
import static org.lwjgl.system.MemoryUtil.NULL;
public class Window {
private final String title;
private int width;
private int height;
private long windowHandle;
private boolean resized;
private boolean vSync;
public Window(String title, int width, int height, boolean vSync) {
this.title = title;
this.width = width;
this.height = height;
this.vSync = vSync;
this.resized = false;
}
public void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set();
// Initialize GLFW. Most GLFW functions will not work before doing this.
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
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, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Create the window
windowHandle = glfwCreateWindow(width, height, title, NULL, NULL);
if (windowHandle == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
}
// Setup resize callback
glfwSetFramebufferSizeCallback(windowHandle, (window, width, height) -> {
this.width = width;
this.height = height;
this.setResized(true);
});
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(windowHandle, (window, key, scancode, action, mods) -> {
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
}
});
// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center our window
glfwSetWindowPos(
windowHandle,
(vidmode.width() - width) / 2,
(vidmode.height() - height) / 2
);
// Make the OpenGL context current
glfwMakeContextCurrent(windowHandle);
if (isvSync()) {
// Enable v-sync
glfwSwapInterval(1);
}
// Make the window visible
glfwShowWindow(windowHandle);
GLES.createCapabilities();
// Set the clear color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
public void setClearColor(float r, float g, float b, float a) {
glClearColor(r, g, b, a);
}
public boolean isKeyPressed(int keyCode) {
return glfwGetKey(windowHandle, keyCode) == GLFW_PRESS;
}
public boolean windowShouldClose() {
return glfwWindowShouldClose(windowHandle);
}
public String getTitle() {
return title;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public boolean isResized() {
return resized;
}
public void setResized(boolean resized) {
this.resized = resized;
}
public boolean isvSync() {
return vSync;
}
public void setvSync(boolean vSync) {
this.vSync = vSync;
}
public void update() {
glfwSwapBuffers(windowHandle);
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.
Here is my class that supposed to create app (main entry point is run method)
public class Geom {
public static class GLContextConfig {
int windowWidth = 800;
int windowHeight = 600;
int majorVersion = 3;
int minoVersion = 2;
int fsaaSamples = 0;
String windowTitle = "GLFW Geom";
GLContextFlags flags = new GLContextFlags();
public static class GLContextFlags {
int fullscreen = 1;
int vsync = 1;
int cursor = 1;
int stereo = 1;
int debug = 1;
int all;
}
}
private GLContextConfig glContextConfig = new GLContextConfig();
private Queue<IRenderable> objectQueue;
private FloatBuffer clearColorBuffer;
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
private long window;
public void run() {
try {
prepare();
mainLoop();
clear();
} finally {
glfwTerminate();
errorCallback.release();
}
}
public void putObjectToRenderQueue(IRenderable obj) {
objectQueue.add(obj);
}
private void prepare() {
glfwSetErrorCallback(errorCallback = GLFWErrorCallback.createPrint(System.err));
if (glfwInit() != GLFW_TRUE) {
throw new CoreException("Failed to initialize GLFW!");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, glContextConfig.majorVersion);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, glContextConfig.minoVersion);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, glContextConfig.fsaaSamples);
glfwWindowHint(GLFW_STEREO, glContextConfig.flags.stereo == 1 ? GL_TRUE : GL_FALSE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
if (glContextConfig.flags.fullscreen == 1) {
if (glContextConfig.windowWidth == 0 || glContextConfig.windowHeight == 0) {
glContextConfig.windowWidth = 0;
glContextConfig.windowHeight = 0;
}
}
window = glfwCreateWindow(glContextConfig.windowWidth, glContextConfig.windowHeight, glContextConfig.windowTitle, NULL, NULL);
if (NULL == window) {
throw new CoreException("Failed to create GLFW window!");
}
glfwSetWindowTitle(window, glContextConfig.windowTitle);
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, GLFW_TRUE);
}
}
});
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vidmode.width() - glContextConfig.windowWidth) / 2, (vidmode.height() - glContextConfig.windowHeight) / 2);
glfwMakeContextCurrent(window);
// v-sync
glfwSwapInterval(glContextConfig.flags.vsync);
glfwShowWindow(window);
}
private void mainLoop() {
GL.createCapabilities();
while (glfwWindowShouldClose(window) == GLFW_FALSE) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
render();
glfwSwapBuffers(window);
glfwPollEvents();
}
}
private void render() {
double time = glfwGetTime();
clearColorBuffer = BufferSupportUtils.makeFloatBuffer(
ArraySupportUtils.addOpacityToColor(
new float[] {
(float) (Math.sin(time) * 0.5f + 0.5f),
(float) (Math.cos(time) * 0.5f + 0.5f),
0.0f
},
1.0f
)
);
GL30.glClearBufferfv(GL11.GL_COLOR, 0, clearColorBuffer);
}
private void clear() {
glfwDestroyWindow(window);
keyCallback.release();
}
}
But I get this error
[LWJGL] GLFW_FORMAT_UNAVAILABLE error
Description : WGL: Failed to find a suitable pixel format
Stacktrace :
org.lwjgl.glfw.GLFW.nglfwCreateWindow(GLFW.java:1168)
org.lwjgl.glfw.GLFW.glfwCreateWindow(GLFW.java:1251)
com.chucke.geom.core.Geom.prepare(Geom.java:125)
com.chucke.geom.core.Geom.run(Geom.java:88)
com.chucke.geom.EntryPoint.main(EntryPoint.java:11)
Exception in thread "main" com.chucke.geom.core.prototype.exception.CoreException: Failed to create GLFW window!
at com.chucke.geom.core.Geom.prepare(Geom.java:127)
at com.chucke.geom.core.Geom.run(Geom.java:88)
at com.chucke.geom.EntryPoint.main(EntryPoint.java:11)
The error references to that line
window = glfwCreateWindow(glContextConfig.windowWidth, glContextConfig.windowHeight, glContextConfig.windowTitle, NULL, NULL);
What's the problem?
P.S I use OpenGL Bible + lwjgl with adjustments
GLFW "WGL: Failed to find a suitable pixel format"
The issue was with
glfwWindowHint(GLFW_STEREO, glContextConfig.flags.stereo == 1 ? GL_TRUE : GL_FALSE);
as I am using integrated Intel video.
So, how do I rotate a triangle by pressing Up, Down, Left or Right. I have a Keyboard class which can read keys and create events. But I don't know the function for rotating in LWJGL 3. I think I'm familiar with the classic gl.h way of rotating, but since LWJGL 3 is pretty new there aren't alot of information on this. Here is code for Display class and KeyboardHandler class.
Display
public class Driver implements Runnable{
private GLFWKeyCallback keyCallback;
private Thread thread = new Thread();
private boolean running = false;
public long window;
private static final int WIDTH = 600;
private static final int HEIGHT = WIDTH / 12 * 9;
public Driver(){
}
private synchronized void start(){
thread.start();
running = true;
}
private synchronized void stop(){
try {
thread.join();
running = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run(){
init();
while(running){
render();
update();
if(glfwWindowShouldClose(window) == GL_TRUE){
running = false;
keyCallback.release();
}
}
}
public void init() {
if(glfwInit() != GL_TRUE){
System.err.println("Failed to initilaize OpenGL");
}
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, "Endless", NULL, NULL);
if(window == NULL){
System.err.println("Could not create window. ");
}
glfwSetKeyCallback(window, keyCallback = new KeyboardHandler());
ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, 100, 100);
glfwMakeContextCurrent(window);
glfwShowWindow(window);
}
public void update() {
if(KeyboardHandler.isKeyDown(GLFW_KEY_LEFT)){
//event who'll start rotation
}
glfwPollEvents();
}
public void render() {
GLContext.createFromCurrent();
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(-1.0f / 2, -1.0f / 2);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(0.0f / 2, 1.0f / 2);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2f(1.0f / 2, -1.0f / 2);
glEnd();
//rotation of triangle
glfwSwapBuffers(window);
}
public static void main(String[] args) {
Driver game = new Driver();
game.start();
game.run();
}
}
And KeyboardHandler
public class KeyboardHandler extends GLFWKeyCallback{
private static boolean keys[] = new boolean[65536];
public void invoke(long window, int key, int scancode, int action, int mods)
{
keys[key] = action != GLFW_RELEASE;
}
public static boolean isKeyDown(int keycode){
return keys[keycode];
}
}
I guess the rotation itself should happen in render() while the keycallback who triggers it should be in update()
With the introduction of LWJGL 3, you must use shaders to rotate, scale, and transform your objects. You can find many resources on the internet that show you how to do this, one of them being the OpenGL programming WikiBook. Specifically, in tutorial four, which deals with rotating objects in modern OpenGL