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();
}
}
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 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.
All, Having difficulty with glGenVertexArrays(). I get the following error:
Exception in thread "main" java.lang.IllegalStateException: This functionality is not available.
at org.lwjgl.system.Checks.checkFunctionality(Checks.java:57)
at org.lwjgl.opengl.GL30.getInstance(GL30.java:667)
at org.lwjgl.opengl.GL30.getInstance(GL30.java:662)
at org.lwjgl.opengl.GL30.nglGenVertexArrays(GL30.java:2789)
at org.lwjgl.opengl.GL30.glGenVertexArrays(GL30.java:2816)
at renderEngine.Loader.createVAO(Loader.java:26)
at renderEngine.Loader.loadToVAO(Loader.java:19)
at renderEngine.MainGameLoop.main(MainGameLoop.java:27)
Here is my Main Game Loop (I call GL.createCapabilities() from the createDisplay() method.)
package renderEngine;
import static org.lwjgl.glfw.GLFW.*;
public class MainGameLoop {
public static DisplayManager dm = new DisplayManager();
public static void main(String[] args) {
//Create Display
dm.createDisplay();
Loader loader = new Loader();
Renderer renderer = new Renderer();
float[] vertices = {
-0.5f,0.5f,0f,
-0.5f,-0.5f,0f,
0.5f,-0.5f,0f,
0.5f,-0.5f,0f,
0.5f,0.5f,0f,
-0.5f,0.5f,0f
};
RawModel model = loader.loadToVAO(vertices);
//Game Loop
while (glfwWindowShouldClose(dm.getWindowID()) != GLFW_TRUE) {
renderer.prepare();
renderer.render(model);
dm.updateDisplay();
}
//Destroy Display
dm.destroyWindow();
loader.cleanUp();
}
}
As referenced above, here is the Display Manager class:
package renderEngine;
import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;
public class DisplayManager {
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
private long windowID;
//Constructor
public DisplayManager(){
init();
}
private void init(){
if(glfwInit() != GLFW_TRUE){
throw new IllegalStateException("Unable to initiate GLFW");
}
}
public long createDisplay(){
windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
if(windowID == 0){
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
GLFW.glfwSetWindowTitle(windowID, "GLFW Window");
setErrorCallback();
setKeyCallback();
glfwMakeContextCurrent(windowID);
GL.createCapabilities();
return windowID;
}
public long getWindowID(){
return this.windowID;
}
private void setErrorCallback(){
errorCallback = GLFWErrorCallback.createPrint(System.err);
glfwSetErrorCallback(errorCallback);
}
private void setKeyCallback(){
keyCallback = new GLFWKeyCallback(){
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
}
};
glfwSetKeyCallback(windowID, keyCallback);
}
public void updateDisplay(){
GLFW.glfwSwapInterval(1);
glfwSwapBuffers(windowID);
glfwPollEvents();
}
public void destroyWindow(){
glfwDestroyWindow(windowID);
keyCallback.release();
glfwTerminate();
errorCallback.release();
}
}
If would seem the above mentioned error is with the loader class:
package renderEngine;
import java.util.List;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Loader {
private List<Integer> vaos = new ArrayList<Integer>();
private List<Integer> vbos = new ArrayList<Integer>();
public RawModel loadToVAO(float[] positions){
int vaoID = createVAO();
storeDataInAttributeList(0,positions);
unbindVAO();
return new RawModel(vaoID,positions.length/3);
}
private int createVAO() {
int vaoID = GL30.glGenVertexArrays();
vaos.add(vaoID);
GL30.glBindVertexArray(vaoID);
return vaoID;
}
private void storeDataInAttributeList(int attributeNumber, float[] data) {
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private void unbindVAO() {
GL30.glBindVertexArray(0); //0 un-binds currently bound VAO
}
public void cleanUp(){
for(int vao:vaos){
GL30.glDeleteVertexArrays(vao);
}
for(int vbo:vbos){
GL15.glDeleteBuffers(vbo);
}
}
private FloatBuffer storeDataInFloatBuffer(float[] data){
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}
In Particular this line of code:
GL30.glBindVertexArray(vaoID);
As far as I can see this is the correct method to do it, and the GL capabilities/context have been set/called from the main thread (main game loops main method, utilising the display manager)
For completeness, here are the RawModel and Renderer Classes, do not suspect an issue these these:
package renderEngine;
public class RawModel {
private int vaoID;
private int vertexCount;
public RawModel(int vaoID, int vertexCount){
this.vaoID = vaoID;
this.vertexCount = vertexCount;
}
public int getVaoID() {
return vaoID;
}
public int getVertexCount() {
return vertexCount;
}
}
And here is the Renderer Class:
package renderEngine;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class Renderer {
public void prepare(){
GL11.glClearColor(1, 0, 0, 1);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
}
public void render(RawModel model){
GL30.glBindVertexArray(model.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, model.getVertexCount());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
}
Any assistance you can give me regarding my implementation of 'glGenVertexArrays' would be much appreciated.
I have now added the following
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
However, am now getting the following error:
Exception in thread "main" java.lang.RuntimeException: Failed to create the GLFW window
at renderEngine.DisplayManager.createDisplay(DisplayManager.java:37)
at renderEngine.MainGameLoop.main(MainGameLoop.java:12)
The specific implementation of my createDisplay() is as follows:
public long createDisplay(){
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
if(windowID == 0){
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
GLFW.glfwSetWindowTitle(windowID, "GLFW Window");
setErrorCallback();
setKeyCallback();
glfwMakeContextCurrent(windowID);
GL.createCapabilities();
return windowID;
}
UPDATE
If have removed the error callbacks, as thought they might be causing an issue. The resulting error is:
Exception in thread "main" java.lang.RuntimeException: Failed to create the GLFW window
at renderEngine.DisplayManager.createDisplay(DisplayManager.java:40)
at renderEngine.MainGameLoop.main(MainGameLoop.java:12)
It seems the RuntimeException is being thrown, and is displaying my custom error message if the glfw window cannot be created. Could this be todo with the order in which I run this? I have played around with the placement of the 'init' method with noluck. There has got to be something I am overlooking?... Thanks.
Updated code for the Display Manager:
package renderEngine;
import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;
public class DisplayManager {
private GLFWErrorCallback errorCallback;
private GLFWKeyCallback keyCallback;
private long windowID;
//Constructor
public DisplayManager(){
init();
}
private void init(){
if(glfwInit() != GLFW_TRUE){
throw new IllegalStateException("Unable to initiate GLFW");
}
}
public long createDisplay(){
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
windowID = glfwCreateWindow(640,480,"Hello World!", 0, 0);
System.out.println(windowID);
if(windowID == 0){
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
glfwMakeContextCurrent(windowID);
GL.createCapabilities();
GLFW.glfwSetWindowTitle(windowID, "GLFW Window");
//setErrorCallback();
//setKeyCallback();
return windowID;
}
public long getWindowID(){
return this.windowID;
}
private void setErrorCallback(){
errorCallback = GLFWErrorCallback.createPrint(System.err);
glfwSetErrorCallback(errorCallback);
}
private void setKeyCallback(){
keyCallback = new GLFWKeyCallback(){
#Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
}
};
glfwSetKeyCallback(windowID, keyCallback);
}
public void updateDisplay(){
GLFW.glfwSwapInterval(1);
glfwSwapBuffers(windowID);
glfwPollEvents();
}
public void destroyWindow(){
glfwDestroyWindow(windowID);
keyCallback.release();
glfwTerminate();
errorCallback.release();
}
}
Many Thanks and Kind Regards,
Jake
The glGenVertexArrays function requires OpenGL 3.0 or higher. You have to explicitly tell GLFW this. Before calling glfwCreateWindow:
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.CONTEXT_VERSION_MINOR, 0);
You can check that you have OpenGL 3.0 or higher by calling GL11.glGetString(GL11.GL_VERSION) or by looking at the GL.getCapabilities().OpenGL30 flag.
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!
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.