[Solved] [newb] Nothing renders in the window

Started by pilif0, July 05, 2016, 21:39:48

Previous topic - Next topic

pilif0

I am trying to learn how to use LWJGL3 and I just got to a state where I want to render something (a test quad for now). I have a class that represents a mesh where I set up the VAO with vertex, colour and element buffers and another object later takes the mesh instance, retrieves its VAO ID and attempts to render it.

The problem I have is that no matter what I try, nothing renders in the window. I can change the background colour through the glClearColor() method but the quad never shows up. I also tried to run some of the demos and they ran fine, so the problem is in this project. But I can't find it.

The VAO set up:
vertexCount = indices.length;

vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

//Vertices
FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(positions.length);
verticesBuffer.put(positions).flip();

vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * 4, 0);

//Colours
FloatBuffer colorsBuffer = BufferUtils.createFloatBuffer(colors.length);
colorsBuffer.put(colors).flip();

colVboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, colVboID);
glBufferData(GL_ARRAY_BUFFER, colorsBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 3 * 4, 0);

//Indices
IntBuffer indicesBuffer = BufferUtils.createIntBuffer(indices.length);
indicesBuffer.put(indices).flip();

idxVboID = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idxVboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);

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


The rendering code:
//Bind the shader
shaderProgram.bind();

//Bind the VAO
glBindVertexArray(mesh.getVaoID());

//Draw
glDrawElements(GL_TRIANGLES, mesh.getVertexCount(), GL_UNSIGNED_INT, 0);

//Restore
glBindVertexArray(0);
shaderProgram.unbind();


Vertex shader:
#version 330

layout (location=0) in vec3 pos;
layout (location=1) in vec3 inColor;

out vec3 exColor;

void main()
{
    gl_Position = vec4(pos, 1.0);
    exColor = inColor;
}


Fragment shader:
#version 330

in vec3 exColor;
out vec4 fragColor;


void main()
{
    fragColor = vec4(exColor, 1.0);
}


Test data being fed into it:
/** The vertices */
float[] vertices = new float[]{
    -0.5f,  0.5f, 0.0f,
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.5f,  0.5f, 0.0f
};
/** The indices */
int[] indices = new int[]{0, 1, 3, 3, 1, 2};
/** The colours */
float[] colors = new float[]{
    1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    1.0f, 1.0f, 1.0f
};


Could you please tell me what I'm doing wrong? If you need any other parts of code, I'll be happy to provide them.

quew8

Nothing immediately jumps out but have you called glGetError()? Should always be calling it in the render loop when you're debugging.

pilif0

Quote from: quew8 on July 08, 2016, 10:52:41
Nothing immediately jumps out but have you called glGetError()? Should always be calling it in the render loop when you're debugging.

I added a the error check as suggested, but it didn't trigger.

This is the check I wrote:
int error = glGetError();
if(error != GL_NO_ERROR){
    Log.log(Log.Severity.ERROR, "OpenGL", "OpenGL error: " + error);
}


It is second-last part of the main loop (the last is delta time calculation). The Log class is my custom logger that formats the message and writes it to both System.out and a file.

Kai

The shown code in your first post works for me. I added a little scaffolding to load the shader and to setup a GLFW window and I see the quad.
Your vertex colors are all white, though. Did you probably set the clearColor to all 1.0f and don't see the quad because of this? :)

Self-contained LWJGL3 program I used:
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.MemoryUtil.NULL;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLUtil;
import org.lwjgl.system.Callback;
 
public class ShaderTest {
    private long window;
    private int program;
    private int vertexCount, vaoID, vboID, idxVboID, colVboID;
    private GLFWKeyCallback keyCallback;
    private Callback debugProc;
 
