rendering: improve frustum culling code, cull chunks at y axis

This commit is contained in:
Bixilon 2021-03-13 18:00:15 +01:00
parent a695a7e027
commit 7bd34f85fa
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
7 changed files with 67 additions and 29 deletions

View File

@ -47,7 +47,7 @@ object KeyBindingsNames {
val TOGGLE_DEBUG_SCREEN = ResourceLocation("minosoft:toggle_debug_screen")
val DEBUG_CLEAR_CHUNK_CACHE = ResourceLocation("minosoft:debug_clear_chunk_cache")
val DEBUG_POLYGEN = ResourceLocation("minosoft:debug_polygen")
val DEBUG_POLYGON = ResourceLocation("minosoft:debug_polygon")
val DEBUG_MOUSE_CATCH = ResourceLocation("minosoft:debug_mouse_catch")
val WHEN_IN_GAME = ResourceLocation("minosoft:in_game")
@ -124,7 +124,7 @@ object KeyBindingsNames {
),
mutableSetOf(mutableSetOf(WHEN_IN_GAME))
),
DEBUG_POLYGEN to KeyBinding(
DEBUG_POLYGON to KeyBinding(
mutableMapOf(
KeyAction.MODIFIER to mutableSetOf(KeyCodes.KEY_F4),
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_P)

View File

@ -39,7 +39,7 @@ import kotlin.math.sin
class Camera(
val connection: Connection,
var fov: Float,
private val renderWindow: RenderWindow,
val renderWindow: RenderWindow,
) {
private var mouseSensitivity = Minosoft.getConfig().config.game.camera.moseSensitivity
private var movementSpeed = 7
@ -73,8 +73,12 @@ class Camera(
var inChunkSectionPosition: InChunkSectionPosition = InChunkSectionPosition(0, 0, 0)
private set
private var screenHeight = 0
private var screenWidth = 0
val frustum: Frustum = Frustum(this)
var screenHeight = 0
private set
var screenWidth = 0
private set
private val shaders: MutableSet<Shader> = mutableSetOf()
private var keyForwardDown = false
@ -214,7 +218,10 @@ class Camera(
// recalculate sky color for current biome
val blockPosition = Position(cameraPosition).toBlockPosition()
renderWindow.setSkyColor(connection.player.world.getChunk(blockPosition.getChunkPosition())?.biomeAccessor?.getBiome(blockPosition, connection.player.world.dimension?.supports3DBiomes ?: false)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR)
connection.renderer.renderWindow.worldRenderer.recalculateFrustum(Frustum(this))
frustum.recalculate()
renderWindow.worldRenderer.recalculateVisibleChunks()
connection.player.world.dimension?.hasSkyLight?.let {
if (it) {
renderWindow.setSkyColor(currentBiome?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR)

View File

@ -43,7 +43,7 @@ object RenderConstants {
const val TEXT_LINE_PADDING = 0
const val CHUNK_SECTIONS_PER_MESH = 8
const val CHUNK_SECTIONS_PER_MESH = 4
const val MAXIMUM_CALLS_PER_FRAME = 10
}

View File

@ -224,7 +224,7 @@ class RenderWindow(
// Make the OpenGL context current
glfwMakeContextCurrent(windowId)
// Enable v-sync
glfwSwapInterval(0)
glfwSwapInterval(1)
// Make the window visible
@ -309,14 +309,14 @@ class RenderWindow(
}
private fun registerGlobalKeyCombinations() {
registerKeyCallback(KeyBindingsNames.DEBUG_POLYGEN) { _: KeyCodes, _: KeyAction ->
registerKeyCallback(KeyBindingsNames.DEBUG_POLYGON) { _: KeyCodes, _: KeyAction ->
polygonEnabled = !polygonEnabled
glPolygonMode(GL_FRONT_AND_BACK, if (polygonEnabled) {
GL_LINE
} else {
GL_FILL
})
sendDebugMessage("Toggled polygen mode!")
sendDebugMessage("Toggled polygon mode!")
}
registerKeyCallback(KeyBindingsNames.DEBUG_MOUSE_CATCH) { _: KeyCodes, _: KeyAction ->
mouseCatch = !mouseCatch

View File

@ -3,7 +3,6 @@ package de.bixilon.minosoft.gui.rendering.chunk
import de.bixilon.minosoft.data.world.ChunkPosition
import de.bixilon.minosoft.gui.rendering.Camera
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.protocol.network.Connection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import glm_.glm
import glm_.vec3.Vec3
@ -13,7 +12,15 @@ class Frustum(private val camera: Camera) {
camera.cameraFront.normalize(),
)
init {
recalculate()
}
fun recalculate() {
normals.clear()
normals.add(camera.cameraFront.normalize())
calculateSideNormals()
calculateVerticalNormals()
}
@ -28,7 +35,7 @@ class Frustum(private val camera: Camera) {
}
private fun calculateVerticalNormals() {
val aspect = camera.connection.renderer.renderWindow.screenHeight.toFloat() / camera.connection.renderer.renderWindow.screenWidth.toFloat()
val aspect = camera.screenHeight.toFloat() / camera.screenWidth.toFloat()
val angle = glm.radians(camera.fov * aspect - 90f)
val sin = glm.sin(angle)
val cos = glm.cos(angle)
@ -63,12 +70,10 @@ class Frustum(private val camera: Camera) {
return true
}
fun containsChunk(chunkPosition: ChunkPosition, connection: Connection): Boolean {
val dimension = connection.player.world.dimension!!
val from = Vec3(chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X, dimension.minY, chunkPosition.z * ProtocolDefinition.SECTION_WIDTH_Z)
val to = from + Vec3(ProtocolDefinition.SECTION_WIDTH_X, dimension.logicalHeight, ProtocolDefinition.SECTION_WIDTH_Z)
val frustum = Frustum(connection.renderer.renderWindow.camera)
return frustum.containsRegion(from, to)
fun containsChunk(chunkPosition: ChunkPosition, lowestBlockHeight: Int, highestBlockHeight: Int): Boolean {
val from = Vec3(chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X, lowestBlockHeight, chunkPosition.z * ProtocolDefinition.SECTION_WIDTH_Z)
val to = from + Vec3(ProtocolDefinition.SECTION_WIDTH_X, highestBlockHeight, ProtocolDefinition.SECTION_WIDTH_Z)
return containsRegion(from, to)
}
}

View File

@ -24,6 +24,8 @@ import org.lwjgl.opengl.GL20.glEnableVertexAttribArray
import org.lwjgl.opengl.GL20.glVertexAttribPointer
class SectionArrayMesh : Mesh() {
var lowestBlockHeight = 0
var highestBlockHeight = 0
fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Int = 14) {
data.add(position.x)

View File

@ -39,7 +39,6 @@ class WorldRenderer(
lateinit var chunkShader: Shader
val allChunkSections = ConcurrentHashMap<ChunkPosition, ConcurrentHashMap<Int, SectionArrayMesh>>()
val visibleChunks = ConcurrentHashMap<ChunkPosition, ConcurrentHashMap<Int, SectionArrayMesh>>()
private lateinit var frustum: Frustum
private var currentTick = 0 // for animation usage
private var lastTickIncrementTime = 0L
val queuedChunks: MutableSet<ChunkPosition> = mutableSetOf()
@ -220,13 +219,33 @@ class WorldRenderer(
Minosoft.THREAD_POOL.execute {
val mesh = prepareSections(chunkPosition, sections)
var sectionMap = allChunkSections[chunkPosition]
if (sectionMap == null) {
sectionMap = ConcurrentHashMap()
allChunkSections[chunkPosition] = sectionMap
var lowestBlockHeight = 0
var highestBlockHeight = 0
for ((sectionHeight, _) in sections) {
if (sectionHeight < lowestBlockHeight) {
lowestBlockHeight = sectionHeight
}
if (sectionHeight > highestBlockHeight) {
highestBlockHeight = sectionHeight
}
}
val index = getSectionIndex(lowestBlockHeight)
lowestBlockHeight *= ProtocolDefinition.SECTION_HEIGHT_Y
highestBlockHeight = highestBlockHeight * ProtocolDefinition.SECTION_HEIGHT_Y + ProtocolDefinition.SECTION_MAX_Y
mesh.lowestBlockHeight = lowestBlockHeight
mesh.highestBlockHeight = highestBlockHeight
val sectionMap = allChunkSections[chunkPosition] ?: let {
val map: ConcurrentHashMap<Int, SectionArrayMesh> = ConcurrentHashMap()
allChunkSections[chunkPosition] = map
map
}
if (frustum.containsChunk(chunkPosition, connection)) {
if (renderWindow.camera.frustum.containsChunk(chunkPosition, lowestBlockHeight, highestBlockHeight)) {
visibleChunks[chunkPosition] = sectionMap
}
@ -302,12 +321,17 @@ class WorldRenderer(
prepareWorld(connection.player.world)
}
fun recalculateFrustum(frustum: Frustum) {
fun recalculateVisibleChunks() {
visibleChunks.clear()
this.frustum = frustum
for ((chunkLocation, sectionMap) in allChunkSections.entries) {
if (frustum.containsChunk(chunkLocation, connection)) {
visibleChunks[chunkLocation] = sectionMap
for ((chunkLocation, indexMap) in allChunkSections) {
val visibleIndexMap: ConcurrentHashMap<Int, SectionArrayMesh> = ConcurrentHashMap()
for ((index, mesh) in indexMap) {
if (renderWindow.camera.frustum.containsChunk(chunkLocation, mesh.lowestBlockHeight, mesh.highestBlockHeight)) {
visibleIndexMap[index] = mesh
}
}
if (visibleIndexMap.isNotEmpty()) {
visibleChunks[chunkLocation] = visibleIndexMap
}
}
}