1
\$\begingroup\$

I'm new to OpenGL and trying to render multiple triangles using single VBO in using LWJGL3. I've followed demos and read some books and wrote following code, but its not drawing my shape. I use vertex and fragment shader.

It prints following log and not drawing anything.

0(6) : warning C7533: global variable gl_FragColor is deprecated after version 120

Fragment info
-------------
0(6) : warning C7533: global variable gl_FragColor is deprecated after version 120

[LWJGL] OpenGL debug message
    ID: 0x20071
    Source: API
    Type: OTHER
    Severity: NOTIFICATION
    Message: Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.

enter image description here

Here's the source code of runnable class:

package mn.digz.lwjgl;

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.system.MemoryUtil.NULL;

import java.io.IOException;
import java.nio.FloatBuffer;
import mn.astvision.assetmanagement.lib.lwjgl.util.ShaderUtil;

import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.opengl.GLUtil;
import org.lwjgl.system.Callback;

/**
 *
 * @author MethoD
 */
public class OpenGLGraphRender {

    long window;
    int width = 1024;
    int height = 768;

    int vao;
    int program;

    int viewProjMatrixUniform;

    Matrix4f viewProjMatrix = new Matrix4f();
    FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);

    FloatBuffer verticesBuffer;
    int vertexPositionAttribute;
    int vertexColorAttribute;
    int pointSize = 3 + 4; // x,y,z + r,g,b,a
    int step = Float.SIZE / 8; // byte per element
    int stride = step * pointSize; // need?

    GLFWErrorCallback errCallback;
    Callback debugProc;

    void init() {
        glfwSetErrorCallback(errCallback = GLFWErrorCallback.createPrint(System.err));

        if (!glfwInit())
            throw new IllegalStateException("Unable to initialize GLFW");

        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

        window = glfwCreateWindow(width, height, "Silhouette rendering with geometry shader", NULL, NULL);
        if (window == NULL) {
            throw new AssertionError("Failed to create the GLFW window");
        }

        GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        glfwSetWindowPos(window, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2);
        glfwMakeContextCurrent(window);
        glfwSwapInterval(1); // enable v sync
        glfwShowWindow(window);
    }

    void createProgram() throws IOException {
        int program = glCreateProgram();
        int vshader = ShaderUtil.createShader("mn/astvision/assetmanagement/lib/lwjgl/shader/vs.glsl", GL_VERTEX_SHADER);
        int fshader = ShaderUtil.createShader("mn/astvision/assetmanagement/lib/lwjgl/shader/fs.glsl", GL_FRAGMENT_SHADER);
        glAttachShader(program, vshader);
        glAttachShader(program, fshader);

        glLinkProgram(program);
        int linked = glGetProgrami(program, GL_LINK_STATUS);
        String programLog = glGetProgramInfoLog(program);
        if (programLog != null && programLog.trim().length() > 0) {
            System.err.println(programLog);
        }
        if (linked == 0) {
            throw new AssertionError("Could not link program");
        }
        this.program = program;
    }

    /**
     * Initialize the shader program.
     */
    void initProgram() {
        glUseProgram(this.program);
        viewProjMatrixUniform = glGetUniformLocation(this.program, "viewProjMatrix");

        glBindAttribLocation(program, 0, "vertexPosition");
        glBindAttribLocation(program, 0, "vertexColor");
        vertexPositionAttribute = glGetAttribLocation(program, "vertexPosition");
        vertexColorAttribute = glGetAttribLocation(program, "vertexColor");

        verticesBuffer = BufferUtils.createFloatBuffer(pointSize * 3 * 3); // point size * 3 points * 3 triangles = 21 floats per triangle
        verticesBuffer.put(new float[] {0f, 0f, 0f, 1f, 1f, 0f, 1f, 2f, 0f, 0f, 1f, 1f, 0f, 1f, 1f, 1.7f, 0f, 1f, 1f, 0f, 1f});
        verticesBuffer.put(new float[] {4f, 4f, 0f, 1f, 1f, 0f, 1f, 6f, 4f, 0f, 1f, 1f, 0f, 1f, 5f, 5.7f, 0f, 1f, 1f, 0f, 1f});
        verticesBuffer.put(new float[] {4f, 1f, 0f, 1f, 1f, 0f, 1f, 6f, 1f, 0f, 1f, 1f, 0f, 1f, 5f, 2.7f, 0f, 1f, 1f, 0f, 1f});
        verticesBuffer.flip();

        int vbo = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);

        glVertexAttribPointer(vertexPositionAttribute, 3, GL_FLOAT, false, stride, 0);
        glVertexAttribPointer(vertexColorAttribute, 4, GL_FLOAT, false, stride, step * 3);
        glEnableVertexAttribArray(vertexPositionAttribute);
        glEnableVertexAttribArray(vertexColorAttribute);

        glUseProgram(0);
    }

    void render() {
        viewProjMatrix
            .setPerspective((float) Math.toRadians(30), (float) width / height, 0.01f, 50.0f)
            .lookAt(0.0f, 2.0f, 7.0f,
                    0.0f, 0.0f, 0.0f,
                    0.0f, 1.0f, 0.0f);

        glUseProgram(this.program);
        glUniformMatrix4fv(viewProjMatrixUniform, false, viewProjMatrix.get(matrixBuffer));

        int numItems = 3;
        glDrawArrays(GL_TRIANGLES, 0, numItems);

        glUseProgram(0);
    }

    void loop() throws IOException {
        GL.createCapabilities();

        debugProc = GLUtil.setupDebugMessageCallback();

        glClearColor(0.55f, 0.75f, 0.95f, 1.0f);
        glEnable(GL_DEPTH_TEST);

        /* Create all needed GL resources */
        createProgram();
        initProgram();

        while (!glfwWindowShouldClose(window)) {
            glfwPollEvents();
            glViewport(0, 0, width, height);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            render();

            glfwSwapBuffers(window);
        }
    }

    void run() {
        try {
            init();
            loop();

            if (debugProc != null)
                debugProc.free();
            errCallback.free();
            glfwDestroyWindow(window);
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            glfwTerminate();
        }
    }
}

