performance: improve light storage a lot

This commit is contained in:
Bixilon 2021-02-28 19:13:17 +01:00
parent 9b7f70366b
commit 6dd2d3c5d3
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 43 additions and 37 deletions

View File

@ -57,8 +57,7 @@ data class BlockPosition(val x: Int, val y: Int, val z: Int) {
}
fun getInChunkSectionPosition(): InChunkSectionPosition {
val location = getInChunkPosition()
return InChunkSectionPosition(location.x, getSectionHeight(), location.z)
return getInChunkPosition().getInChunkSectionLocation()
}
fun getSectionHeight(): Int {

View File

@ -14,18 +14,33 @@
package de.bixilon.minosoft.data.world.light
import de.bixilon.minosoft.data.world.BlockPosition
import de.bixilon.minosoft.data.world.InChunkPosition
import de.bixilon.minosoft.data.world.InChunkSectionPosition
import unsigned.toUInt
class ChunkLightAccessor(
private val blockLightLevel: MutableMap<Int, MutableMap<InChunkPosition, Byte>> = mutableMapOf(),
private val skyLightLevel: MutableMap<Int, MutableMap<InChunkPosition, Byte>> = mutableMapOf(),
private val blockLightLevel: MutableMap<Int, ByteArray> = mutableMapOf(),
private val skyLightLevel: MutableMap<Int, ByteArray> = mutableMapOf(),
) : LightAccessor {
override fun getSkyLight(blockPosition: BlockPosition): Byte {
return skyLightLevel[blockPosition.getSectionHeight()]?.get(blockPosition.getInChunkPosition()) ?: 0
override fun getSkyLight(blockPosition: BlockPosition): Int {
return get(skyLightLevel, blockPosition)
}
override fun getBlockLight(blockPosition: BlockPosition): Byte {
return blockLightLevel[blockPosition.getSectionHeight()]?.get(blockPosition.getInChunkPosition()) ?: 0
override fun getBlockLight(blockPosition: BlockPosition): Int {
return get(blockLightLevel, blockPosition)
}
private fun get(data: MutableMap<Int, ByteArray>, blockPosition: BlockPosition): Int {
val index = getIndex(blockPosition.getInChunkSectionPosition())
val byte = data[blockPosition.getSectionHeight()]?.get(index ushr 1)?.toUInt() ?: 0xFF
return if (index and 0x01 == 0) { // first nibble
byte and 0x0F
} else {
((byte) shr 4) and 0x0F
}
}
private fun getIndex(inChunkSectionPosition: InChunkSectionPosition): Int {
return inChunkSectionPosition.y shl 8 or (inChunkSectionPosition.z shl 4) or inChunkSectionPosition.x
}
fun merge(chunkLightAccessor: ChunkLightAccessor) {

View File

@ -16,11 +16,11 @@ package de.bixilon.minosoft.data.world.light
import de.bixilon.minosoft.data.world.BlockPosition
object DummyLightAccessor : LightAccessor {
override fun getSkyLight(blockPosition: BlockPosition): Byte {
override fun getSkyLight(blockPosition: BlockPosition): Int {
return 15
}
override fun getBlockLight(blockPosition: BlockPosition): Byte {
override fun getBlockLight(blockPosition: BlockPosition): Int {
return 15
}

View File

@ -17,11 +17,11 @@ import de.bixilon.minosoft.data.world.BlockPosition
interface LightAccessor {
fun getSkyLight(blockPosition: BlockPosition): Byte
fun getSkyLight(blockPosition: BlockPosition): Int
fun getBlockLight(blockPosition: BlockPosition): Byte
fun getBlockLight(blockPosition: BlockPosition): Int
fun getLightLevel(blockPosition: BlockPosition): Byte {
fun getLightLevel(blockPosition: BlockPosition): Int {
val blockLight = getBlockLight(blockPosition)
val skyLight = getSkyLight(blockPosition)
if (blockLight > skyLight) {

View File

@ -19,11 +19,11 @@ import de.bixilon.minosoft.data.world.World
class WorldLightAccessor(
private val world: World,
) : LightAccessor {
override fun getSkyLight(blockPosition: BlockPosition): Byte {
override fun getSkyLight(blockPosition: BlockPosition): Int {
return world.chunks[blockPosition.getChunkPosition()]?.lightAccessor?.getSkyLight(blockPosition) ?: 0
}
override fun getBlockLight(blockPosition: BlockPosition): Byte {
override fun getBlockLight(blockPosition: BlockPosition): Int {
return world.chunks[blockPosition.getChunkPosition()]?.lightAccessor?.getBlockLight(blockPosition) ?: 0
}
}

View File

@ -25,7 +25,7 @@ import org.lwjgl.opengl.GL20.glVertexAttribPointer
class ChunkMesh : Mesh() {
fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Byte = 14) {
fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Int = 14) {
data.add(position.x)
data.add(position.y)
data.add(position.z)
@ -44,7 +44,12 @@ class ChunkMesh : Mesh() {
data.add(Float.fromBits(tintColor.color))
}
data.add(lightLevel / MAX_LIGHT_LEVEL)
val rightLightLevel = if (lightLevel == 0) {
1
} else {
lightLevel + 1
}
data.add(rightLightLevel / MAX_LIGHT_LEVEL)
}
override fun load() {
@ -75,6 +80,6 @@ class ChunkMesh : Mesh() {
companion object {
private const val FLOATS_PER_VERTEX = 11
private const val MAX_LIGHT_LEVEL = 15f
private const val MAX_LIGHT_LEVEL = 17f // Level 0 and 15 kind of does not exist here.
}
}

View File

@ -62,7 +62,7 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolea
// if (texture.isTransparent) {
// return // ToDo: force render transparent faces
// }
val lightLevel = lightAccessor.getLightLevel(position + face.cullFace) // ToDo: rotate cullface
val lightLevel = lightAccessor.getLightLevel(position + directionMapping[face.cullFace]) // ToDo: rotate cullface
val drawPositions = arrayOf(positions[positionTemplate[0]], positions[positionTemplate[1]], positions[positionTemplate[2]], positions[positionTemplate[3]])

View File

@ -170,7 +170,7 @@ class HUDDebugScreenElement(private val hudTextElement: HUDTextElement) : HUDTex
val yaw = hudTextElement.renderWindow.camera.yaw
val pitch = hudTextElement.renderWindow.camera.pitch
val direction = Directions.byDirection(camera.cameraFront)
return "${Directions.byDirection(camera.cameraFront).name.toLowerCase()} (${direction.directionVector} (${formatRotation(yaw)} / ${formatRotation(pitch)})"
return "${Directions.byDirection(camera.cameraFront).name.toLowerCase()} ${direction.directionVector} (${formatRotation(yaw)} / ${formatRotation(pitch)})"
}

View File

@ -14,7 +14,6 @@
package de.bixilon.minosoft.util.chunk
import de.bixilon.minosoft.data.mappings.Dimension
import de.bixilon.minosoft.data.world.InChunkPosition
import de.bixilon.minosoft.data.world.light.ChunkLightAccessor
import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.protocol.protocol.InByteBuffer
@ -34,7 +33,7 @@ object LightUtil {
return ChunkLightAccessor(blockLight, skyLight)
}
private fun readLightArray(buffer: InByteBuffer, lightMask: BitSet, dimension: Dimension): MutableMap<Int, MutableMap<InChunkPosition, Byte>> {
private fun readLightArray(buffer: InByteBuffer, lightMask: BitSet, dimension: Dimension): MutableMap<Int, ByteArray> {
var highestSectionIndex = dimension.highestSection + 1
val lowesSectionIndex = dimension.lowestSection - 1
if (buffer.versionId >= ProtocolVersions.V_20W49A) {
@ -42,26 +41,14 @@ object LightUtil {
highestSectionIndex = lightMask.length()
}
val lightLevels: MutableMap<Int, MutableMap<InChunkPosition, Byte>> = mutableMapOf()
val lightLevels: MutableMap<Int, ByteArray> = mutableMapOf()
for ((arrayIndex, sectionHeight) in (lowesSectionIndex until highestSectionIndex).withIndex()) { // light sections
val currentSectionLightLevel: MutableMap<InChunkPosition, Byte> = mutableMapOf()
if (!lightMask[arrayIndex]) {
continue
}
val lightArray = buffer.readBytes(buffer.readVarInt())
var index = 0
for (y in 0 until 16) {
for (z in 0 until 16) {
for (x in 0 until 16 step 2) {
currentSectionLightLevel[InChunkPosition(x, y + sectionHeight * 16, z)] = (lightArray[index].toInt() and 0x0F).toByte()
currentSectionLightLevel[InChunkPosition(x + 1, y + sectionHeight * 16, z)] = ((lightArray[index].toInt() ushr 4) and 0x0F).toByte()
index++
}
}
}
lightLevels[sectionHeight] = currentSectionLightLevel
lightLevels[sectionHeight] = buffer.readBytes(buffer.readVarInt())
}
return lightLevels
}