gpt4 book ai didi

java - 使用 glDrawArrays 绘图工作正常,但使用 glDrawElements 则失败

转载 作者:行者123 更新时间:2023-12-01 11:26:48 25 4
gpt4 key购买 nike

我的着色器工作正常,我可以使用 glDrawArrays 进行绘制,但我很难让 glDrawElements 工作。我在 lwjgl 函数调用与标准 openGL 不同的地方添加了注释。代码:

import org.lwjgl.Sys
import org.lwjgl.glfw._
import org.lwjgl.opengl._
import java.nio.ByteBuffer
import java.nio.FloatBuffer
import org.lwjgl.glfw.Callbacks._
import org.lwjgl.glfw.GLFW._
import org.lwjgl.opengl.GL11._
import org.lwjgl.opengl.GL15._
import org.lwjgl.opengl.GL20._
import org.lwjgl.opengl.GL30._
import org.lwjgl.system.MemoryUtil._
import org.lwjgl.BufferUtils._
import hands._
import javafx.scene.shape.CullFace


class Test {

val vertex_positions: Array[Float] = Array(
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f
)

val vertex_indices: Array[Int] = Array(
0, 1, 2
)

// We need to strongly reference callback instances.
val errorCallback: GLFWErrorCallback = Callbacks.errorCallbackPrint();
val keyCallback: GLFWKeyCallback = new GLFWKeyCallback() {
@Override
def invoke(window: Long , key: Int, scancode: Int , action: Int , mods: Int) {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, GL_TRUE) // We will detect this in our rendering loop
}
}

val WIDTH = 800
val HEIGHT = 600

def run(): Unit = {
System.out.println("Hello LWJGL " + Sys.getVersion() + "!")

try {

val vertBuffer = hands.createFlippedBuffer(vertex_positions)
val indexBuffer = hands.createFlippedBuffer(vertex_indices)

// Setup an error callback. The default implementation
// will print the error message in System.err.
glfwSetErrorCallback(errorCallback)

// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( glfwInit() != GL_TRUE )
throw new IllegalStateException("Unable to initialize GLFW")

// Configure our window
glfwDefaultWindowHints() // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GL_FALSE) // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE) // the window will be resizable
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)

// Create the window
val window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL)
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window")

// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, keyCallback)

// Get the resolution of the primary monitor
val vidmode: ByteBuffer = glfwGetVideoMode(glfwGetPrimaryMonitor())
// Center our window
glfwSetWindowPos(
window,
(GLFWvidmode.width(vidmode) - WIDTH) / 2,
(GLFWvidmode.height(vidmode) - HEIGHT) / 2)

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

// Make the window visible
glfwShowWindow(window)

// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the ContextCapabilities instance and makes the OpenGL
// bindings available for use.
GLContext.createFromCurrent()

//create shader, and use it as program
val shader = new Shader()
glUseProgram(shader.program)

val vao = glGenVertexArrays()
glBindVertexArray(vao)

val vbo = glGenBuffers()
glBindBuffer(GL_ARRAY_BUFFER, vbo)
//http://javadoc.lwjgl.org/org/lwjgl/opengl/GL15.html#glBufferData%28int,%20java.nio.FloatBuffer,%20int%29
glBufferData(GL_ARRAY_BUFFER, vertBuffer, GL_STATIC_DRAW)

//this function accepts false instead of GL_FALSE
glVertexAttribPointer(0, 3, GL_FLOAT, false , 0, 0)
glEnableVertexAttribArray(0)

val ebo = glGenBuffers()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
//http://javadoc.lwjgl.org/org/lwjgl/opengl/GL15.html#glBufferData%28int,%20java.nio.ShortBuffer,%20int%29
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW)


// Set the clear color
glClearColor(0, 0, 0.4f, 1)
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
//glfwWindowShouldClose produces a GL_FALSE, instead of a boolean value
while ( glfwWindowShouldClose(window) == GL_FALSE ) {

glClear(GL_COLOR_BUFFER_BIT) // clear the framebuffer

glBindVertexArray(vao)
glEnableVertexAttribArray(0)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)

//http://javadoc.lwjgl.org/org/lwjgl/opengl/GL11.html#glDrawElements%28int,%20java.nio.ShortBuffer%29
glDrawElements(GL_TRIANGLES, indexBuffer)
//glDrawArrays(GL_TRIANGLES, 0, 9)

glfwSwapBuffers(window); // swap the color buffers

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

// Release window and window callbacks
glfwDestroyWindow(window)
keyCallback.release()
} finally {
// Terminate GLFW and release the GLFWerrorfun
glfwTerminate()
errorCallback.release()
}
}

}

object main{

def main( args: Array[String] ) = {
new Test().run();
}
}

最佳答案

glDrawElements() 有两种变体最后一个参数的定义和使用方式有很大不同:

  1. 以“数据”作为参数。参数的确切类型取决于语言绑定(bind),但它通常类似于 C/C++ 中的指针、Java 中的缓冲区等。

  2. 一个接受整数偏移量作为参数。

如果缓冲区当前绑定(bind)到 GL_ELEMENT_ARRAY_BUFFER,则使用选项 2 。作为最后一个参数给出的整数是相对于绑定(bind)缓冲区开头的偏移量(以字节为单位)。

如果没有缓冲区绑定(bind)到 GL_ELEMENT_ARRAY_BUFFER,则使用选项 1 。在本例中,最后一个参数直接指定索引数据。

您的代码中的问题是您将两者混合在一起。您有缓冲区限制,因此需要使用选项 2。但是您正在使用选项 1。在您的情况下,正确的调用是:

glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0)

请注意,计数(第二个参数)以顶点为单位给出,而偏移(最后一个参数)以字节为单位给出。由于您使用的是整个缓冲区,并且偏移量为 0,因此这里没有什么区别。但这是常见的错误来源。

在 C/C++ 等弱类型语言中,实际上只有一个 glDrawElements()调用,选项 2 的偏移量被转换为指针。这也是如果您错误地使用选项 1 的调用(而不是 OpenGL 错误)会导致崩溃的原因。根据记录 C/C++ 绑定(bind)的规范,只有一次调用,因此在这种情况下不存在调用“错误”入口点的情况。它们只是更强类型语言中的不同入口点。

关于java - 使用 glDrawArrays 绘图工作正常,但使用 glDrawElements 则失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30756964/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com