Triangle in OpenGL doesn't render

45 Views Asked by At

I'm using LWJGL 3, My Triangle Does Not Render. Here's my code:

package com.xicreations.infinimob;

import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.MemoryStack;

import java.nio.IntBuffer;

import static org.lwjgl.glfw.GLFW.*;
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.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.NULL;

public class Infinimob 
{
    private final int WIDTH = 800, HEIGHT = 800;
    private final String TITLE = "Infinimob 0.0.1a";
    
    private static String vs = "#version 330 core\n" + 
    "layout (location = 0) in vec3 aPos;\n" + 
    "void main()\n" +
    "{\n" + 
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" + 
    "}\0";
    
    private static String fs = "#version 330 core\n" + 
            "out vec4 fragColor;\n" + 
            "void main()\n" +
            "{\n" + 
            "   fragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n" + 
            "}\0";
    
    private long window;
    private int vao, vbo;
    private int vertexCount = 3;
    
    private void init()
    {
        if (!glfwInit()) 
        {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

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

        window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
        if (window == NULL) 
        {
            throw new RuntimeException("Failed to create the GLFW window");
        }

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

            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 int loadShader(String shaderSource, int shaderType) 
    {
        int shader = glCreateShader(shaderType);
        glShaderSource(shader, shaderSource);
        glCompileShader(shader);
        if (glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) {
            throw new RuntimeException("Failed to compile shader: " + glGetShaderInfoLog(shader));
        }
        return shader;
    }

    private void initShaders() 
    {
        int vertexShader = loadShader(vs, GL_VERTEX_SHADER);
        int fragmentShader = loadShader(fs, GL_FRAGMENT_SHADER);

        int shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, fragmentShader);
        glAttachShader(shaderProgram, vertexShader);
        glLinkProgram(shaderProgram);
        if (glGetProgrami(shaderProgram, GL_LINK_STATUS) == GL_FALSE) {
            throw new RuntimeException("Failed to link shader program: " + glGetProgramInfoLog(shaderProgram));
        }
        glUseProgram(shaderProgram);
    }
    
    private void loop() 
    {
        GL.createCapabilities();
        initShaders();

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

        vao = glGenVertexArrays();
        vbo = glGenBuffers();

        glBindVertexArray(vao);

        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * Float.BYTES, 0);
        glEnableVertexAttribArray(0);

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

        glViewport(0, 0, WIDTH, HEIGHT);
        
        while (!glfwWindowShouldClose(window)) 
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            
            glUseProgram(0);
            glBindVertexArray(vao);
            glDrawArrays(GL_TRIANGLES, 0, vertexCount);
            glBindVertexArray(0);

            glfwSwapBuffers(window);

            glfwPollEvents();
        }
    }

    private void cleanup() 
    {
        glDeleteBuffers(vbo);
        glDeleteVertexArrays(vao);
        glfwTerminate();
    }
    
    public static void main(String[] args) 
    {
        Infinimob app = new Infinimob();
        app.init();
        app.loop();
        app.cleanup();
    }
}

I think it should work, but it doesn't.

More information:

I'm using OpenGL 3.3, What's weirder, if i make the vertex shader and fragment shader exactly same, and remove the check for Linking errors, The triangle renders as white. I am probably going to rewrite the entire code if nothing works.

1

There are 1 best solutions below

0
Farhad Reza On

Here in this code-

while (!glfwWindowShouldClose(window)) 
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            
    glUseProgram(0);
    glBindVertexArray(vao);

You are not supposed to pass '0' to glUseProgram. It's going to unbind the shader program you created and binded in your initShaders function. You should pass your shader program's handle/id returned by glCreateProgram.

However, in your initShaders function, you are not storing the handle/id value in a member variable of the class. So what you can do is simply remove the 'glUseProgram(0);' line since the program is already binded and it should work, even though I haven't tested the code.

More ideal solution would be declaring 'int shaderProgram' as a member variable instead of local-

private void initShaders() 
{
    int vertexShader = loadShader(vs, GL_VERTEX_SHADER);
    int fragmentShader = loadShader(fs, GL_FRAGMENT_SHADER);

    shaderProgram = glCreateProgram();
...

and then pass it to glUseProgram before drawing your triangle-

while (!glfwWindowShouldClose(window)) 
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            
    glUseProgram(shaderProgram);
    glBindVertexArray(vao);