Skip to content

Instantly share code, notes, and snippets.

@nbilyk

nbilyk/Main2.kt Secret

Last active April 2, 2016 21:59
Show Gist options
  • Save nbilyk/32a2598ccf262c7a4e663e6aae0224a6 to your computer and use it in GitHub Desktop.
Save nbilyk/32a2598ccf262c7a4e663e6aae0224a6 to your computer and use it in GitHub Desktop.
import org.lwjgl.BufferUtils
import org.lwjgl.glfw.GLFW.*
import org.lwjgl.glfw.GLFWErrorCallback
import org.lwjgl.opengl.*
import org.lwjgl.opengl.GL11.*
import org.lwjgl.system.MemoryUtil.NULL
import java.io.File
import java.nio.FloatBuffer
import java.nio.ShortBuffer
class Main2 {
// We need to strongly reference callback instances.
private var errorCallback: GLFWErrorCallback? = null
// The window handle
private var window: Long = 0
// Quad variables
private var vaoId = 0
private var vboId = 0
private var vboiId = 0
private var verticesBuffer: FloatBuffer? = null
private var indicesBuffer: ShortBuffer? = null
fun run() {
try {
initGl()
initShader()
setupQuad()
loop()
dispose()
// Destroy window and window callbacks
glfwDestroyWindow(window)
} finally {
// Terminate GLFW and free the GLFWErrorCallback
glfwTerminate()
errorCallback!!.free()
}
}
private fun initGl() {
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
// Setup an error callback. The default implementation
// will print the error message in System.err.
errorCallback = GLFWErrorCallback.createPrint(System.err)
glfwSetErrorCallback(errorCallback)
// Initialize GLFW. Most GLFW functions will not work before doing this.
if (glfwInit() != GLFW_TRUE)
throw IllegalStateException("Unable to initialize GLFW")
// Configure our window
glfwDefaultWindowHints() // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE) // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE) // the window will be resizable
val WIDTH = 300
val HEIGHT = 300
// Create the window
window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL)
if (window == NULL)
throw RuntimeException("Failed to create the GLFW window")
// Get the resolution of the primary monitor
val vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor())
// Center our window
glfwSetWindowPos(
window,
(vidmode.width() - WIDTH) / 2,
(vidmode.height() - 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 GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities()
// And do this after glfwMakeContextCurrent(window)
GLUtil.setupDebugMessageCallback(System.err)
// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f)
println("Vendor: ${GL11.glGetString(GL11.GL_VENDOR)}")
}
private var _program: Int = -1
private fun initShader() {
val vertexShaderSrc = """
#version 100
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}"""
val fragmentShaderSrc = """
void main() {
gl_FragColor = vec4(0.0, 1.0, 0.0, 0.2);
}"""
_program = GL20.glCreateProgram()
compileShader(vertexShaderSrc, GL20.GL_VERTEX_SHADER)
compileShader(fragmentShaderSrc, GL20.GL_FRAGMENT_SHADER)
GL20.glLinkProgram(_program)
GL20.glUseProgram(_program)
}
private fun compileShader(shaderSrc: String, shaderType: Int): Int {
val shader = GL20.glCreateShader(shaderType)
GL20.glShaderSource(shader, shaderSrc)
GL20.glCompileShader(shader)
GL20.glAttachShader(_program, shader)
println("Shader info: " + GL20.glGetShaderInfoLog(shader))
return shader
}
fun setupQuad() {
// Sending data to OpenGL requires the usage of (flipped) byte buffers
indicesBuffer = BufferUtils.createShortBuffer(6 * 2)
verticesBuffer = BufferUtils.createFloatBuffer(indicesBuffer!!.capacity() * 3)
// Create a new Vertex Array Object in memory and select it (bind)
// A VAO can have up to 16 attributes (VBO's) assigned to it by default
vaoId = GL30.glGenVertexArrays()
GL30.glBindVertexArray(vaoId)
GL20.glEnableVertexAttribArray(0)
// Create a new Vertex Buffer Object in memory and select it (bind)
// A VBO is a collection of Vectors which in this case resemble the location of each vertex.
vboId = GL15.glGenBuffers()
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId)
// Put the VBO in the attributes list at index 0
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0)
// Create a new VBO for the indices and select it (bind)
vboiId = GL15.glGenBuffers()
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId)
GL11.glEnable(GL_BLEND)
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
// GL11.glColor4f(0.0f, 1.0f, 0.0f, 0.2f)
}
private fun loop() {
drawScene()
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while (glfwWindowShouldClose(window) == GLFW_FALSE) {
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents()
Thread.sleep(50)
}
}
private var highestI = -1
private fun drawScene() {
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) // clear the framebuffer
val n = 8
for (i in 0..n - 1) {
val p = i / n.toFloat()
val offsetX = p * 2f - 1f
val s = Math.sin((p * 3f).toDouble()).toFloat()
val offsetY = s
// Vertices, the order is not important.
val vertices = floatArrayOf(-0.5f + offsetX, 0.5f + offsetY, 0f, // Left top ID: 0
-0.5f + offsetX, -0.5f + offsetY, 0f, // Left bottom ID: 1
0.5f + offsetX, -0.5f + offsetY, 0f, // Right bottom ID: 2
0.5f + offsetX, 0.5f + offsetY, 0f // Right left ID: 3
)
// OpenGL expects to draw vertices in counter clockwise order by default
var h = (highestI + 1)
highestI += 4
val indices = intArrayOf(// Left bottom triangle
h + 0, h + 1, h + 2, // Right top triangle
h + 2, h + 3, h + 0)
draw(vertices, indices)
}
flush()
glfwSwapBuffers(window) // swap the color buffers
}
private fun draw(vertices: FloatArray, indices: IntArray) {
verticesBuffer!!.put(vertices)
for (indice in indices) {
indicesBuffer!!.put(indice.toShort())
}
if (verticesBuffer!!.position() + vertices.size > verticesBuffer!!.limit() - vertices.size) flush()
}
private fun flush() {
val indicesL = indicesBuffer!!.position()
println("indicesL ${indicesL}")
if (indicesL == 0) return
verticesBuffer!!.flip()
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW)
verticesBuffer!!.clear()
indicesBuffer!!.flip()
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer!!, GL15.GL_STATIC_DRAW)
indicesBuffer!!.clear()
highestI = -1
// Draw the vertices
GL11.glDrawElements(GL11.GL_TRIANGLES, indicesL, GL11.GL_UNSIGNED_SHORT, 0)
}
private fun dispose() {
// Disable the VBO index from the VAO attributes list
GL20.glDisableVertexAttribArray(0)
// Delete the vertex VBO
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0)
GL15.glDeleteBuffers(vboId)
// Delete the index VBO
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0)
GL15.glDeleteBuffers(vboiId)
// Delete the VAO
GL30.glBindVertexArray(0)
GL30.glDeleteVertexArrays(vaoId)
}
}
fun main(args: Array<String>) {
val file = File("native")
if (!file.exists()) throw RuntimeException("native folder does not exist")
System.setProperty("org.lwjgl.librarypath", file.absolutePath)
Main2().run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment