Question

I'm trying to draw a fairly simple scene: A white quad (made out of two triangles) with corners (-0.5, -0.5), (0.5, -0.5), (-0.5, 0.5) and (0.5, 0.5) on a pink background. But somehow the quad doesn't end up on the screen.

I'm running the code with the lwjgl-debug.jar and lwjgl in debug mode but not a single error is reported back. I'm probalbly missing something small but I am unable to find it.

Here's the code:

GridShaderTest.java

import java.io.File;
import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;

public class GridShaderTest {
    private static final int WIDTH = 1024;
    private static final int HEIGHT = Math.round(WIDTH/16f*9);

    private int meshBufferID;
    private int vaoID;

    public GridShaderTest() {
        try {
            Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
            Display.create();
            Display.setTitle("Beneath the Surface");
            GL11.glClearColor(0.8f, 0f, 0.8f, 1f);
            GL11.glViewport(0, 0, WIDTH, HEIGHT);
        } catch(LWJGLException e) {
            e.printStackTrace();
            System.exit(1);
        }

        final Shader shader = new Shader(new File("target/classes/shaders/tileshader"), new String[] {"pos", "inColor"}, new String[] {});

        createMeshBuffer();
        createVAO(shader);

        while(!Display.isCloseRequested()) {
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);

            shader.use();

            GL30.glBindVertexArray(vaoID);
            shader.enableVAttributes();

            GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 2);

            shader.disableVAttributes();
            GL30.glBindVertexArray(0);

            GL20.glUseProgram(0);

            Display.sync(60);
            Display.update();
        }

        Display.destroy();
    }

    private void createMeshBuffer() {
        // Layout: x,y,r,g,b
        meshBufferID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, meshBufferID);
        final FloatBuffer meshBuffer = BufferUtils.createFloatBuffer(30);

        meshBuffer
            .put(-0.5f).put(-0.5f)  .put(1f).put(1f).put(1f)
            .put(0.5f).put(-0.5f)   .put(1f).put(1f).put(1f)
            .put(-0.5f).put(0.5f)   .put(1f).put(1f).put(1f)

            .put(-0.5f).put(0.5f)   .put(1f).put(1f).put(1f)
            .put(0.5f).put(-0.5f)   .put(1f).put(1f).put(1f)
            .put(0.5f).put(0.5f)    .put(1f).put(1f).put(1f);

        meshBuffer.flip();
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, meshBuffer, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }

    private void createVAO(Shader shader) {
        vaoID = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vaoID);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, meshBufferID);
        GL20.glVertexAttribPointer(shader.getAttribLocation("pos"), 2, GL11.GL_FLOAT, false, 20, 0);
        GL20.glVertexAttribPointer(shader.getAttribLocation("inColor"), 3, GL11.GL_FLOAT, false, 20, 8);

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

    public static void main(String[] args) {
        new GridShaderTest();
    }
}

tileshader/vert.glsl

#version 150 core

in vec2 pos;
in vec3 inColor;
out vec3 passColor;

void main() {
    gl_Position = vec4(pos, 0.0f, 1.0f);
    passColor = inColor;
}

tileshader/frag.glsl

#version 150 core
in vec3 passColor;
out vec4 fragColor;

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

I'm pretty sure the Shader class is correct but for completeness here it is:

import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_VALIDATE_STATUS;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.OpenGLException;

public class Shader {
    public final int id;
    public final Map<String, Integer> attribLocations, uniformLocations;

    public Shader(File path, String[] attribNames, String[] uniformNames) {
        final int vsID = loadShader(new File(path, "vert.glsl"), GL20.GL_VERTEX_SHADER);
        final int fsID = loadShader(new File(path, "frag.glsl"), GL20.GL_FRAGMENT_SHADER);

        id = GL20.glCreateProgram();
        GL20.glAttachShader(id, vsID);
        GL20.glAttachShader(id, fsID);

        GL20.glLinkProgram(id);
        checkLinkage(id);

        GL20.glValidateProgram(id);
        checkValidation(id);

        GL20.glDetachShader(id, vsID);
        GL20.glDetachShader(id, fsID);

        GL20.glDeleteShader(vsID);
        GL20.glDeleteShader(fsID);

        attribLocations = new HashMap<>(attribNames.length+1, 1);
        for(String name: attribNames) {
            attribLocations.put(name, GL20.glGetAttribLocation(id, name));
        }

        uniformLocations = new HashMap<>(uniformNames.length+1, 1);
        for(String name: uniformNames) {
            uniformLocations.put(name, GL20.glGetUniformLocation(id, name));
        }
    }

    public void use() {
        GL20.glUseProgram(id);
    }

    public void unload() {
        GL20.glDeleteProgram(id);
    }

    public int getAttribLocation(String name) {
        return attribLocations.get(name);
    }

    public int getUniformLocation(String name) {
        return uniformLocations.get(name);
    }

    public void enableVAttributes() {
        for(String s: attribLocations.keySet()) {
            GL20.glEnableVertexAttribArray(attribLocations.get(s));
        }
    }

    public void disableVAttributes() {
        for(String s: attribLocations.keySet()) {
            GL20.glDisableVertexAttribArray(attribLocations.get(s));
        }
    }

    private static int loadShader(File file, int type) {
        final StringBuilder builder = new StringBuilder();

        try(BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while((line = reader.readLine()) != null) {
                builder.append(line).append("\n");
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(2);
        }

        final int shaderID = GL20.glCreateShader(type);
        GL20.glShaderSource(shaderID, builder);
        GL20.glCompileShader(shaderID);

        checkCompilation(shaderID);

        return shaderID;
    }

    private static void checkValidation(int programID) {
        int error = glGetProgrami(programID, GL_VALIDATE_STATUS);
        if(error == GL_FALSE) {
            throw new OpenGLException(glGetProgramInfoLog(programID, glGetProgrami(programID, GL_INFO_LOG_LENGTH)));
        }
    }

    private static void checkCompilation(int shaderID) {
        int error = glGetShaderi(shaderID, GL_COMPILE_STATUS);
        if(error == GL_FALSE) {
            throw new OpenGLException(glGetShaderInfoLog(shaderID, glGetShaderi(shaderID, GL_INFO_LOG_LENGTH)));
        }
    }

    private static void checkLinkage(int programID) {
        int error = glGetProgrami(programID, GL_LINK_STATUS);
        if(error == GL_FALSE) {
            throw new OpenGLException(glGetProgramInfoLog(programID, glGetProgrami(programID, GL_INFO_LOG_LENGTH)));
        }
    }
}
Was it helpful?

Solution

This line

GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 2);

renders nothing. You need to put the number or vertices (6 in your case) there, not the number of primitives.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top