Here's the ShaderUtil.java

package mn.digz.lwjgl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import org.lwjgl.BufferUtils;
import org.lwjgl.PointerBuffer;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.system.MemoryUtil.memUTF8;

/**
 *
 * @author MethoD
 */
public class ShaderUtil {

    /**
     * Create a shader object from the given classpath resource.
     *
     * @param resource the class path
     * @param type the shader type
     *
     * @return the shader object id
     *
     * @throws IOException
     */
    public static int createShader(String resource, int type) throws IOException {
        return createShader(resource, type, null);
    }

    /**
     * Create a shader object from the given classpath resource.
     *
     * @param resource the class path
     * @param type the shader type
     * @param version the GLSL version to prepend to the shader source, or null
     *
     * @return the shader object id
     *
     * @throws IOException
     */
    public static int createShader(String resource, int type, String version) throws IOException {
        int shader = glCreateShader(type);

        ByteBuffer source = ioResourceToByteBuffer(resource, 8192);

        if (version == null) {
            PointerBuffer strings = BufferUtils.createPointerBuffer(1);
            IntBuffer lengths = BufferUtils.createIntBuffer(1);

            strings.put(0, source);
            lengths.put(0, source.remaining());

            glShaderSource(shader, strings, lengths);
        } else {
            PointerBuffer strings = BufferUtils.createPointerBuffer(2);
            IntBuffer lengths = BufferUtils.createIntBuffer(2);

            ByteBuffer preamble = memUTF8("#version " + version + "\n", false);

            strings.put(0, preamble);
            lengths.put(0, preamble.remaining());

            strings.put(1, source);
            lengths.put(1, source.remaining());

            glShaderSource(shader, strings, lengths);
        }

        glCompileShader(shader);
        int compiled = glGetShaderi(shader, GL_COMPILE_STATUS);
        String shaderLog = glGetShaderInfoLog(shader);
        if (shaderLog != null && shaderLog.trim().length() > 0) {
            System.err.println(shaderLog);
        }
        if (compiled == 0) {
            throw new AssertionError("Could not compile shader");
        }
        return shader;
    }

    /**
     * Reads the specified resource and returns the raw data as a ByteBuffer.
     *
     * @param resource the resource to read
     * @param bufferSize the initial buffer size
     *
     * @return the resource data
     *
     * @throws IOException if an IO error occurs
     */
    public static ByteBuffer ioResourceToByteBuffer(String resource, int bufferSize) throws IOException {
        ByteBuffer buffer;
        URL url = Thread.currentThread().getContextClassLoader().getResource(resource);
        File file = new File(url.getFile());
        if (file.isFile()) {
            FileInputStream fis = new FileInputStream(file);
            FileChannel fc = fis.getChannel();
            buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
            fc.close();
            fis.close();
        } else {
            buffer = BufferUtils.createByteBuffer(bufferSize);
            InputStream source = url.openStream();
            if (source == null) {
                throw new FileNotFoundException(resource);
            }
            try {
                ReadableByteChannel rbc = Channels.newChannel(source);
                try {
                    while (true) {
                        int bytes = rbc.read(buffer);
                        if (bytes == -1) {
                            break;
                        }
                        if (buffer.remaining() == 0) {
                            buffer = resizeBuffer(buffer, buffer.capacity() * 2);
                        }
                    }
                    buffer.flip();
                } finally {
                    rbc.close();
                }
            } finally {
                source.close();
            }
        }
        return buffer;
    }

