简体   繁体   中英

LWJGL 3 Won't Draw A Line

I'm trying to draw a line with LWJGL 3. It compiles and all of the natives are set up correctly. I'm running on Ubuntu. I really don't see what the problem is; the window initializes and the background is the correct clear color, but the line won't draw. I copied the code almost exactly from the only example I could find on their new website. I have no idea what I'm doing wrong.

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;

import java.awt.DisplayMode;
import java.nio.ByteBuffer;

import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWvidmode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.Display;
import org.lwjgl.util.glu.GLU;

public class Main {
    // We need to strongly reference callback instances.
    private static GLFWErrorCallback errorCallback;
    private static GLFWKeyCallback   keyCallback;
    static final int INIT_WIDTH = 300;
    static final int INIT_HEIGHT = 300;

    // The window handle
    private static long window;

    public static boolean verbose = true;

    public static void init() {
        final String WINDOW_TITLE = "WINDOW";

        vPrint("Initializing GLFW...");
        if (glfwInit() != GL11.GL_TRUE) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }
        vPrint("Done!\n");

        //Window will be hidden after creation
        glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
        //Window will be resizable
        glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);

        vPrint("Creating window...");
        window = glfwCreateWindow(INIT_WIDTH, INIT_HEIGHT, WINDOW_TITLE, NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        } else {
            vPrint("Done!\n");
        }

        //Setup a key callback. It will be called every time a key is pressed, repeated or released.
        glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
            @Override
            public void invoke(long window, int key, int scancode, int action, int mods) {
                if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
                    glfwSetWindowShouldClose(window, GL_TRUE); // We will detect this in our rendering loop
            }
        });

        // Get the resolution of the primary monitor
        ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        // Center our window
        glfwSetWindowPos(
            window,
            (GLFWvidmode.width(vidmode) - INIT_WIDTH) / 2,
            (GLFWvidmode.height(vidmode) - INIT_HEIGHT) / 2
        );

        // Make the OpenGL context current
        glfwMakeContextCurrent(window);
        // Enable v-sync
        glfwSwapInterval(1);

        // Make the window visible
        glfwShowWindow(window);
        GLContext.createFromCurrent();

        //Set window clear color
        glClearColor(0.5f, 0.0f, 0.0f, 0.0f);

        initOpenGL();
    }

    public static void main(String[] args) {
        try {
            init();
            loop();

            glfwDestroyWindow(window);
            keyCallback.release();
        } finally {
            glfwTerminate();
            errorCallback.release();
        }
    }

    public static void loop() {
        // Run the rendering loop until the user has attempted to close
        // the window or has pressed the ESCAPE key.
        while ( glfwWindowShouldClose(window) == GL_FALSE ) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

            glfwSwapBuffers(window); // swap the color buffers
            render();

            // Poll for window events. The key callback above will only be
            // invoked during this call.
            glfwPollEvents();
        }
    }

    private static void vPrint(String str) {
        if (verbose) {
            System.out.print(str);
        }
    }

    private static void render() {
        glColor3f(1, 1, 1);
        glBegin(GL_LINE);
            glVertex2f(10, 10);
            glVertex2f(20, 20);
        glEnd();
    }

    private static void initOpenGL() {
         glViewport(0, 0, INIT_WIDTH, INIT_HEIGHT);
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();

         // Calculate The Aspect Ratio Of The Window
         GLU.gluPerspective(30.0f, (float)INIT_HEIGHT / (float)INIT_HEIGHT, 0.3f, 200.0f);

         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
    }
}

EDIT: I'm fairly sure now that it's an error with my use of GL_LINE ;

There are a number of issues here.

Draw Call

You have a popular but sometimes hard to spot error here:

glBegin(GL_LINE);

The enum for drawing lines is GL_LINES (note trailing S ). GL_LINE on the other hand is one of the possible arguments for glPolygonMode() . So this call should be:

glBegin(GL_LINES);

Order of Calls in Draw Loop

The order of calls in your rendering loop looks wrong:

while ( glfwWindowShouldClose(window) == GL_FALSE ) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glfwSwapBuffers(window);
    render();
    glfwPollEvents();
}

The glfwSwapBuffers() call specifies that you finished rendering, and are ready to present what you rendered. Since you're making that call before you call render() , what is presented is only the cleared buffer.

Or looking at it differently, if you step through the sequence of calls between the end of the loop and the start, and ignoring the glfwPollEvents() call, your render() call is followed immediately by glClear() . So the result of the rendering is cleared before it ever has a chance of being presented.

The correct sequence of calls is:

while ( glfwWindowShouldClose(window) == GL_FALSE ) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    render();
    glfwSwapBuffers(window);
    glfwPollEvents();
}

This will allow your rendering to be executed before the result is presented with the glfwSwapBuffers() call.

Range of Coordinates

You need to be careful about the transformations and coordinate ranges. When you set up just a perspective transformation, it will assume that your coordinates are between the near and far plane range looking from the origin down the negative z-axis. You will need a translation in the negative z-direction as part of your modelview matrix to get your coordinates inside the viewing volume. Otherwise the whole geometry will be clipped away.

For example, you can add a glTranslatef() call when you set up the modelview matrix, which will place your geometry between the near and far planes:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -50.0f);

You may want to look for a tutorial that explains the OpenGL coordinate systems and transformations if this explanation is not sufficient.

It's because your points are not on the screen :

glVertex2f(10, 10);
glVertex2f(20, 20);

In this case the coordinate system do from -1.0f to 1.0f in x and y the center of the screen is 0.0. By doing this you should see something :

glVertex2f(0.0f, 0.0f);
glVertex2f(1.0f, 1.0f);

But your code is good.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM