Search code examples
javaopengllwjgl

GLFW3 Hello Triangle


I'm stuck trying to figure out why this code is wrong. Its suposed to show a square on the screen. With GL_FRONT_AND_BACK to GL_LINE i see a single line. With GL_FRONT_AND_BACK to GL_FILL a get nothing.

Fragment shader:

#version 330 core

out vec4 oColor;

void main() {
   oColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

Vertex Shader:

#version 330 core

layout (location = 0) in vec3 iPosition;

void main() {
    gl_Position = vec4(iPosition, 1.0);
}

All this code is basicaly copied from the learn opengl site https://learnopengl.com/Getting-started/Hello-Triangle

import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.system.MemoryUtil;

import java.nio.file.Files;
import java.nio.file.Paths;

import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.glfw.GLFW.*;

public class HelloTriangle {

    public static void main(String[] args) {
        if (!glfwInit()) {
            System.out.println("GLFW failed to initialize");
            System.exit(9);
        }

        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

        final var window = glfwCreateWindow(800, 600, "LearnOpenGL", MemoryUtil.NULL, MemoryUtil.NULL);
        if (window == 0) {
            System.out.println("GLFW failed to create window");
            glfwTerminate();
            System.exit(9);
        }

        {
            glfwMakeContextCurrent(window);
            GL.createCapabilities();
            glfwSetFramebufferSizeCallback(window, (long w, int width, int height) -> GL11.glViewport(0,0, width, height));
        }

        final var program = glCreateProgram();
        {
            final var vertex = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(vertex, getResourceAsString("basic.vert"));
            glCompileShader(vertex);
            if(glGetShaderi(vertex, GL_COMPILE_STATUS) != GL_TRUE) {
                System.out.printf("Failed to compile VERTEX Shader: %s%n", glGetShaderInfoLog(vertex, Integer.MAX_VALUE));
                GL.destroy();
                glfwTerminate();
                System.exit(9);
            }
            glAttachShader(program, vertex);

            final var fragment = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(fragment, getResourceAsString("basic.frag"));
            glCompileShader(fragment);
            if(glGetShaderi(vertex, GL_COMPILE_STATUS) != GL_TRUE) {
                System.out.printf("Failed to compile FRAGMENT Shader: %s%n", glGetShaderInfoLog(vertex, Integer.MAX_VALUE));
                GL.destroy();
                glfwTerminate();
                System.exit(9);
            }
            glAttachShader(program, fragment);

            glLinkProgram(program);
            glDeleteShader(vertex);
            glDeleteShader(fragment);
        }

        final var VAO = glGenVertexArrays();
        final var VBO = glGenBuffers();
        final var EBO = glGenBuffers();
        {
            glBindVertexArray(VAO);
            float[] vertices = {
                    0.5f,  0.5f, 0.0f,  // top right
                    0.5f, -0.5f, 0.0f,  // bottom right
                    -0.5f, -0.5f, 0.0f,  // bottom left
                    -0.5f,  0.5f, 0.0f   // top left
            };

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

            int[] indices = {  // note that we start from 0!
                    0, 1, 3,  // first Triangle
                    1, 2, 3   // second Triangle
            };

            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW);

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

            glBindBuffer(GL_ARRAY_BUFFER, 0);
        }

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

        glfwShowWindow(window);
        while (!glfwWindowShouldClose(window))
        {
            // input
            // -----
            if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
                glfwSetWindowShouldClose(window, true);

            // render
            // ------
            glClear(GL_COLOR_BUFFER_BIT);

            // draw our first triangle
            glUseProgram(program);
            glBindVertexArray(VAO);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

            // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
            // -------------------------------------------------------------------------------
            glfwSwapBuffers(window);
            glfwPollEvents();
        }

        // optional: de-allocate all resources once they've outlived their purpose:
        // ------------------------------------------------------------------------
        glDeleteVertexArrays(VAO);
        glDeleteBuffers(VBO);
        glDeleteBuffers(EBO);
        glDeleteProgram(program);

        // glfw: terminate, clearing all previously allocated GLFW resources.
        // ------------------------------------------------------------------
        GL.destroy();
        glfwTerminate();
    }

    private static String getResourceAsString(String name) {
        try {
            final var resource = Thread.currentThread().getContextClassLoader().getResource(name);
            if (resource == null) return null;

            final var path = Paths.get(resource.toURI());
            return Files.readString(path);
        } catch (Exception ex) {
            return null;
        }
    }

}

Solution

  • The SIZE constant represents the size in bits, but not in bytes. However, the stride argument of glVertexAttribPointer specifies the byte offset between consecutive generic vertex attributes

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

    glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * Float.SIZE / 8, 0);
    

    or

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