尝试绘制三角形时 LWJGL 输出闪烁

LWJGL Flickering Output When Attempting to Draw Triangle

我一直在尝试使用 LWJGL 进入 OpenGL,但我 运行 遇到了一个我找不到解决方案的问题。当尝试使用下面的代码绘制三角形时,window 正确打开并开始闪烁一个不一定是预期三角形的形状(有时它会短暂出现,但通常在其中一个象限中有矩形window).

我犹豫的部分原因在于,通过阅读各种在线帖子和文档,OpenGL 如何在最近的记忆中发生变化,以使用功能较少且更面向对象的方法(VBO 和 GLSL?)与 GL4。我的理解是否正确?学习 LWJGL 的新 OpenGL 的首选资源是什么?

提前致谢!

import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;

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

public class Main {
  private long windowID;

  private float[] tri = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f};

  public static void main(String[] args) {
    new Main().run();
  }

  public void run() { // Useful for making an instance class as opposed to a static main class?
    init();
    loop();

    glfwFreeCallbacks(windowID);
    glfwDestroyWindow(windowID);

    glfwTerminate();
    glfwSetErrorCallback(null).free();
  }

  public void init() { // Initializes all LWJGL components
    GLFWErrorCallback.createPrint(System.err).set(); // Create error callback route for GL

    if (!glfwInit()) { // Init GLFW
      throw new IllegalStateException("Failed to initialize GLFW!");
    } else {
      System.out.println("GLFW successfully initialized!");
    }

    windowID = glfwCreateWindow(640, 480, "Creating Window", NULL, NULL);

    if (windowID == NULL) { // Verify window creation
      throw new IllegalStateException("Failed to create window!");
    } else {
      System.out.println("Successfully created window!");
    }

    glfwDefaultWindowHints(); // Set window Proporties
    glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
    glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

    glfwSetKeyCallback(windowID, (window, key, scancode, action, mods) -> { // Key callback for closing the window
      if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
        glfwSetWindowShouldClose(window, true);
    });

    try (MemoryStack stack = stackPush()) { // Center the window
      IntBuffer pWidth = stack.mallocInt(1);
      IntBuffer pHeight = stack.mallocInt(1);

      glfwGetWindowSize(windowID, pWidth, pHeight);

      GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

      glfwSetWindowPos( // Center the window
          windowID, 
          (vidmode.width() - pWidth.get(0)) / 2,
          (vidmode.height() - pHeight.get(0)) / 2
          );
    }

    glfwMakeContextCurrent(windowID); // Make the window current
    glfwSwapInterval(0); // Sets the min num of pushed frames before buffers are swaped (Likely prevents horizontal tearing)
    glfwShowWindow(windowID); // Unhides the window
  }

  private void loop() {
    GL.createCapabilities();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // The color to clear the buffers with

    while(!glfwWindowShouldClose(windowID)) { // If the window is allowed to live
      glClear(GL_COLOR_BUFFER_BIT); // The OR is nessesary for some reason

      FloatBuffer vBuff = BufferUtils.createFloatBuffer(6);
      vBuff.put(tri);
      glEnableClientState(GL_VERTEX_ARRAY);
      glVertexPointer(2, GL_FLOAT, 0, vBuff);
      glDrawArrays(GL_TRIANGLES, 0, 6);
      glDisableClientState(GL_VERTEX_ARRAY);

      glfwSwapBuffers(windowID);
      glfwPollEvents();
    } 
  }
}

您在创建并填充缓冲区后错过了 vBuff.flip()

vBuff.put(tri) 将数据传输到缓冲区,从当前位置开始(在本例中是缓冲区的开头)。缓冲区位置按数据大小递增。所以新的缓冲区位置在新数据的末尾。

flip() 将缓冲区的限制(长度)设置为当前位置,然后将位置设置为零。

另外,在循环中没有必要不断地创建和填充缓冲区,在循环之前做一次就足够了:

FloatBuffer vBuff = BufferUtils.createFloatBuffer(6);
vBuff.put(tri);
vBuff.flip();

while(!glfwWindowShouldClose(windowID)) {
    glClear(GL_COLOR_BUFFER_BIT);

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, vBuff);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    glDisableClientState(GL_VERTEX_ARRAY);

    glfwSwapBuffers(windowID);
    glfwPollEvents();
}