    private void init() {
        if (!glfwInit())
            throw new IllegalStateException("Unable to initialize GLFW");
        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
        window = glfwCreateWindow(800, 600, "", NULL, NULL);
        if (window == NULL) {
            throw new AssertionError("Failed to create the GLFW window");
        }
        glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
            @Override
            public void invoke(long window, int key, int scancode, int action, int mods) {
                if (action != GLFW_RELEASE)
                    return;
 
                if (key == GLFW_KEY_ESCAPE) {
                    glfwSetWindowShouldClose(window, true);
                }
            }
        });
        glfwMakeContextCurrent(window);
        glfwShowWindow(window);
        GL.createCapabilities();
        debugProc = GLUtil.setupDebugMessageCallback();
 
        createProgram();
        createVbo();
    }
    private void createVbo() {
        // See: http://forum.lwjgl.org/index.php?topic=6271.msg33478#msg33478
        /** The vertices */
        float[] positions = new float[]{
            -0.5f,  0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f,
             0.5f, -0.5f, 0.0f,
             0.5f,  0.5f, 0.0f
        };
        /** The indices */
        int[] indices = new int[]{0, 1, 3, 3, 1, 2};
        /** The colours */
        float[] colors = new float[]{
            0.0f, 1.0f, 1.0f,
            1.0f, 0.0f, 1.0f,
            1.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 1.0f
        };
 
        vertexCount = indices.length;
        vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
 
        //Vertices
        FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(positions.length);
        verticesBuffer.put(positions).flip();
 
        vboID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * 4, 0);
 
        //Colours
        FloatBuffer colorsBuffer = BufferUtils.createFloatBuffer(colors.length);
        colorsBuffer.put(colors).flip();
 
        colVboID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, colVboID);
        glBufferData(GL_ARRAY_BUFFER, colorsBuffer, GL_STATIC_DRAW);
        glVertexAttribPointer(1, 3, GL_FLOAT, false, 3 * 4, 0);
 
        //Indices
        IntBuffer indicesBuffer = BufferUtils.createIntBuffer(indices.length);
        indicesBuffer.put(indices).flip();
 
        idxVboID = glGenBuffers();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idxVboID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
 
        //Unbind
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
    }
    private static int createShader(String source, int type) {
        int shader = glCreateShader(type);
        glShaderSource(shader, source);
        glCompileShader(shader);
        int compiled = glGetShaderi(shader, GL_COMPILE_STATUS);
        String shaderLog = glGetShaderInfoLog(shader);
        if (shaderLog.trim().length() > 0)
            System.err.println(shaderLog);
        if (compiled == 0)
            throw new AssertionError("Could not compile shader");
        return shader;
    }
    private void createProgram() {
        int program = glCreateProgram();
        int vshader = createShader(
"#version 330\n" +
"layout (location=0) in vec3 pos;" +
"layout (location=1) in vec3 inColor;" +
"out vec3 exColor;" +
"void main()" +
"{" +
"    gl_Position = vec4(pos, 1.0);" +
"    exColor = inColor;" +
"}"
, GL_VERTEX_SHADER);
        int fshader = createShader(
"#version 330\n" +
"in vec3 exColor;" +
"out vec4 fragColor;" +
"void main()" +
"{" +
"    fragColor = vec4(exColor, 1.0);" +
"}"
,GL_FRAGMENT_SHADER);
        glAttachShader(program, vshader);
        glAttachShader(program, fshader);
        glLinkProgram(program);
        int linked = glGetProgrami(program, GL_LINK_STATUS);
        String programLog = glGetProgramInfoLog(program);
        if (programLog.trim().length() > 0)
            System.err.println(programLog);
        if (linked == 0)
            throw new AssertionError("Could not link program");
        this.program = program;
        glUseProgram(program);
        glUseProgram(0);
    }
    private void render() {
        glClear(GL_COLOR_BUFFER_BIT);
        // See: http://forum.lwjgl.org/index.php?topic=6271.msg33478#msg33478
        glUseProgram(program);
        glBindVertexArray(vaoID);
        glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);
        glUseProgram(0);
    }
    private void loop() {
        while (!glfwWindowShouldClose(window)) {
            glfwPollEvents();
            render();
            glfwSwapBuffers(window);
        }
    }
    private void run() {
        try {
            init();
            loop();
            if (debugProc != null) {
                debugProc.free();
            }
            keyCallback.free();
            glfwDestroyWindow(window);
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            glfwTerminate();
        }
    }
    public static void main(String[] args) {
        new ShaderTest().run();
    }
}

pilif0

I ran your program Kai and it worked. That showed me that the problem must be somewhere else in the code and I believe that I have found it now. After about an hour of comparing your code to my project I noticed a different order of function calls. In the main loop, I called the buffer swap at the start, you at the end. And right after that I noticed something that made me red wit emberrassment. I was clearing the color and depth buffer right before it. I was clearing the buffer right before showing it the whole time.  :-[

Lesson learned: don't just copy from a book, think thoroughly about what you're doing

I moved the buffer swap to the end of the loop right before the delta time calculation and it's now showing a nice white quad. I want to thank you both for your help with this. If I manage to bring this project to successfull completion, it will be a small game and you are both guaranteed a copy. If you want to take a look at the rest of the code, it is up on https://github.com/pilif0/Runner. I will clean up the code and commit the rendering there withing the next two days.