    private static ByteBuffer resizeBuffer(ByteBuffer buffer, int newCapacity) {
        ByteBuffer newBuffer = BufferUtils.createByteBuffer(newCapacity);
        buffer.flip();
        newBuffer.put(buffer);
        return newBuffer;
    }
}

Here's my vertex shader:

#version 150

uniform mat4 viewMatrix;
uniform mat4 projMatrix;

//in vec3 position;
in vec3 vertexPosition;
in vec4 vertexColor;

out vec4 vColor;

void main(void) {
  gl_Position = projMatrix * viewMatrix * vec4(vertexPosition, 1.0);
  vColor = vertexColor;
}

Here's my fragment shader:

#version 150

in vec4 vColor;

void main(void) {
  gl_FragColor = vColor;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Please show the debugging steps you've taken so far, including any error messages or information about the state of the application at the time of the crash. You should also take the time to pare down the code to the minimal amount that reproduces the issue (what we call a minimal, complete, verifiable example). The less of your code someone has to wade through, the faster they can spot the problem and the more likely you are to get good answers quickly. \$\endgroup\$ – DMGregory Jul 5 '17 at 3:32
  • \$\begingroup\$ Thanks for suggestion. I removed some key event and window resize callbacks and added error info. \$\endgroup\$ – digz6666 Jul 5 '17 at 3:55
  • \$\begingroup\$ @DMGregory I should have called flip() on the buffer. After call flip() its not crashing but its not drawing anything, so there's something else. \$\endgroup\$ – digz6666 Jul 5 '17 at 9:03
1
\$\begingroup\$

There are multiple issues with the code you posted.

You're trying to use a uniform named viewProjMatrix:

viewProjMatrixUniform = glGetUniformLocation(this.program, "viewProjMatrix");

But that uniform doesn't exist in your shader. In the shader you have two matrices:

uniform mat4 viewMatrix;
uniform mat4 projMatrix;

You bind both vertex attributes to the same index (0):

glBindAttribLocation(program, 0, "vertexPosition");
glBindAttribLocation(program, 0, "vertexColor");

While this isn't illegal, it's not what you mean to be doing. Set vertexColor to 1 instead. Or get rid of those two lines and use the default locations given to them.

Strangely you then try and get get the attribute locations. You know the values, you just (incorrectly) set them both to 0.

vertexPositionAttribute = glGetAttribLocation(program, "vertexPosition");
vertexColorAttribute = glGetAttribLocation(program, "vertexColor");

You are also calling glDrawArrays with 3 as the count. A single triangle has 3 indices. You're trying to draw 3 triangles. That's 9 indices.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your detailed answer, fixed the problems and its drawn :) \$\endgroup\$ – digz6666 Jul 6 '17 at 1:42
1
\$\begingroup\$

You use a perspective matrix with a near plane of 0.01 and a far plane of 50. This means that only stuff, that has a Z coordinate between these two values can be rendered. Because all your triangles have a Z coordinate of 0, they'll get culled.

\$\endgroup\$
  • \$\begingroup\$ I've changed z coordinates to 1.0f and its still not drawn :) \$\endgroup\$ – digz6666 Jul 5 '17 at 11:32
1
\$\begingroup\$

I'd also like to remind you that the code you copy-pasted is under copyright and you just declared your own @author tag on it. At least give credit to the original authors, which is also mentioned in the file you copied.

Your shader utils is a 1:1 verbatim copy of the class DemoUtils in the LWJGL3 Demos repository: https://github.com/LWJGL/lwjgl3-demos/blob/master/src/org/lwjgl/demo/opengl/util/DemoUtils.java#L118-L226

License information (as also mentioned in the source file) can be found here: https://www.lwjgl.org/license

\$\endgroup\$
  • \$\begingroup\$ Ah yes, just created with Netbeans and copy pasted it. \$\endgroup\$ – digz6666 Jul 7 '17 at 3:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.