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 { fun getInChunkSectionPosition(): InChunkSectionPosition {
val location = getInChunkPosition() return getInChunkPosition().getInChunkSectionLocation()
return InChunkSectionPosition(location.x, getSectionHeight(), location.z)
} }
fun getSectionHeight(): Int { fun getSectionHeight(): Int {

View File

@ -14,18 +14,33 @@
package de.bixilon.minosoft.data.world.light package de.bixilon.minosoft.data.world.light
import de.bixilon.minosoft.data.world.BlockPosition 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( class ChunkLightAccessor(
private val blockLightLevel: MutableMap<Int, MutableMap<InChunkPosition, Byte>> = mutableMapOf(), private val blockLightLevel: MutableMap<Int, ByteArray> = mutableMapOf(),
private val skyLightLevel: MutableMap<Int, MutableMap<InChunkPosition, Byte>> = mutableMapOf(), private val skyLightLevel: MutableMap<Int, ByteArray> = mutableMapOf(),
) : LightAccessor { ) : LightAccessor {
override fun getSkyLight(blockPosition: BlockPosition): Byte { override fun getSkyLight(blockPosition: BlockPosition): Int {
return skyLightLevel[blockPosition.getSectionHeight()]?.get(blockPosition.getInChunkPosition()) ?: 0 return get(skyLightLevel, blockPosition)
} }
override fun getBlockLight(blockPosition: BlockPosition): Byte { override fun getBlockLight(blockPosition: BlockPosition): Int {
return blockLightLevel[blockPosition.getSectionHeight()]?.get(blockPosition.getInChunkPosition()) ?: 0 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) { fun merge(chunkLightAccessor: ChunkLightAccessor) {

View File

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

View File

@ -17,11 +17,11 @@ import de.bixilon.minosoft.data.world.BlockPosition
interface LightAccessor { 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 blockLight = getBlockLight(blockPosition)
val skyLight = getSkyLight(blockPosition) val skyLight = getSkyLight(blockPosition)
if (blockLight > skyLight) { if (blockLight > skyLight) {

View File

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

View File

@ -25,7 +25,7 @@ import org.lwjgl.opengl.GL20.glVertexAttribPointer
class ChunkMesh : Mesh() { 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.x)
data.add(position.y) data.add(position.y)
data.add(position.z) data.add(position.z)
@ -44,7 +44,12 @@ class ChunkMesh : Mesh() {
data.add(Float.fromBits(tintColor.color)) 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() { override fun load() {
@ -75,6 +80,6 @@ class ChunkMesh : Mesh() {
companion object { companion object {
private const val FLOATS_PER_VERTEX = 11 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) { // if (texture.isTransparent) {
// return // ToDo: force render transparent faces // 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]]) 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 yaw = hudTextElement.renderWindow.camera.yaw
val pitch = hudTextElement.renderWindow.camera.pitch val pitch = hudTextElement.renderWindow.camera.pitch
val direction = Directions.byDirection(camera.cameraFront) 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 package de.bixilon.minosoft.util.chunk
import de.bixilon.minosoft.data.mappings.Dimension 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.ChunkLightAccessor
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.protocol.protocol.InByteBuffer import de.bixilon.minosoft.protocol.protocol.InByteBuffer
@ -34,7 +33,7 @@ object LightUtil {
return ChunkLightAccessor(blockLight, skyLight) 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 var highestSectionIndex = dimension.highestSection + 1
val lowesSectionIndex = dimension.lowestSection - 1 val lowesSectionIndex = dimension.lowestSection - 1
if (buffer.versionId >= ProtocolVersions.V_20W49A) { if (buffer.versionId >= ProtocolVersions.V_20W49A) {
@ -42,26 +41,14 @@ object LightUtil {
highestSectionIndex = lightMask.length() 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 for ((arrayIndex, sectionHeight) in (lowesSectionIndex until highestSectionIndex).withIndex()) { // light sections
val currentSectionLightLevel: MutableMap<InChunkPosition, Byte> = mutableMapOf()
if (!lightMask[arrayIndex]) { if (!lightMask[arrayIndex]) {
continue continue
} }
val lightArray = buffer.readBytes(buffer.readVarInt()) lightLevels[sectionHeight] = 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
} }
return lightLevels return lightLevels
} }