我的着色器工作正常,我可以使用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();
}
}
答案 0 :(得分:0)
glDrawElements()
有两种变体在定义和使用最后一个参数方面有很大不同:
一个人需要"数据"作为论点。参数的确切类型取决于语言绑定,但它通常类似于C / C ++中的指针,Java中的缓冲区等。
将一个整数偏移作为参数。
如果缓冲区当前绑定到GL_ELEMENT_ARRAY_BUFFER
,则使用选项2。作为最后一个参数给出的整数是相对于绑定缓冲区起始的偏移量(以字节为单位)。
如果没有缓冲区绑定到GL_ELEMENT_ARRAY_BUFFER
,则使用选项1。在这种情况下,最后一个参数直接指定索引数据。
您的代码中的问题是您要将两者混合在一起。您有一个缓冲区绑定,因此您需要使用选项2.但是您使用选项1.您的案例中的正确调用将是:
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0)
请注意, count (第二个参数)以顶点为单位给出,而 offset (最后一个参数)以字节为单位给出。由于您正在使用整个缓冲区,并且偏移量为0,因此这里没有任何区别。但它经常出错。
在像C / C ++这样的弱类型语言中,实际上只有一个glDrawElements()
调用,并且选项2的偏移量被强制转换为指针。如果您错误地使用选项1中的调用而不是OpenGL错误,这也是导致崩溃的原因。根据规范C / C ++绑定的规范,只有一个调用,所以没有调用"错误"在这种情况下的切入点。它们只是更强类型语言的不同入口点。