render simple letter on screen

This commit is contained in:
Bixilon 2021-02-08 23:16:10 +01:00
parent b418145f88
commit c706ee7d36
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 172 additions and 38 deletions

View File

@ -2,8 +2,12 @@ package de.bixilon.minosoft.gui.rendering
import de.bixilon.minosoft.data.entities.EntityRotation
import de.bixilon.minosoft.data.entities.Location
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.data.world.ChunkLocation
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.font.Font2DMesh
import de.bixilon.minosoft.gui.rendering.shader.Shader
import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureArray
import de.bixilon.minosoft.protocol.network.Connection
import de.bixilon.minosoft.protocol.packets.serverbound.play.PacketPlayerPositionAndRotationSending
@ -27,7 +31,9 @@ class RenderWindow(private val connection: Connection) {
private var screenHeight = 600
private var polygonEnabled = false
private lateinit var chunkShader: Shader
private lateinit var fontShader: Shader
private lateinit var minecraftTextures: TextureArray
private lateinit var fontAtlasTexture: TextureArray
private var windowId: Long = 0
private var deltaTime = 0.0 // time between current frame and last frame
@ -36,7 +42,8 @@ class RenderWindow(private val connection: Connection) {
val renderQueue = ConcurrentLinkedQueue<Runnable>()
val chunkSectionsToDraw = ConcurrentHashMap<ChunkLocation, ConcurrentHashMap<Int, Mesh>>()
val chunkSectionsToDraw = ConcurrentHashMap<ChunkLocation, ConcurrentHashMap<Int, WorldMesh>>()
val font2DToDraw = ConcurrentLinkedQueue<Font2DMesh>()
fun init(latch: CountUpAndDownLatch? = null) {
@ -110,17 +117,35 @@ class RenderWindow(private val connection: Connection) {
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
minecraftTextures = TextureArray(connection.version.assetsManager, connection.version.mapping.blockMap.values)
minecraftTextures = TextureArray(connection.version.assetsManager, resolveBlockTextureIds(connection.version.mapping.blockMap.values))
minecraftTextures.load()
fontAtlasTexture = TextureArray(connection.version.assetsManager, listOf(Texture("font/unicode_page_00", 0)), 256)
fontAtlasTexture.load()
chunkShader = Shader("chunk_vertex.glsl", "chunk_fragment.glsl")
chunkShader.load()
chunkShader.use()
chunkShader.setInt("texture0", 0)
camera.calculateProjectionMatrix(screenWidth, screenHeight, chunkShader)
camera.calculateViewMatrix(chunkShader)
fontShader = Shader("font_vertex.glsl", "font_fragment.glsl")
fontShader.load()
fontShader.use()
fontShader.setFloat("atlasSize", 256f)
val font = Font()
val char = font.chars['§']!!
font2DToDraw.add(Font2DMesh(floatArrayOf(
-0.5f, -0.5f, char.column * 16f, char.row * 16f + char.width, font.atlasOffset + char.atlasPage.toFloat(),
-0.5f, 0f, char.column * 16f, char.row * 16f, font.atlasOffset + char.atlasPage.toFloat(),
0f, -0.5f, char.column * 16f + char.width, char.row * 16f + char.width, font.atlasOffset + char.atlasPage.toFloat(),
0f, -0.5f, char.column * 16f + char.width, char.row * 16f + char.width, font.atlasOffset + char.atlasPage.toFloat(),
-0.5f, 0f, char.column * 16f, char.row * 16f, font.atlasOffset + char.atlasPage.toFloat(),
0f, 0f, char.column * 16f + char.width, char.row * 16f, font.atlasOffset + char.atlasPage.toFloat(),
)))
glfwSetWindowSizeCallback(windowId, object : GLFWWindowSizeCallback() {
override fun invoke(window: Long, width: Int, height: Int) {
glViewport(0, 0, width, height)
@ -148,6 +173,8 @@ class RenderWindow(private val connection: Connection) {
deltaTime = currentFrame - lastFrame
lastFrame = currentFrame
glEnable(GL_DEPTH_TEST)
minecraftTextures.use(GL_TEXTURE0)
chunkShader.use()
@ -160,6 +187,15 @@ class RenderWindow(private val connection: Connection) {
}
}
glDisable(GL_DEPTH_TEST)
fontAtlasTexture.use(GL_TEXTURE0)
fontShader.use()
for (font in font2DToDraw) {
font.draw()
}
glfwSwapBuffers(windowId)
glfwPollEvents()
@ -179,6 +215,7 @@ class RenderWindow(private val connection: Connection) {
if (glfwGetTime() - lastPositionChangeTime > 0.05) {
// ToDo: Replace this with proper movement and only send it, when out position changed
connection.sendPacket(PacketPlayerPositionAndRotationSending(Location(camera.cameraPosition), EntityRotation(camera.yaw, camera.pitch), false))
lastPositionChangeTime = glfwGetTime()
}
@ -207,4 +244,16 @@ class RenderWindow(private val connection: Connection) {
})
polygonEnabled = !polygonEnabled
}
private fun resolveBlockTextureIds(blocks: Set<Block>): List<Texture> {
val textures: MutableList<Texture> = mutableListOf()
textures.add(TextureArray.DEBUG_TEXTURE)
val textureMap: MutableMap<String, Texture> = mutableMapOf()
textureMap[TextureArray.DEBUG_TEXTURE.name] = TextureArray.DEBUG_TEXTURE
for (block in blocks) {
block.blockModel?.resolveTextures(textures, textureMap)
}
return textures
}
}

View File

@ -45,7 +45,7 @@ class Renderer(private val connection: Connection) {
renderWindow.renderQueue.add {
sectionMap[sectionHeight]?.unload()
sectionMap.remove(sectionHeight)
sectionMap[sectionHeight] = Mesh(data, Vec3(chunkLocation.x, sectionHeight, chunkLocation.z))
sectionMap[sectionHeight] = WorldMesh(data, Vec3(chunkLocation.x, sectionHeight, chunkLocation.z))
}
}
}

View File

@ -2,9 +2,6 @@ package de.bixilon.minosoft.gui.rendering;
import de.bixilon.minosoft.gui.rendering.shader.Shader;
import glm_.vec3.Vec3;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
import static org.lwjgl.opengl.GL11.glDrawArrays;
@ -12,13 +9,13 @@ import static org.lwjgl.opengl.GL15.glDeleteBuffers;
import static org.lwjgl.opengl.GL15.glGenBuffers;
import static org.lwjgl.opengl.GL30.*;
public class Mesh {
public class WorldMesh {
int vAO;
int vBO;
Vec3 worldPosition;
int trianglesCount;
public Mesh(float[] data, Vec3 worldPosition) {
public WorldMesh(float[] data, Vec3 worldPosition) {
this.worldPosition = worldPosition;
this.trianglesCount = data.length / 6; // <- bytes per vertex
this.vAO = glGenVertexArrays();
@ -26,17 +23,17 @@ public class Mesh {
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(this.vAO);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vBO);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, data, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 6 * Float.BYTES, 0L);
GL20.glEnableVertexAttribArray(0);
GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, 6 * Float.BYTES, 3 * Float.BYTES);
GL20.glEnableVertexAttribArray(1);
GL20.glVertexAttribPointer(2, 1, GL11.GL_FLOAT, false, 6 * Float.BYTES, 5 * Float.BYTES);
GL20.glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, this.vBO);
glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 6 * Float.BYTES, 0L);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 6 * Float.BYTES, 3 * Float.BYTES);
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 1, GL_FLOAT, false, 6 * Float.BYTES, 5 * Float.BYTES);
glEnableVertexAttribArray(2);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
public void draw(Shader chunkShader) {

View File

@ -0,0 +1,17 @@
package de.bixilon.minosoft.gui.rendering.font
class Font {
val chars: MutableMap<Char, FontChar> = mutableMapOf()
val atlasOffset = 0
init {
for (page in 0 until 256) {
for (x in 0 until 16) {
for (y in 0 until 16) {
chars[(page * 256 + (x * 16 + y)).toChar()] = FontChar(page, x, y)
}
}
}
}
}

View File

@ -0,0 +1,40 @@
package de.bixilon.minosoft.gui.rendering.font
import glm_.BYTES
import org.lwjgl.opengl.GL11.GL_FLOAT
import org.lwjgl.opengl.GL20.glEnableVertexAttribArray
import org.lwjgl.opengl.GL20.glVertexAttribPointer
import org.lwjgl.opengl.GL30.*
class Font2DMesh(data: FloatArray) {
var vAO: Int = glGenVertexArrays()
var vBO: Int = glGenBuffers()
var trianglesCount: Int = data.size / 5 // <- bytes per vertex
fun draw() {
glBindVertexArray(vAO)
glDrawArrays(GL_TRIANGLES, 0, trianglesCount)
}
fun unload() {
glDeleteVertexArrays(vAO)
glDeleteBuffers(vBO)
}
init {
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(vAO)
glBindBuffer(GL_ARRAY_BUFFER, vBO)
glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW)
glVertexAttribPointer(0, 2, GL_FLOAT, false, 5 * Float.BYTES, 0L)
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * Float.BYTES, (2 * Float.BYTES).toLong())
glEnableVertexAttribArray(1)
glVertexAttribPointer(2, 1, GL_FLOAT, false, 5 * Float.BYTES, (4 * Float.BYTES).toLong())
glEnableVertexAttribArray(2)
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0)
}
}

