Having problems showing the textures on my 3D box in LWJGL using slick.
Earlier I had the error:
WARN:class org.newdawn.slick.opengl.PNGImageData failed to read the data
java.lang.UnsupportedOperationException: Unsupported format for this image
Saying it couldnt read the image. So I converted the image to 24bit (also tried 8bit) and now i only get:
INFO:Use Java PNG Loader = true
My 3D cube is shown but no textures on it. Dont know what to do to make it show my textures.
Textures class:
package com.base.engine;
import static org.lwjgl.opengl.GL11.*;
public class Texture {
private int id;
public Texture(int id) {
this.id = id;
}
public void bind() {
glBindTexture(GL_TEXTURE_2D, id);
}
public int getID() {
return id;
}
}
Material class
package com.base.engine;
public class Material
{
private Texture texture;
private Vector3f color;
public Material(Texture texture)
{
this(texture, new Vector3f(1,1,1));
}
public Material(Texture texture, Vector3f color)
{
this.texture = texture;
this.color = color;
}
public Texture getTexture()
{
return texture;
}
public void setTexture(Texture texture)
{
this.texture = texture;
}
public Vector3f getColor()
{
return color;
}
public void setColor(Vector3f color)
{
this.color = color;
}
}
Game class:
package com.base.engine;
import java.io.FileInputStream;
import java.io.InputStream;
public class Game
{
private Mesh mesh;
private Shader shader;
private Material material;
private Transform transform;
private Camera camera;
public Game()
{
mesh = ResourceLoader.loadMesh("box.obj");
material = new Material(ResourceLoader.loadTexture("test.png"), new Vector3f(0,1,1));
shader = BasicShader.getInstance();
camera = new Camera();
// Vertex[] vertices = new Vertex[] {new Vertex(new Vector3f(-1,-1,0), new Vector2f(0,0)),
// new Vertex(new Vector3f(0,1,0), new Vector2f(0.5f,0)),
// new Vertex(new Vector3f(1,-1,0), new Vector2f(1.0f,0)),
// new Vertex(new Vector3f(0,-1,1), new Vector2f(0.5f,1.0f))};
//
// int[] indices = new int[] {3,1,0,
// 2,1,3,
// 0,1,2,
// 0,2,3};
//
// mesh.addVertices(vertices, indices);
Transform.setProjection(70f, Window.getWidth(), Window.getHeight(), 0.1f, 1000);
Transform.setCamera(camera);
transform = new Transform();
}
public void input()
{
camera.input();
// if(Input.getKeyDown(Input.KEY_UP))
// System.out.println("We've just pressed up!");
// if(Input.getKeyUp(Input.KEY_UP))
// System.out.println("We've just released up!");
//
// if(Input.getMouseDown(1))
// System.out.println("We've just right clicked at " + Input.getMousePosition().toString());
// if(Input.getMouseUp(1))
// System.out.println("We've just released right mouse button!");
}
float temp = 0.0f;
public void update()
{
temp += Time.getDelta();
float sinTemp = (float)Math.sin(temp);
transform.setTranslation(sinTemp, 0, 5);
transform.setRotation(0, sinTemp * 180, 0);
//transform.setScale(0.7f * sinTemp, 0.7f * sinTemp, 0.7f * sinTemp);
}
public void render()
{
RenderUtil.setClearColor(Transform.getCamera().getPos().div(2048f).abs());
shader.bind();
shader.updateUniforms(transform.getTransformation(), transform.getProjectedTransformation(), material);
mesh.draw();
}
}
RenderUtil class:
package com.base.engine;
import static org.lwjgl.opengl.GL11.*;
public class RenderUtil
{
public static void clearScreen()
{
//TODO: Stencil Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
public static void setTextures(boolean enabled)
{
if(enabled)
glEnable(GL_TEXTURE_2D);
else
glDisable(GL_TEXTURE_2D);
}
public static void unbindTextures()
{
glBindTexture(GL_TEXTURE_2D, 0);
}
public static void setClearColor(Vector3f color)
{
glClearColor(color.getX(), color.getY(), color.getZ(), 1.0f);
}
public static void initGraphics()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glFrontFace(GL_CW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
//TODO: Depth clamp for later
glEnable(GL_TEXTURE_2D);
glEnable(GL_FRAMEBUFFER_SRGB);
}
public static String getOpenGLVersion()
{
return glGetString(GL_VERSION);
}
}
Shader class:
package com.base.engine;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL32.*;
import java.util.HashMap;
public class Shader
{
private int program;
private HashMap<String, Integer> uniforms;
public Shader()
{
program = glCreateProgram();
uniforms = new HashMap<String, Integer>();
if(program == 0)
{
System.err.println("Shader creation failed: Could not find valid memory location in constructor");
System.exit(1);
}
}
public void bind()
{
glUseProgram(program);
}
public void updateUniforms(Matrix4f worldMatrix, Matrix4f projectedMatrix, Material material)
{
}
public void addUniform(String uniform)
{
int uniformLocation = glGetUniformLocation(program, uniform);
if(uniformLocation == 0xFFFFFFFF)
{
System.err.println("Error: Could not find uniform: " + uniform);
new Exception().printStackTrace();
System.exit(1);
}
uniforms.put(uniform, uniformLocation);
}
public void addVertexShader(String text)
{
addProgram(text, GL_VERTEX_SHADER);
}
public void addGeometryShader(String text)
{
addProgram(text, GL_GEOMETRY_SHADER);
}
public void addFragmentShader(String text)
{
addProgram(text, GL_FRAGMENT_SHADER);
}
public void compileShader()
{
glLinkProgram(program);
if(glGetProgram(program, GL_LINK_STATUS) == 0)
{
System.err.println(glGetProgramInfoLog(program, 1024));
System.exit(1);
}
glValidateProgram(program);
if(glGetProgram(program, GL_VALIDATE_STATUS) == 0)
{
System.err.println(glGetProgramInfoLog(program, 1024));
System.exit(1);
}
}
private void addProgram(String text, int type)
{
int shader = glCreateShader(type);
if(shader == 0)
{
System.err.println("Shader creation failed: Could not find valid memory location when adding shader");
System.exit(1);
}
glShaderSource(shader, text);
glCompileShader(shader);
if(glGetShader(shader, GL_COMPILE_STATUS) == 0)
{
System.err.println(glGetShaderInfoLog(shader, 1024));
System.exit(1);
}
glAttachShader(program, shader);
}
public void setUniformi(String uniformName, int value)
{
glUniform1i(uniforms.get(uniformName), value);
}
public void setUniformf(String uniformName, float value)
{
glUniform1f(uniforms.get(uniformName), value);
}
public void setUniform(String uniformName, Vector3f value)
{
glUniform3f(uniforms.get(uniformName), value.getX(), value.getY(), value.getZ());
}
public void setUniform(String uniformName, Matrix4f value)
{
glUniformMatrix4(uniforms.get(uniformName), true, Util.createFlippedBuffer(value));
}
}
BasicShader class:
package com.base.engine;
public class BasicShader extends Shader
{
private static final BasicShader instance = new BasicShader();
public static BasicShader getInstance()
{
return instance;
}
private BasicShader()
{
super();
addVertexShader(ResourceLoader.loadShader("basicVertex.vs"));
addFragmentShader(ResourceLoader.loadShader("basicFragment.fs"));
compileShader();
addUniform("transform");
addUniform("color");
}
public void updateUniforms(Matrix4f worldMatrix, Matrix4f projectedMatrix, Material material)
{
if(material.getTexture() != null)
material.getTexture().bind();
else
RenderUtil.unbindTextures();
setUniform("transform", projectedMatrix);
setUniform("color", material.getColor());
}
}
basicVertex.vs
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
out vec2 texCoord0;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(position, 1.0);
texCoord0 = texCoord;
}
basicFragment.fs
#version 330
in vec2 texCoord0;
out vec4 fragColor;
uniform vec3 color;
uniform sampler2D sampler;
void main()
{
vec4 textureColor = texture(sampler, texCoord0.xy);
if(textureColor == vec4(0,0,0,0))
fragColor = vec4(color, 1);
else
fragColor = textureColor * vec4(color, 1);
}
Thanks for the help!
According to the code you have provided, you have never actually bound a texture.
I see you have imported org.lwjgl.opengl.GL11.* but have something called a "shader" that you bind in your code. Are you using the fixed-function pipeline or shaders? I ask because if you really are using only OpenGL 1.1 in your software, you will also need to enable GL_TEXTURE_2D.
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've been following a tutorial by LWJGLGameDev on LWJGL found at https://lwjglgamedev.gitbooks.io/3d-game-development-with-lwjgl/content/. I'm using its source code and have my project set up the same way as theirs. Everything seemed fine until I tried to run the code from the tutorial in chapter 8 when the Renderer tries to create the modelViewMatrix uniform and it throws an exception that it could not find the uniform modelViewMatrix. I'm a newbie at LWJGL and openGL so I don't fully understand what is happening. Thank you in advance. Here is the relevant code:
public class Renderer {
/**
* Field of View in Radians
*/
private static final float FOV = (float) Math.toRadians(60.0f);
private static final float Z_NEAR = 0.01f;
private static final float Z_FAR = 1000.f;
private final Transformation transformation;
private ShaderProgram shaderProgram;
public Renderer() {
transformation = new Transformation();
}
public void init(Window window) throws Exception {
// Create shader
shaderProgram = new ShaderProgram();
shaderProgram.createVertexShader(Utils.loadResource("/shaders/vertex.vs"));
shaderProgram.createFragmentShader(Utils.loadResource("/shaders/fragment.fs"));
shaderProgram.link();
// Create uniforms for modelView and projection matrices and texture
shaderProgram.createUniform("projectionMatrix");
shaderProgram.createUniform("texture_sampler");
shaderProgram.createUniform("modelViewMatrix");
}
public void clear() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
public void render(Window window, Camera camera, GameItem[] gameItems) {
clear();
if ( window.isResized() ) {
glViewport(0, 0, window.getWidth(), window.getHeight());
window.setResized(false);
}
shaderProgram.bind();
// Update projection Matrix
Matrix4f projectionMatrix = transformation.getProjectionMatrix(FOV, window.getWidth(), window.getHeight(), Z_NEAR, Z_FAR);
shaderProgram.setUniform("projectionMatrix", projectionMatrix);
// Update view Matrix
Matrix4f viewMatrix = transformation.getViewMatrix(camera);
shaderProgram.setUniform("texture_sampler", 0);
// Render each gameItem
for(GameItem gameItem : gameItems) {
// Set model view matrix for this item
Matrix4f modelViewMatrix = transformation.getModelViewMatrix(gameItem, viewMatrix);
shaderProgram.setUniform("modelViewMatrix", modelViewMatrix);
// Render the mes for this game item
gameItem.getMesh().render();
}
shaderProgram.unbind();
}
public void cleanup() {
if (shaderProgram != null) {
shaderProgram.cleanup();
}
}
}
ShaderProgram:
public class ShaderProgram {
private final int programId;
private int vertexShaderId;
private int fragmentShaderId;
private final Map<String, Integer> uniforms;
public ShaderProgram() throws Exception {
programId = glCreateProgram();
if (programId == 0) {
throw new Exception("Could not create Shader");
}
uniforms = new HashMap<>();
}
public void createUniform(String uniformName) throws Exception {
int uniformLocation = glGetUniformLocation(programId, uniformName);
if (uniformLocation < 0) {
throw new Exception("Could not find uniform:" + uniformName);
}
uniforms.put(uniformName, uniformLocation);
}
public void setUniform(String uniformName, Matrix4f value) {
try (MemoryStack stack = MemoryStack.stackPush()) {
// Dump the matrix into a float buffer
FloatBuffer fb = stack.mallocFloat(16);
value.get(fb);
glUniformMatrix4fv(uniforms.get(uniformName), false, fb);
}
}
public void setUniform(String uniformName, int value) {
glUniform1i(uniforms.get(uniformName), value);
}
public void createVertexShader(String shaderCode) throws Exception {
vertexShaderId = createShader(shaderCode, GL_VERTEX_SHADER);
}
public void createFragmentShader(String shaderCode) throws Exception {
fragmentShaderId = createShader(shaderCode, GL_FRAGMENT_SHADER);
}
protected int createShader(String shaderCode, int shaderType) throws Exception {
int shaderId = glCreateShader(shaderType);
if (shaderId == 0) {
throw new Exception("Error creating shader. Type: " + shaderType);
}
glShaderSource(shaderId, shaderCode);
glCompileShader(shaderId);
if (glGetShaderi(shaderId, GL_COMPILE_STATUS) == 0) {
throw new Exception("Error compiling Shader code: " + glGetShaderInfoLog(shaderId, 1024));
}
glAttachShader(programId, shaderId);
return shaderId;
}
public void link() throws Exception {
glLinkProgram(programId);
if (glGetProgrami(programId, GL_LINK_STATUS) == 0) {
throw new Exception("Error linking Shader code: " + glGetProgramInfoLog(programId, 1024));
}
if (vertexShaderId != 0) {
glDetachShader(programId, vertexShaderId);
}
if (fragmentShaderId != 0) {
glDetachShader(programId, fragmentShaderId);
}
glValidateProgram(programId);
if (glGetProgrami(programId, GL_VALIDATE_STATUS) == 0) {
System.err.println("Warning validating Shader code: " + glGetProgramInfoLog(programId, 1024));
}
}
public void bind() {
glUseProgram(programId);
}
public void unbind() {
glUseProgram(0);
}
public void cleanup() {
unbind();
if (programId != 0) {
glDeleteProgram(programId);
}
}
}
Transformation:
public class Transformation {
private final Matrix4f projectionMatrix;
private final Matrix4f modelViewMatrix;
private final Matrix4f viewMatrix;
public Transformation() {
projectionMatrix = new Matrix4f();
modelViewMatrix = new Matrix4f();
viewMatrix = new Matrix4f();
}
public final Matrix4f getProjectionMatrix(float fov, float width, float height, float zNear, float zFar) {
float aspectRatio = width / height;
projectionMatrix.identity();
projectionMatrix.perspective(fov, aspectRatio, zNear, zFar);
return projectionMatrix;
}
public Matrix4f getViewMatrix(Camera camera) {
Vector3f cameraPos = camera.getPosition();
Vector3f rotation = camera.getRotation();
viewMatrix.identity();
// First do the rotation so camera rotates over its position
viewMatrix.rotate((float)Math.toRadians(rotation.x), new Vector3f(1, 0, 0))
.rotate((float)Math.toRadians(rotation.y), new Vector3f(0, 1, 0));
// Then do the translation
viewMatrix.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z);
return viewMatrix;
}
public Matrix4f getModelViewMatrix(GameItem gameItem, Matrix4f viewMatrix) {
Vector3f rotation = gameItem.getRotation();
modelViewMatrix.identity().translate(gameItem.getPosition()).
rotateX((float)Math.toRadians(-rotation.x)).
rotateY((float)Math.toRadians(-rotation.y)).
rotateZ((float)Math.toRadians(-rotation.z)).
scale(gameItem.getScale());
Matrix4f viewCurr = new Matrix4f(viewMatrix);
return viewCurr.mul(modelViewMatrix);
}
}
Utils:
public class Utils {
public static String loadResource(String fileName) throws Exception {
String result;
try (InputStream in = Utils.class.getClass().getResourceAsStream(fileName);
Scanner scanner = new Scanner(in, "UTF-8")) {
result = scanner.useDelimiter("\\A").next();
}
return result;
}
}
GameItem:
public class GameItem
{
private final Mesh mesh;
private final Vector3f position;
private float scale;
private final Vector3f rotation;
public GameItem(Mesh mesh)
{
this.mesh=mesh;
position=new Vector3f(0,0,0);
scale=1;
rotation=new Vector3f(0,0,0);
}
public Vector3f getPosition()
{
return position;
}
public void setPosition(float x, float y, float z)
{
this.position.x=x;
this.position.y=y;
this.position.z=z;
}
public float getScale()
{
return scale;
}
public void setScale(float scale)
{
this.scale=scale;
}
public Vector3f getRotation()
{
return rotation;
}
public void setRotation(float x, float y, float z) {
this.rotation.x = x;
this.rotation.y = y;
this.rotation.z = z;
}
public Mesh getMesh() {
return mesh;
}
}
Mesh:
public class Mesh {
private final int vaoId;
private final List<Integer> vboIdList;
private final int vertexCount;
private final Texture texture;
public Mesh(float[] positions, float[] textCoords, int[] indices, Texture texture) {
FloatBuffer posBuffer = null;
FloatBuffer textCoordsBuffer = null;
IntBuffer indicesBuffer = null;
try {
this.texture = texture;
vertexCount = indices.length;
vboIdList = new ArrayList();
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
// Position VBO
int vboId = glGenBuffers();
vboIdList.add(vboId);
posBuffer = MemoryUtil.memAllocFloat(positions.length);
posBuffer.put(positions).flip();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, posBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
// Texture coordinates VBO
vboId = glGenBuffers();
vboIdList.add(vboId);
textCoordsBuffer = MemoryUtil.memAllocFloat(textCoords.length);
textCoordsBuffer.put(textCoords).flip();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, textCoordsBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
// Index VBO
vboId = glGenBuffers();
vboIdList.add(vboId);
indicesBuffer = MemoryUtil.memAllocInt(indices.length);
indicesBuffer.put(indices).flip();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
} finally {
if (posBuffer != null) {
MemoryUtil.memFree(posBuffer);
}
if (textCoordsBuffer != null) {
MemoryUtil.memFree(textCoordsBuffer);
}
if (indicesBuffer != null) {
MemoryUtil.memFree(indicesBuffer);
}
}
}
public int getVaoId() {
return vaoId;
}
public int getVertexCount() {
return vertexCount;
}
public void render() {
// Activate firs texture bank
glActiveTexture(GL_TEXTURE0);
// Bind the texture
glBindTexture(GL_TEXTURE_2D, texture.getId());
// Draw the mesh
glBindVertexArray(getVaoId());
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawElements(GL_TRIANGLES, getVertexCount(), GL_UNSIGNED_INT, 0);
// Restore state
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);
}
public void cleanUp() {
glDisableVertexAttribArray(0);
// Delete the VBOs
glBindBuffer(GL_ARRAY_BUFFER, 0);
for (int vboId : vboIdList) {
glDeleteBuffers(vboId);
}
// Delete the texture
texture.cleanup();
// Delete the VAO
glBindVertexArray(0);
glDeleteVertexArrays(vaoId);
}
}
Window:
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);
GL.createCapabilities();
// Set the clear color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
}
public long getWindowHandle() {
return windowHandle;
}
public void setClearColor(float r, float g, float b, float alpha) {
glClearColor(r, g, b, alpha);
}
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();
}
}
Never mind, the problem was that the vertex.vs file had to specify the uniform:
#version 330
layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;
out vec2 outTexCoord;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
outTexCoord = texCoord;
}
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 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!