【问题标题】:LWJGL Flickering Output When Attempting to Draw Triangle尝试绘制三角形时 LWJGL 闪烁输出
【发布时间】:2018-08-22 19:08:54
【问题描述】:

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

我犹豫不决的部分原因在于,通过阅读各种在线帖子和文档,OpenGL 如何在最近的记忆中发生了变化,以使用 GL4 的功能更少而更多面向对象的方法(VBO 和 GLSL?)。我的理解是否正确?学习 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()flip() 将缓冲区的限制(长度)设置为当前位置,然后将位置设置为零 - 请参阅ByteBuffer in LWJGL。没有必要在循环中连续创建和填充缓冲区,在循环之前执行一次就足够了。
  • 谢谢你的回复,你说的很对,加了flip现在就完美了,谢谢。关于我的缓冲区创建错位的好点。

标签: java opengl rendering lwjgl


【解决方案1】:

在创建并填充缓冲区后,您错过了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();
}

【讨论】:

    猜你喜欢
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2014-12-10
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多