View File

@ -0,0 +1,6 @@
package de.bixilon.minosoft.gui.rendering.font
class FontChar(val atlasPage: Int, val row: Int, val column: Int) {
val width = 16
}

View File

@ -0,0 +1,8 @@
package de.bixilon.minosoft.gui.rendering.hud
enum class HUDScale(val scale: Float) {
TINY(0.1f),
MEDIUM(0.2f),
LARGE(0.5f),
SENIOR(1.0f),
}

View File

@ -1,8 +1,6 @@
package de.bixilon.minosoft.gui.rendering.textures
import de.bixilon.minosoft.data.assets.AssetsManager
import de.bixilon.minosoft.data.mappings.blocks.Block
import de.bixilon.minosoft.gui.rendering.textures.TextureLoader.loadTextureArray
import org.lwjgl.opengl.GL11.*
import org.lwjgl.opengl.GL12.glTexImage3D
import org.lwjgl.opengl.GL12.glTexSubImage3D
@ -11,7 +9,7 @@ import org.lwjgl.opengl.GL30.GL_TEXTURE_2D_ARRAY
import org.lwjgl.opengl.GL30.glGenerateMipmap
import java.nio.ByteBuffer
class TextureArray(private val assetsManager: AssetsManager, private val blocks: Set<Block>) {
class TextureArray(private val assetsManager: AssetsManager, private val textures: List<Texture>, private val size: Int = 16) {
var textureId = 0
fun load(): Int {
@ -24,32 +22,20 @@ class TextureArray(private val assetsManager: AssetsManager, private val blocks:
// load and generate the texture
val textures = resolveTextureIds(blocks)
val textureMap: Map<Texture, ByteBuffer> = loadTextureArray(assetsManager, textures)
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16, textures.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, null as ByteBuffer?)
val textureMap: Map<Texture, ByteBuffer> = TextureLoader.loadTextureArray(assetsManager, textures)
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, size, size, textures.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, null as ByteBuffer?)
for ((key, value) in textureMap) {
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, key.id, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, value)
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, key.id, size, size, 1, GL_RGBA, GL_UNSIGNED_BYTE, value)
}
glGenerateMipmap(GL_TEXTURE_2D_ARRAY)
return textureId
}
private fun resolveTextureIds(blocks: Set<Block>): List<Texture> {
val textures: MutableList<Texture> = mutableListOf()
textures.add(DEBUG_TEXTURE)
val textureMap: MutableMap<String, Texture> = mutableMapOf()
textureMap[DEBUG_TEXTURE.name] = DEBUG_TEXTURE
for (block in blocks) {
block.blockModel?.resolveTextures(textures, textureMap)
}
return textures
}
fun use(textureMode: Int) {
glActiveTexture(textureMode)
glBindTexture(GL_TEXTURE_2D, textureId)
glBindTexture(GL_TEXTURE_2D_ARRAY, textureId)
}
companion object {

View File

@ -3,7 +3,6 @@ layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec2 textureIndex;
layout (location = 2) in float textureLayer;
out vec3 vertexColor;
out vec3 passTextureCoordinates;

View File

@ -0,0 +1,19 @@
#version 330 core
out vec4 outColor;
in vec3 passTextureCoordinates;
uniform sampler2DArray texureArray;
void main() {
vec4 texColor = texture(texureArray, passTextureCoordinates);
if (texColor.a == 0) {
discard;
}
texColor.r = 0.8f;
texColor.g = 0.8f;
texColor.b = 0.0f;
outColor = texColor;
}

View File

@ -0,0 +1,13 @@
#version 330 core
layout (location = 0) in vec2 inPosition;
layout (location = 1) in vec2 textureIndex;
layout (location = 2) in float textureLayer;
out vec3 passTextureCoordinates;
uniform float atlasSize;
void main() {
gl_Position = vec4(inPosition, 0.0f, 1.0f);
passTextureCoordinates = vec3(textureIndex / atlasSize, textureLayer);
}