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();
}
}
Related
I am creating a 3D game using LWJGL3, and I want the window loaded in the background and hidden, wait for my game setup and only than showing up.
My problem is even if I call GLFW.glfwHideWindow(window) immidetly after GLFW.glfwCreateWindow(width, height, title, isFullscreen ? GLFW.glfwGetPrimaryMonitor() : 0, 0);
the window flickering, than load the game and than showing up (when I want).
How to prevent the window from flickering? Maybe I just change one of the arguments in GLFW.glfwCreateWindow?
My code:
Window class:
package renderEngine.io;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.glfw.GLFWWindowSizeCallback;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjglx.util.vector.Vector3f;
public class Window {
private int width, height;
private String title;
private long window;
private int frames;
private static long time;
private Input input;
private Vector3f background = new Vector3f(0, 0, 0);
private GLFWWindowSizeCallback sizeCallback;
private boolean isResized;
private boolean isFullscreen;
private int[] windowPosX = new int[1], windowPosY = new int[1];
public Window(int width, int height, String title) {
this.width = width;
this.height = height;
this.title = title;
}
public static void initLWJGL() {
if (!GLFW.glfwInit()) {
System.err.println("ERROR: GLFW wasn't initializied");
return;
}
}
public void create() {
initLWJGL();
input = new Input();
window = GLFW.glfwCreateWindow(width, height, title, isFullscreen ? GLFW.glfwGetPrimaryMonitor() : 0, 0);
if (window == 0) {
System.err.println("ERROR: Window wasn't created");
return;
}
GLFW.glfwHideWindow(window);
GLFWVidMode videoMode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
windowPosX[0] = (videoMode.width() - width) / 2;
windowPosY[0] = (videoMode.height() - height) / 2;
GLFW.glfwSetWindowPos(window, windowPosX[0], windowPosY[0]);
GLFW.glfwMakeContextCurrent(window);
GL.createCapabilities();
GL11.glEnable(GL11.GL_DEPTH_TEST);
createCallbacks();
GLFW.glfwSwapInterval(1);
time = System.currentTimeMillis();
}
public void setVisible(boolean visible) {
if (visible) {
GLFW.glfwShowWindow(window);
}else {
GLFW.glfwHideWindow(window);
}
}
private void createCallbacks() {
sizeCallback = new GLFWWindowSizeCallback() {
public void invoke(long window, int w, int h) {
width = w;
height = h;
isResized = true;
}
};
GLFW.glfwSetKeyCallback(window, input.getKeyboardCallback());
GLFW.glfwSetCursorPosCallback(window, input.getMouseMoveCallback());
GLFW.glfwSetMouseButtonCallback(window, input.getMouseButtonsCallback());
GLFW.glfwSetScrollCallback(window, input.getMouseScrollCallback());
GLFW.glfwSetWindowSizeCallback(window, sizeCallback);
}
public void update() {
if (isResized) {
GL11.glViewport(0, 0, width, height);
isResized = false;
}
GL11.glClearColor(background.getX(), background.getY(), background.getZ(), 1.0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GLFW.glfwPollEvents();
frames++;
if (System.currentTimeMillis() > time + 1000) {
GLFW.glfwSetWindowTitle(window, title + " | FPS: " + frames);
time = System.currentTimeMillis();
frames = 0;
}
}
public void swapBuffers() {
GLFW.glfwSwapBuffers(window);
}
public boolean shouldClose() {
return GLFW.glfwWindowShouldClose(window);
}
public void destroy() {
input.destroy();
sizeCallback.free();
GLFW.glfwWindowShouldClose(window);
GLFW.glfwDestroyWindow(window);
GLFW.glfwTerminate();
}
public void setBackgroundColor(float r, float g, float b) {
background.set(r, g, b);
}
public boolean isFullscreen() {
return isFullscreen;
}
public void setFullscreen(boolean isFullscreen) {
this.isFullscreen = isFullscreen;
isResized = true;
if (isFullscreen) {
GLFW.glfwGetWindowPos(window, windowPosX, windowPosY);
GLFW.glfwSetWindowMonitor(window, GLFW.glfwGetPrimaryMonitor(), 0, 0, width, height, 0);
} else {
GLFW.glfwSetWindowMonitor(window, 0, windowPosX[0], windowPosY[0], width, height, 0);
}
}
public void mouseState(boolean lock) {
GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, lock ? GLFW.GLFW_CURSOR_DISABLED : GLFW.GLFW_CURSOR_NORMAL);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public String getTitle() {
return title;
}
public long getWindow() {
return window;
}
}
Main class:
package main;
import java.util.Calendar;
import org.lwjglx.util.vector.Vector3f;
import entities.Camera;
import entities.Light;
import gameplay.Car;
import models.RawModel;
import models.TexturedModel;
import renderEngine.Loader;
import renderEngine.MasterRenderer;
import renderEngine.OBJLoader;
import renderEngine.io.Window;
import shaders.StaticShader;
import terrains.Terrain;
import textures.ModelTexture;
import textures.TerrainTexture;
import textures.TerrainTexturesPack;
public class Main{
public static Window window = new Window(1000, 600, "Driving Game");
public static void main(String[] args) {
Light light = new Light(new Vector3f(3, -2, -20), new Vector3f(1, 1, 1));
Loader loader = new Loader();
Camera camera = new Camera(null);
camera.setAngleAround(180);
camera.setPitch(20);
camera.setDistance(10);
Car myCar = new Car(null, new Vector3f(0,0,0),0,0,0,1f);
myCar.setBonus_height(0.5f);
myCar.setBonus_rotation(new Vector3f(0, -90, 0));
camera.setPlayer(myCar);
window.create();
TexturedModel carTexturedModel = loadTexturedModel(loader, "/models/cars/Car1.obj", "/models/cars/texture.png");
myCar.setModel(carTexturedModel);
Terrain terrain = new Terrain(0, -1, loader,
new TerrainTexturesPack(new TerrainTexture(loader.loadTexture("/res/1/grassy")),
new TerrainTexture(loader.loadTexture("/res/1/dirt")),
new TerrainTexture(loader.loadTexture("/res/1/pinkFlowers")),
new TerrainTexture(loader.loadTexture("/res/1/path"))),
new TerrainTexture(loader.loadTexture("/res/1/blendMap")), "/res/heightmap");
StaticShader shader = new StaticShader();
MasterRenderer masterRenderer = new MasterRenderer(loader);
Calendar c = Calendar.getInstance();
int frames = 0;
window.setVisible(true);
while(!window.shouldClose()){
window.update();
frames++;
camera.move();
myCar.move(terrain);
shader.start();
masterRenderer.proccessTerrain(terrain);
masterRenderer.proccessEntity(myCar);
masterRenderer.render(light, camera);
shader.stop();
window.swapBuffers();
}
System.out.println("The game run at "
+ ((double)frames/(Calendar.getInstance().getTimeInMillis() - c.getTimeInMillis())*1000) + " FPS");
shader.cleanUp();
loader.cleanUp();
masterRenderer.cleanUp();
window.destroy();
}
public static TexturedModel loadTexturedModel(Loader loader, String objFile, String textureFile) {
RawModel rawModel = OBJLoader.loadObjModel(objFile, loader);
ModelTexture modelTexture = new ModelTexture(loader.loadTexture(textureFile));
TexturedModel texturedModel = new TexturedModel(rawModel, modelTexture);
return texturedModel;
}
}
Notice:
I have to create the window before loading the models into the VAO, so I can't move the window.create() method lower than where it is.
Thank for any answer!
Create a hidden window. See GLFW - Window visibility. Set the GLFW_VISIBLE property before creating the window
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
window = GLFW.glfwCreateWindow(width, height, title,
isFullscreen ? GLFW.glfwGetPrimaryMonitor() : 0, 0);
I am creating a program in Java, and would like to make my own button class as opposed to using a JButton. I've got all the aesthetics sorted out but I'm not sure how to get the mouse pressed event in Java.
This is my code:
// Button.java
package cella;
import java.awt.Color;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
public class Button extends MouseAdapter {
int x, y, w, h;
String ph, val;
boolean mouseDown;
Color LIGHTGRAY = new Color(200, 200, 200);
public Button(int xt, int yt, int wt, int ht, String pht, String valt) {
x = xt;
y = yt;
w = wt;
h = ht;
ph = pht;
val = valt;
mouseDown = false;
}
public void draw(Graphics g, Point mouse) {
if (contains(mouse)) {
g.setColor(Color.GRAY);
} else {
g.setColor(LIGHTGRAY);
}
g.fillRect(x, y, w, h);
g.setColor(Color.BLACK);
g.drawRect(x, y, w, h);
g.drawString(ph, x + 5, y + h - 5);
}
private boolean contains(Point pos) {
if (pos.x > x && pos.x < x + w && pos.y > y && pos.y < y + h) {
return true;
} else {
return false;
}
}
public boolean pressed(Point pos) {
if (contains(pos) && mouseDown) {
System.out.println("Pressed");
return true;
}
else return false;
}
}
The boolean mouseDown will be set to true when the mouse is pressed and then false when released however i can't find a way to catch these events, mouseListener gives errors about needing abstract classes when i try to implement it. Thanks for any help you can give me.
Full code
Try this.
JButton button = new JButton("Click!");
button.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.NOBUTTON) {
textArea.setText("No button clicked...");
} else if (e.getButton() == MouseEvent.BUTTON1) {
textArea.setText("Button 1 clicked...");
}
}
});
See available methods
Hope this help!
You can add a listener to your button that handles the event.
JButton button = new JButton("Click for Stuff");
button.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
switch(e.getButton())
{
case MouseEvent.NOBUTTON : // do stuff on button release
break;
case MouseEvent.BUTTON1 : // do stuff on click
break;
}
}
});
I know this question is a few years old, but I thought my input might be useful to someone down the road trying to accomplish the same task, considering I have some experience in custom UIs.
If you want a fully non-JComponent button, then you're going to need to also program your mouselistener and a UI Object Registry and a render/update function all operating on their required threads. I've done that, complete with NumberInputFields, Buttons, PasswordFields, TextFields, TextAreas, Graphics, and a variety of other UI objects. You don't want to unless you're going for a radically different look and feel than what is already supplied with very different functionality (for instance, my TextArea and TextField took in BitLines made up of TextBits rather than Strings, which allowed for each character to individually be formatted or colored or sized, complete with customized hover and click events). If such a different result is desired, you would do well to look into everything that goes into making a full UI within a Canvas object. If not, you have a couple other options.
Option 1: Extend the JButton class like has already been suggested. This is the easiest and likely the best option for you. It's fairly simple, and you can make that button be whatever you want it to be (within reason, of course).
Option 2: Create your own custom look and feel by extending the BasicLookAndFeel class. This is more complex and may take a bit of time and research, but in the end you can format all of your program to have a consistent L&F throughout, giving a satisfying and unique look to your software.
Here's an example of what it can take to make a button with basic functionality, completely separate from the JComponent class. Please note that this does NOT include the many background classes required to make this operate, such as the registry, the renderer, the animation and image loaders, the listeners, etc.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import dev.blue.neuron.storage.Animation;
public class Button extends UIObject {
private Animation whileDown;
private Animation whileUp;
private int tooltipTimer = 0;
private boolean showTooltip = false;
private boolean useTooltip = false;
protected boolean showingClicked = false;
protected boolean isSelected;
private boolean showID;
private int fontSize;
private Color color = Color.BLACK;
public Button(String id, boolean showID, boolean useTooltip, int fontSize, int x, int y, int width, int height,
int animationSpeed, Animation whileDown, Animation whileUp) {
this.id = id;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.whileDown = whileDown;
this.whileUp = whileUp;
this.bounds = new Rectangle(x, y, width, height);
this.showID = showID;
this.fontSize = fontSize;
this.useTooltip = useTooltip;
}
public void render(Graphics g) {
animate();
this.whileUp.render(g);
this.whileDown.render(g);
if (this.showID) {
g.setFont(new Font("Helvetica", 1, this.fontSize));
g.setColor(this.color);
g.drawString(this.id, this.x + this.width / 2 - g.getFontMetrics().stringWidth(this.id) / 2,
(int) ((this.y + this.height / 2) + g.getFontMetrics().getHeight() / 3.5D));
}
if (this.showTooltip && this.useTooltip) {
g.setFont(new Font("Helvetica", 0, 12));
g.setColor(Color.GRAY);
g.drawString(this.id, this.x, (int) (this.y + g.getFontMetrics().getHeight() * 1.5D));
}
}
public void setColor(Color color) {
this.color = color;
}
public void update() {
if (this.hovering) {
this.tooltipTimer++;
} else if (this.showingClicked) {
this.showingClicked = false;
}
if (this.tooltipTimer >= 50)
this.showTooltip = true;
runOnUpdate();
}
public void runOnUpdate() {
}
public void onMouseMove(Point p) {
if (this.bounds.contains(p)) {
if (!this.hovering) {
this.hovering = true;
runOnHover();
}
} else if (this.hovering) {
this.hovering = false;
this.showTooltip = false;
this.tooltipTimer = 0;
runOnStopHover();
}
}
private void animate() {
if (this.showingClicked) {
if (!this.whileDown.isRunning()) {
this.whileUp.end();
this.whileDown.run();
}
} else if (!this.whileUp.isRunning()) {
this.whileDown.end();
this.whileUp.run();
}
}
public boolean onClick(int button, Point p) {
if (this.bounds.contains(p)) {
runClick();
return true;
}
return false;
}
public void runOnMissedClick() {
}
public boolean onMouseDown(int button, Point p) {
if (this.bounds.contains(p)) {
(App.getInstance().getMouseManager()).clickedObject = this;
runMouseDown();
this.showingClicked = true;
return true;
}
return false;
}
public boolean onMouseUp(int button, Point p) {
if ((App.getInstance().getMouseManager()).clickedObject == this)
(App.getInstance().getMouseManager()).clickedObject = null;
if (!this.bounds.contains(p))
runOnMissedClick();
if (this.showingClicked) {
this.showingClicked = false;
if (this.bounds.contains(p)) {
runMouseUp();
onClick(button, p);
return true;
}
return false;
}
return false;
}
public void onType(KeyEvent e) {
}
public void onKeyPressed(KeyEvent e) {
}
public Animation getWhileUpAnim() {
return this.whileUp;
}
public Animation getWhileDownAnim() {
return this.whileDown;
}
public void setWhileUpAnim(Animation whileUp) {
this.whileUp = whileUp;
}
public void setWhileDownAnim(Animation whileDown) {
this.whileDown = whileDown;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
}
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'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.
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.