Terry Darcy
Terry Darcy

Reputation: 1

I'm having trouble getting a model rendered to the window using open gl and glfw (LWJGL)

I'm working on getting familiar with the LWJGL library for java and I've been following a few tutorials online and I can't seem to get a model rendered.

im using OpenGL 2.1(this seems to be very outdated but Im not really sure about how to update that, I know its tied in with the hardware you have, I'm using a MacBook Pro 2017 model if anyone is interested in my specs)

if someone could take a look at my code and tell me what im doing wrong I would really appreciate it! (all that is being rendered right now is a red window)

from the sources I've studied this code should result in a square made up of two triangles coloured in a gradient using a vertex and a fragment shader but instead nothing is being rendered.

public class Main {

private long window;
    private int width = 1280, height = 720;

    public void run() {
    System.out.println("LWJGL " + Version.getVersion() + "!");

    init();
    loop();

    glfwFreeCallbacks(window);
    glfwDestroyWindow(window);

    glfwTerminate();
    glfwSetErrorCallback(null).free();
    }

    private void init() {
    GLFWErrorCallback.createPrint(System.err).set();

    if (!glfwInit()) throw new IllegalStateException("Unable to initialize GLFW");

    glfwDefaultWindowHints(); 
    glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); 
    glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); 

    window = glfwCreateWindow(width, height, "TESTING", NULL, NULL);
    if (window == NULL) throw new RuntimeException("Failed to create the GLFW window");

    glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
        if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) glfwSetWindowShouldClose(window, true); /
    });

    try (MemoryStack stack = stackPush()) {
        IntBuffer pWidth = stack.mallocInt(1); // int*
        IntBuffer pHeight = stack.mallocInt(1); // int*

        glfwGetWindowSize(window, pWidth, pHeight);

        GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

        glfwSetWindowPos(window, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2);
    }
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    glfwShowWindow(window);
    }

    private void loop() {
    GL.createCapabilities();

      GL11.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

    Renderer renderer = new Renderer();
    Loader loader = new Loader();
        StaticShader shader = new StaticShader();


    float[] vertices = {
            -0.5f, 0.5f, 0f,
            -0.5f, -0.5f, 0f,
            0.5f, -0.5f, 0f,
            0.5f, 0.5f, 0f,
          };

    int[] indicies = {
        0,1,3,
        3,1,2
    };

    RawModel model = loader.loadToVAO(vertices, indicies);

    while (!glfwWindowShouldClose(window)) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glfwSwapBuffers(window);

        renderer.prepare();
        shader.start();
        renderer.render(model);
        shader.stop();

        glfwPollEvents();
    }
     loader.cleanUp();
     shader.cleanUp();
    }

    public static void main(String[] args) {
    new Main().run();
    }

}

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;
    }

}

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);
            //System.out.println(model.getVertexCount());
            GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
            GL20.glDisableVertexAttribArray(0);
            GL30.glBindVertexArray(0);
        }
}

public class Loader {

    private List<Integer> vaos = new ArrayList<Integer>();
    private List<Integer> vbos = new ArrayList<Integer>();

    public RawModel loadToVAO(float[] positions,int[] indicies) {
        int vaoID = createVAO();
        bindIndecesBuffer(indicies); 
        storeDataInAttributeList(0, positions);
        unbindVAO();
        return new RawModel(vaoID, indicies.length);
    }

    private void bindIndecesBuffer(int[] indices) {
        int vboID = GL15.glGenBuffers();
        vbos.add(vboID);
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboID);
        IntBuffer buffer = storeDatainIntBuffer(indices);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
    }

    private IntBuffer storeDatainIntBuffer(int[] data) {
        IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
        buffer.put(data);
        buffer.flip();
        return buffer;
    }

    public void cleanUp() {
        for (int vao : vaos) {
            GL30.glDeleteVertexArrays(vao);
        }
        for (int vbo : vbos) {
            GL15.glDeleteBuffers(vbo);
        }
    }


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

    private FloatBuffer storeDataInFloatBuffer(float[] data) {
        FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
        buffer.put(data);
        buffer.flip();
        return buffer;
    }

}

public abstract class ShaderProgram {

    private int programID;
    private int vertexShaderID;
    private int fragmentShaderID;

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

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

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

    public void cleanUp(){
        stop();
        GL20.glDetachShader(programID, vertexShaderID);
        GL20.glDetachShader(programID, fragmentShaderID);
        GL20.glDeleteShader(vertexShaderID);
        GL20.glDeleteShader(fragmentShaderID);
        GL20.glDeleteProgram(programID);
    }

    protected abstract void bindAttributes();

    protected void bindAttribute(int attribute, String variableName){
        GL20.glBindAttribLocation(programID, attribute, variableName);
    }

    private static int loadShader(String file, int type){
        StringBuilder shaderSource = new StringBuilder();
        try{
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String line;
            while((line = reader.readLine())!=null){
                shaderSource.append(line).append("//\n");
            }
            reader.close();
        }catch(IOException e){
            e.printStackTrace();
            System.exit(-1);
        }
        int shaderID = GL20.glCreateShader(type);
        GL20.glShaderSource(shaderID, shaderSource);
        GL20.glCompileShader(shaderID);
        if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS )== GL11.GL_FALSE){
            System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
            System.err.println("Could not compile shader!");
            System.exit(-1);
        }
        return shaderID;
    }

}

public class StaticShader extends ShaderProgram {

    private static final String VERTEX_FILE = "src/shaderEngine/vertexShader.txt";
    private static final String FRAGMENT_FILE = "src/shaderEngine/fragmentShader.txt";

    public StaticShader() {
        super(VERTEX_FILE, FRAGMENT_FILE);
    }

    @Override
    protected void bindAttributes() {
        super.bindAttribute(0, "position");
    }

}

//VERTEX SHADER

#version 120

attribute vec3 position;

varying vec3 colour;

void main(void){

    gl_Position = vec4(position,1.0);
    colour = vec3(position.x+0.5,0.0,position.y+0.5);
}

//FRAGMENT SHADER

#version 120

varying vec3 colour;

void main(void){

    gl_FragColor = vec4(colour,1.0);

}

Upvotes: 0

Views: 111

Answers (1)

derhass
derhass

Reputation: 45342

Your code uses Vertex Array Objects (VAOs) for rendering. As the GL30 syntax of lwjgl already suggests, this is an OpenGL 3.0 feature. Running this code with a GL 2.1 context will only work if your implementation happens to implement the GL_ARB_vertex_array_object OpenGL extension.

im using OpenGL 2.1(this seems to be very outdated but Im not really sure about how to update that, I know its tied in with the hardware you have, I'm using a MacBook Pro 2017 model if anyone is interested in my specs)

YOu are limited to OpenGL 2.1 because you are using a legacy GL context. If you want somewhat modern OpenGL on OSX, you have to request a GL 3.2 core profile context at context creation. Also be warned that the most recent GL version that Apple is going to support is GL 4.1, and Apple actually declared OpenGL as deprecated and might remove it completely from future versions of OSX.

Upvotes: 1

Related Questions