Search code examples
openglshaderlwjgl

Does LWJGL3 and OpenGL need a shader to render?


My code does not work. I think there is a way to render something on the screen without shaders but how? I heard something about modern OpenGL rendering and how OpenGL needs shaders to render. Help me.

This is my code:

import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
import static org.lwjgl.glfw.GLFW.glfwTerminate;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL30;
import org.lwjgl.system.MemoryUtil;

public class Main {

     public static long window;
     public static boolean running = true;

     public static void createWindow() { 
        GLFW.glfwInit();

        GLFW.glfwDefaultWindowHints();
        GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GL30.GL_FALSE);
        GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GL30.GL_TRUE);

        window = GLFW.glfwCreateWindow(600, 600, "RenderQuad", 0, 0);

        GLFW.glfwMakeContextCurrent(window);

        GLFWVidMode vidmode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());

        GLFW.glfwSetWindowPos(window, (vidmode.width() - 600) / 2, (vidmode.height() - 600) / 2);

        GLFW.glfwShowWindow(window);

        GL.createCapabilities();

        GL30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    }

    public static int vaoID;
    public static int vboID;

    public static void render() {
        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
        };

        vaoID = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vaoID);

        FloatBuffer buffer = MemoryUtil.memAllocFloat(vertices.length);
        buffer.put(vertices);
        buffer.flip();

        vboID = GL30.glGenBuffers();
        GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, vboID);
        GL30.glBufferData(GL30.GL_ARRAY_BUFFER, buffer, GL30.GL_STATIC_DRAW);
        MemoryUtil.memFree(buffer);

        GL30.glVertexAttribPointer(0, 3, GL30.GL_FLOAT, false, 0, 0);

        GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, 0);

        GL30.glBindVertexArray(0);
    }

    public static void loopCycle() {
        GL30.glClear(GL30.GL_COLOR_BUFFER_BIT);

        GL30.glEnableVertexAttribArray(0);

        GL30.glBindVertexArray(vaoID);
        GL30.glDrawArrays(GL30.GL_TRIANGLES, 0, 6);

        GL30.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray(0);
    }

    public static void clean() {
        GL30.glDisableVertexAttribArray(0);

        GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, 0);
        GL30.glBindVertexArray(0);

        GL30.glDeleteBuffers(vboID);
        GL30.glDeleteVertexArrays(vaoID);


        glfwDestroyWindow(window);
        glfwTerminate();
    }

    public static void loop() {
        GLFW.glfwSwapBuffers(window);
        GLFW.glfwPollEvents();
        //GL30.glClear(GL30.GL_COLOR_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT);
    }

    public static void main(String[] args) {
        createWindow();
        render();

        while(running) {
            if(GLFW.glfwWindowShouldClose(window)) {running = false; break;}
            loopCycle();
            loop();
        }   
        clean();
    }
}

Solution

  • You do not have the array for vertex attribute 0 enabled when you draw. The array enable state for each vertex attribute is part of the VAO, and when you call glEnableVertexAttribArray it will affect the currently bound VAO.

    I have no idea where this comes from, but a lot of people (and seemingly also tutorials) use a scheme like:

    Setup() {
      glGenVertexArrays(1, &vao);
      glBindVertexArray(vao);
      // ... [set up some VBOs and maybe EBO]
      glVertexAttribPointer(...);
      glBindVertexArray(vao);
    }
    
    Draw()
    {
      glBindVertexArray(vao);
      glEnableVertexAttribArray(...); 
      glDraw...(...);
      glDisableVertexAttribArray(...); 
      glBindVertexArray(0);
    }
    

    Now this scheme in principle works, you just mistakenly enable the array while VAO 0 is still bound, and then switch to vao for which no array is enabled at all.

    But this scheme is utterly inefficient, the VAO does store this information for a reason: so that you not have to re-specify it each time you want to use it. As a result, the glEnableVertexAttribArray() belongs into the Setup function, and should only be called again if the actual set of vertex attributes for that particular VAO changes (which is never in those examples).

    I heard something about modern OpenGL rendering and how OpenGL needs shaders to render.

    Yes. Note that shaders were introduced to OpenGL with Version 2.0 in 2004, so that's quite a a strecht of the term modern when it comes to GPU development. You really should consider switching to a 3.2 core profile context, where all the legacy deprecated stuff leftover from the 90s is removed.