1

I am trying to make a game for a school project, and everything works, except when I build to a jar, it doesn't render anything, and I have determined that it is because it cant find the shader file. Here is the code that reads the file.

public static int loadShader(String filepath, int type){
    StringBuilder result = new StringBuilder();

    try{
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filepath));
        String buffer = "";
        while((buffer = bufferedReader.readLine()) != null)
            result.append(buffer + "\n");
        bufferedReader.close();
    }catch (IOException e1){
        e1.printStackTrace();
    }

    int shaderID = glCreateShader(type);
    glShaderSource(shaderID, result.toString());
    glCompileShader(shaderID);
    if(glGetShaderi(shaderID, GL_COMPILE_STATUS) == GL_FALSE){
        System.err.println(glGetShaderInfoLog(shaderID, 500));
        System.err.println("Could not compile shader.");
        System.err.println(-1);
    }
    return shaderID;

}

This is where I need to put the path for the file

public static void loadAll(){
    shader1 = new Shader("src/com/myGame/shaders/vertex.shader", "src/com/myGame/shaders/fragment.shader");
    shader3 = new Shader("src/com/myGame/shaders/vertex3.shader", "src/com/myGame/shaders/fragment3.shader");
}

And this is the Shader class

public class Shader {
    private int programID;
    private int vertexShaderID;
    private int fragmentShaderID;

public Shader(String vertexFile, String fragmentFile){
    vertexShaderID = loadShader(vertexFile, GL_VERTEX_SHADER);
    fragmentShaderID = loadShader(fragmentFile, GL_FRAGMENT_SHADER);
    programID = glCreateProgram();
    glAttachShader(programID, vertexShaderID);
    glAttachShader(programID, fragmentShaderID);
    glLinkProgram(programID);
    glValidateProgram(programID);
}

public void start(){
    glUseProgram(programID);
}

public void stop(){
    glUseProgram(0);
}

public int getID(){
    return this.programID;
}

public int getUniform(String name){
    int result = glGetUniformLocation(programID, name);
    if(result == -1)
        System.err.println("Could not find uniform variable'" + name + "'!");
    return glGetUniformLocation(programID, name);
}

public void setUniform3f(String name, Vector3f vector) {
    glUniform3f(getUniform(name), vector.x, vector.y, vector.z);
}

}

This all works when I am compiling in IntelliJ, but not when I compile, build and run it as a jar. When I try to run it as a jar from the command prompt, it says that it can't figure out the variable pos which is put into the setUniform3f method in the shader class.

Edit: I am trying it with an InputStream, this is what I have, but it gets a Null Pointer exception.

    Exception in thread "Bot Fighting" java.lang.NullPointerException
at java.io.Reader.<init>(Reader.java:78)
at java.io.InputStreamReader.<init>(InputStreamReader.java:72)
at com.myGame.utils.Utilities.loadShader(Utilities.java:22)
at com.myGame.graphicsEngine.Shader.<init>(Shader.java:20)
at com.myGame.graphicsEngine.ShaderManager.loadAll(ShaderManager.java:20)
at com.myGame.gameEngine.Level.<init>(Level.java:21)
at com.myGame.main.BotMain.init(BotMain.java:50)
at com.myGame.main.BotMain.run(BotMain.java:58)
at java.lang.Thread.run(Thread.java:745)

This is my code with the InputStream

     public static int loadShader(String filepath, int type){
    StringBuilder result = new StringBuilder();
    InputStream in = ClassLoader.getSystemResourceAsStream(filepath);
    try{
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
        String buffer = "";
        while((buffer = bufferedReader.readLine()) != null)
            result.append(buffer + "\n");
        bufferedReader.close();
    }catch (IOException e1){
        e1.printStackTrace();
    }
    try {
        in.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    int shaderID = glCreateShader(type);
    glShaderSource(shaderID, result.toString());
    glCompileShader(shaderID);
    if(glGetShaderi(shaderID, GL_COMPILE_STATUS) == GL_FALSE){
        System.err.println(glGetShaderInfoLog(shaderID, 500));
        System.err.println("Could not compile shader.");
        System.err.println(-1);
    }
    return shaderID;

I am obviously not using this right, so how do I use this?

Seth G.
  • 427
  • 1
  • 4
  • 8
  • 3
    You should not rely on loading the shader files from the file system, especially not via relative paths. Relative paths are sensitive to the VM's working directory, which may vary. You should put your files in the jar, and access them via the `getResourceAsStream()` method of the `Class` object corresponding to one of your classes. For example, `Shader.class.getResourceAsStream("/shaders/vertex.shader")` (supposing you put the shaders in `/shader`, relative to the root of the jar). – John Bollinger May 20 '16 at 18:33
  • @JohnBollinger, that is what I have been seeing to do, but I can't figure out how to do it, when I try, it says that it can't do it in a static context. How would I implement that? – Seth G. May 20 '16 at 23:21
  • We cannot explain the errors you get in any detail without examining the code with which they are associated. There are, however, numerous questions that have previously been asked here and answered about the "non-static variable/method cannot be referenced from a static context" error, such as http://stackoverflow.com/questions/2559527/non-static-variable-cannot-be-referenced-from-a-static-context. – John Bollinger May 20 '16 at 23:47
  • @JohnBollinger Ok, I am trying to use the InputStream, it is in most recent edit – Seth G. May 21 '16 at 00:07

1 Answers1

1

Try this:

public static void loadAll(){
    shader1 = new Shader("com/myGame/shaders/vertex.shader", "com/myGame/shaders/fragment.shader");
    shader3 = new Shader("com/myGame/shaders/vertex3.shader", "com/myGame/shaders/fragment3.shader");
}

Without the "src/"

If it dont work, use this:

InputStreamReader(cls.getResourceAsStream(name))

where Class<?> cls is some class that is in the same package as the shaders and String name is the file name, something like:

public static int loadShader(Class<?> cls, String name, int type){
    StringBuilder result = new StringBuilder();
    InputStream in = ClassLoader.getSystemResourceAsStream(cls, name);
    try{
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
        String buffer = "";
        while((buffer = bufferedReader.readLine()) != null)
            result.append(buffer + "\n");
        bufferedReader.close();
    }catch (IOException e1){
        e1.printStackTrace();
    }

and you call loadShader(com.myGame.shaders.Shader.class, "vertex.shader", GL_VERTEX_SHADER). The thing is, you need to use a class in the same package as the files.

Hope it helps

Judison
  • 46
  • 3