Search code examples
javaopenglglsllwjglglfw

OpenGL doesn't find context while coding shaders.: LWJGL


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.


Solution

  • 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();
        }
    }