Renders a quad

This commit is contained in:
Jared Dunbar 2023-09-20 20:40:45 -04:00
parent 6ede022d4f
commit 6e8cfc7329
5 changed files with 269 additions and 3 deletions

View File

@ -7,7 +7,7 @@ import org.lwjgl.system.MemoryUtil.*
import kotlin.system.exitProcess import kotlin.system.exitProcess
fun main() { fun main() {
if (!glfwInit()) { /*if (!glfwInit()) {
exitProcess(1) exitProcess(1)
} }
@ -37,9 +37,12 @@ fun main() {
glDrawArrays(GL_TRIANGLES, 0, 3) glDrawArrays(GL_TRIANGLES, 0, 3)
glfwSwapBuffers(window) glfwSwapBuffers(window)
} }
glfwTerminate() glfwTerminate()*/
}
Render.run()
}
/*
private fun createWindow(): Long { private fun createWindow(): Long {
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE) glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE)
val window = glfwCreateWindow(800, 600, "Window Title", NULL, NULL) val window = glfwCreateWindow(800, 600, "Window Title", NULL, NULL)
@ -47,3 +50,4 @@ private fun createWindow(): Long {
createCapabilities() createCapabilities()
return window return window
} }
*/

View File

@ -0,0 +1,242 @@
package org.ja4.vaxel
import org.lwjgl.BufferUtils
import org.lwjgl.PointerBuffer
import org.lwjgl.glfw.GLFW.*
import org.lwjgl.glfw.GLFWKeyCallback
import org.lwjgl.opengl.GL
import org.lwjgl.opengl.GL20.*
import org.lwjgl.opengl.GL30.glBindVertexArray
import org.lwjgl.opengl.GL30.glGenVertexArrays
import org.lwjgl.opengl.GLUtil
import org.lwjgl.stb.STBImage.stbi_image_free
import org.lwjgl.stb.STBImage.stbi_load_from_memory
import org.lwjgl.system.Callback
import org.lwjgl.system.MemoryStack
import org.lwjgl.system.MemoryUtil.*
import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.IOException
import java.nio.ByteBuffer
import java.nio.IntBuffer
import java.nio.channels.FileChannel
object Render {
var width = 1024
var height = 768
var window: Long? = null
var program: Int? = null
var quadProgramInputPosition: Int? = null
var quadProgramInputTextureCoords: Int? = null
var vao: Int? = null
var debugProc: Callback? = null
var keyCallback: GLFWKeyCallback? = null
fun init() {
glfwInit()
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0)
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE)
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE)
window = glfwCreateWindow(width, height, "Simple quad", NULL, NULL)
keyCallback = object : GLFWKeyCallback() {
override fun invoke(window: Long, key: Int, scancode: Int, action: Int, mods: Int) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
glfwSetWindowShouldClose(window, true)
}
}
glfwSetKeyCallback(window!!, keyCallback)
glfwMakeContextCurrent(window!!)
glfwShowWindow(window!!)
MemoryStack.stackPush().use {frame ->
val framebufferSize = frame.mallocInt(2)
nglfwGetFramebufferSize(window!!, memAddress(framebufferSize), memAddress(framebufferSize) + 4)
width = framebufferSize.get(0)
height = framebufferSize.get(1)
}
val caps = GL.createCapabilities()
val debugProc = GLUtil.setupDebugMessageCallback()
createTexture()
createQuadProgram()
createFullScreenQuad()
}
fun resizeBuffer(buffer: ByteBuffer, newCapacity: Int): ByteBuffer {
val newBuffer = BufferUtils.createByteBuffer(newCapacity)
buffer.flip()
newBuffer.put(buffer)
return newBuffer
}
fun ioResourceToByteBuffer(resource: String, bufferSize: Int): ByteBuffer {
var buffer: ByteBuffer
val url = Thread.currentThread().contextClassLoader.getResource(resource)
?: throw IOException("Classpath resource not found: $resource")
val file = File(url.file)
if (file.isFile) {
val fis = FileInputStream(file)
val fc = fis.channel
buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size())
fc.close()
fis.close()
} else {
buffer = BufferUtils.createByteBuffer(bufferSize)
val source = url.openStream() ?: throw FileNotFoundException(resource)
source.use { source ->
val buf = ByteArray(8192)
while (true) {
val bytes = source.read(buf, 0, buf.size)
if (bytes == -1) {
break;
}
if (buffer.remaining() < bytes) {
buffer = resizeBuffer(buffer, Math.max(buffer.capacity() * 2, buffer.capacity() - buffer.remaining() + bytes))
}
buffer.put(buf, 0, bytes)
}
buffer.flip()
}
}
return buffer
}
fun createShader(resource: String, type: Int): Int {
return createShader(resource, type, null)
}
fun createShader(resource: String, type: Int, version: String?): Int {
val shader = glCreateShader(type)
val source = ioResourceToByteBuffer(resource, 8192)
val strings: PointerBuffer
val lengths: IntBuffer
if (version == null) {
strings = BufferUtils.createPointerBuffer(1)
lengths = BufferUtils.createIntBuffer(1)
strings.put(0, source)
lengths.put(0, source.remaining())
} else {
strings = BufferUtils.createPointerBuffer(2)
lengths = BufferUtils.createIntBuffer(2)
val preamble = memUTF8("#version $version\n", false)
strings.put(0, preamble)
lengths.put(0, preamble.remaining())
strings.put(1, source)
lengths.put(1, source.remaining())
}
glShaderSource(shader, strings, lengths)
glCompileShader(shader)
val compiled = glGetShaderi(shader, GL_COMPILE_STATUS)
val shaderLog = glGetShaderInfoLog(shader)
if (shaderLog.trim().isNotEmpty()) {
System.err.println(shaderLog)
}
if (compiled == 0) {
throw AssertionError("Could not compile shader")
}
return shader
}
fun createQuadProgram() {
program = glCreateProgram()
val vshader = createShader("texturedQuad.vs", GL_VERTEX_SHADER)
val fshader = createShader("texturedQuad.fs", GL_FRAGMENT_SHADER)
glAttachShader(program!!, vshader)
glAttachShader(program!!, fshader)
glLinkProgram(program!!)
val linked = glGetProgrami(program!!, GL_LINK_STATUS)
val programLog = glGetProgramInfoLog(program!!)
if (programLog.trim().isNotEmpty()) {
System.err.println(programLog)
}
if (linked == 0) {
throw AssertionError("Could not link program")
}
glUseProgram(program!!)
val texLocation = glGetUniformLocation(program!!, "tex")
glUniform1i(texLocation, 0)
quadProgramInputPosition = glGetAttribLocation(program!!, "position")
quadProgramInputTextureCoords = glGetAttribLocation(program!!, "texCoords")
glUseProgram(0)
}
fun createFullScreenQuad() {
vao = glGenVertexArrays()
glBindVertexArray(vao!!)
val positionVbo = glGenBuffers()
var fb = BufferUtils.createFloatBuffer(2 * 6)
fb.put(-1.0f).put(-1.0f)
fb.put(1.0f).put(-1.0f)
fb.put(1.0f).put(1.0f)
fb.put(1.0f).put(1.0f)
fb.put(-1.0f).put(1.0f)
fb.put(-1.0f).put(-1.0f)
fb.flip()
glBindBuffer(GL_ARRAY_BUFFER, positionVbo)
glBufferData(GL_ARRAY_BUFFER, fb, GL_STATIC_DRAW)
glVertexAttribPointer(quadProgramInputPosition!!, 2, GL_FLOAT, false, 0, 0L)
glEnableVertexAttribArray(quadProgramInputPosition!!)
val texCoordsVbo = glGenBuffers()
fb = BufferUtils.createFloatBuffer(2 * 6)
fb.put(0.0f).put(1.0f)
fb.put(1.0f).put(1.0f)
fb.put(1.0f).put(0.0f)
fb.put(1.0f).put(0.0f)
fb.put(0.0f).put(0.0f)
fb.put(0.0f).put(1.0f)
fb.flip()
glBindBuffer(GL_ARRAY_BUFFER, texCoordsVbo)
glBufferData(GL_ARRAY_BUFFER, fb, GL_STATIC_DRAW)
glVertexAttribPointer(quadProgramInputTextureCoords!!, 2, GL_FLOAT, true, 0, 0L)
glEnableVertexAttribArray(quadProgramInputTextureCoords!!)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
}
fun createTexture() {
val width = BufferUtils.createIntBuffer(1)
val height = BufferUtils.createIntBuffer(1)
val components = BufferUtils.createIntBuffer(1)
val data = stbi_load_from_memory(ioResourceToByteBuffer("environment.jpg", 1024), width, height, components, 4)?: throw AssertionError("Unable to load file")
val id = glGenTextures()
glBindTexture(GL_TEXTURE_2D, id)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width.get(), height.get(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
stbi_image_free(data)
}
fun render() {
glClear(GL_COLOR_BUFFER_BIT)
glUseProgram(program!!)
glBindVertexArray(vao!!)
glDrawArrays(GL_TRIANGLES, 0, 6)
glBindVertexArray(0)
glUseProgram(0)
}
fun loop() {
while (!glfwWindowShouldClose(window!!)) {
glfwPollEvents()
glViewport(0, 0, width, height)
render()
glfwSwapBuffers(window!!)
}
}
fun run() {
init()
loop()
if (debugProc != null) {
debugProc!!.free()
}
keyCallback!!.free()
glfwDestroyWindow(window!!)
glfwTerminate()
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

View File

@ -0,0 +1,10 @@
#version 130
uniform sampler2D tex;
in vec2 texCoordsVarying;
out vec4 color;
void main() {
color = texture(tex, texCoordsVarying);
}

View File

@ -0,0 +1,10 @@
#version 130
in vec3 position;
in vec2 texCoords;
out vec2 texCoordsVarying;
void main() {
texCoordsVarying = texCoords;
gl_Position = vec4(position, 1.0);
}