The following LWJGL code is expected to render a blueish square in the center of the screen. Instead, I get a blank white screen. It’s like the rendering is not working at all, or that I am rendering outside of the screen.
I’m a complete noob in OpenGL and LWJGL, so I’m out of my depth. I went through everything but can’t seem to find anything that might be wrong with the code.
OpenGLTest.scala
package com.summerbulb.lwjgl import game.graphics.VertexArray import game.input.KeyboardInput import org.lwjgl.glfw.GLFW._ import org.lwjgl.glfw.GLFWVidMode import org.lwjgl.opengl.GL import org.lwjgl.opengl.GL11._ import org.lwjgl.opengl.GL20._ import org.lwjgl.system.MemoryUtil.NULL import scala.collection.mutable class OpenGLTest() extends Runnable { val width: Int = 1280 val height: Int = 720 var isRunning = false var window: Long = 0L val vertices = Array[Float]( -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f ) val indices = Array[Byte]( 0, 1, 2, 2, 3, 0 ) val textureCoordinates = Array[Float]( 0, 1, 0, 0, 1, 0, 1, 1 ) val vertShader = "#version 400 coren" + "n" + "layout (location = 0) in vec4 position;n" + "layout (location = 1) in vec2 tc;n" + "n" + // "uniform mat4 pr_matrix;n" + "n" + "void main()n" + "{n" + " gl_Position = position;n" + "}" val fragShader = "#version 400 coren" + "n" + "layout (location = 0) out vec4 color;n" + "n" + "void main()n" + "{n" + " color = vec4(0.2, 0.3, 0.8, 1.0);n" + "}" lazy val background = new VertexArray(vertices, indices, textureCoordinates) lazy val shaderProgramId = createShaderProgram(vertShader, fragShader) val cache = mutable.Map[String, Int]() def getUniform(name: String) = { if (cache.contains(name)) cache(name) else { val location = glGetUniformLocation(shaderProgramId, name) if (location == -1) { System.err.println("Could not find uniform variable '" + name + "'!") } else { cache.put(name, location) } location } } def start() = { isRunning = true val thread = new Thread(this, "OpenGlTest") thread.start() } def init(): Unit = { if (!glfwInit()) { throw new Exception("Unable to initialize GLFW") } glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE) glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3) glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3) glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE) window = glfwCreateWindow(width, height, "OpenGlTest", NULL, NULL) if (window == null) { throw new Exception("Could not create window.") } val vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor()) glfwSetWindowPos(window, (GLFWVidMode.WIDTH - width) / 2, (GLFWVidMode.HEIGHT - height) / 2) glfwSetKeyCallback(window, new KeyboardInput()) glfwMakeContextCurrent(window) glfwShowWindow(window) GL.createCapabilities() glClearColor(1.0f, 1.0f, 1.0f, 1.0f) glEnable(GL_DEPTH_TEST | GL_DEPTH_BUFFER_BIT) println("OpenGL: " + glGetString(GL_VERSION)) } override def run(): Unit = { init() while (isRunning) { update() render() if (glfwWindowShouldClose(window)) isRunning = false } } def update(): Unit = { glfwPollEvents() // ESC closes the window if (KeyboardInput.keys(GLFW_KEY_ESCAPE)) { isRunning = false } } def render(): Unit = { glClear(GL_COLOR_BUFFER_BIT) glUseProgram(shaderProgramId) background.render() glUseProgram(0) glfwSwapBuffers(window) } def createShaderProgram(vert: String, frag: String): Int = { val program:Int = glCreateProgram() val vertID = glCreateShader(GL_VERTEX_SHADER) val fragID = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(vertID, vert) glShaderSource(fragID, frag) glCompileShader(vertID) if (glGetShaderi(vertID, GL_COMPILE_STATUS) != GL_TRUE) { val infoLog = glGetShaderInfoLog(vertID) throw new Exception("Failed to compile vertex shader.nDetails:n" + infoLog) } glCompileShader(fragID) if (glGetShaderi(fragID, GL_COMPILE_STATUS) != GL_TRUE) { val infoLog = glGetShaderInfoLog(fragID) throw new Exception("Failed to compile fragment shader.nDetails:n" + infoLog) } glAttachShader(program, vertID) glAttachShader(program, fragID) glLinkProgram(program) glValidateProgram(program) glDeleteShader(vertID) glDeleteShader(fragID) val error = glGetError() if (error != GL_NO_ERROR) { println(error) System.exit(200) } program } } object OpenGLTest { def main(args: Array[String]): Unit = { new OpenGLTest().start() } }
VertexArray.scala
package game.graphics import java.nio.{ByteBuffer, ByteOrder, FloatBuffer, IntBuffer} import org.lwjgl.opengl.GL11._ import org.lwjgl.opengl.GL15._ import org.lwjgl.opengl.GL20._ import org.lwjgl.opengl.GL30._ class VertexArray(vertices: Array[Float], indices: Array[Byte], textureCoordinates: Array[Float]) { val count = indices.length val vao = glGenVertexArrays() glBindVertexArray(vao) val vbo = glGenBuffers() glBindBuffer(GL_ARRAY_BUFFER, vbo) // val verticesBuffer = BufferUtils.createFloatBuffer(vertices.length) // verticesBuffer.put(vertices).flip() glBufferData(GL_ARRAY_BUFFER, createFloatBuffer(vertices) , GL_STATIC_DRAW) glVertexAttribPointer(Shader.VERTEX_ATTRIB, 3, GL_FLOAT, false, 0, 0) glEnableVertexAttribArray(Shader.VERTEX_ATTRIB) val tbo = glGenBuffers() glBindBuffer(GL_ARRAY_BUFFER, tbo) // val texCoordBuffer = BufferUtils.createFloatBuffer(textureCoordinates.length) // texCoordBuffer.put(textureCoordinates).flip() glBufferData(GL_ARRAY_BUFFER, createFloatBuffer(textureCoordinates), GL_STATIC_DRAW) glVertexAttribPointer(Shader.TCOORD_ATTRIB , 2, GL_FLOAT, false, 0, 0) glEnableVertexAttribArray(Shader.TCOORD_ATTRIB) val ibo = glGenBuffers() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo) // private val indicesBuffer: ByteBuffer = BufferUtils.createByteBuffer(indices.length) // indicesBuffer.put(indices).flip() glBufferData(GL_ELEMENT_ARRAY_BUFFER, createByteBuffer(indices), GL_STATIC_DRAW ) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glBindBuffer(GL_ARRAY_BUFFER, 0) glBindVertexArray(0) def bind() = { glBindVertexArray(vao) glEnableVertexAttribArray(Shader.VERTEX_ATTRIB) glEnableVertexAttribArray(Shader.TCOORD_ATTRIB) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo) } def unbind() = { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glBindVertexArray(0) } def draw() = { glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_BYTE, 0) } def render() = { bind() draw() } def createByteBuffer(array: Array[Byte]): ByteBuffer = { val result = ByteBuffer.allocateDirect(array.length).order(ByteOrder.nativeOrder) result.put(array).flip result } def createFloatBuffer(array: Array[Float]): FloatBuffer = { val result = ByteBuffer.allocateDirect(array.length << 2).order(ByteOrder.nativeOrder).asFloatBuffer result.put(array).flip result } def createIntBuffer(array: Array[Int]): IntBuffer = { val result = ByteBuffer.allocateDirect(array.length << 2).order(ByteOrder.nativeOrder).asIntBuffer result.put(array).flip result } }
Advertisement
Answer
The call of
glEnable(GL_DEPTH_TEST | GL_DEPTH_BUFFER_BIT)
will cause an INVALID_ENUM
error. The parameter to glEnable
has to be a single enumerator constant. The parameter is not a bit mask where, the values can be concatenated by |
.
glClearColor(1.0f, 1.0f, 1.0f, 1.0f) glEnable(GL_DEPTH_TEST)
If you want to clear the buffers, then you’ve to call glClear
. The parameter of glClear
is a bit mask that indicate the buffers to be cleared:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)