mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 11:24:56 -04:00
ambient occlusion: on demand
This is way faster now and almost disappeared in the cpu profiling. It also renders ao only on touching faces
This commit is contained in:
parent
b174638aaf
commit
1b869e4761
@ -34,11 +34,12 @@ import de.bixilon.minosoft.data.world.chunk.chunk.Chunk
|
|||||||
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
|
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
|
||||||
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
|
||||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.InChunkSectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.RenderedBlockEntity
|
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.RenderedBlockEntity
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes
|
||||||
import de.bixilon.minosoft.gui.rendering.light.AmbientOcclusionUtil
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusion
|
||||||
import de.bixilon.minosoft.gui.rendering.models.block.state.render.WorldRenderProps
|
import de.bixilon.minosoft.gui.rendering.models.block.state.render.WorldRenderProps
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -68,6 +69,7 @@ class SolidSectionMesher(
|
|||||||
val entities: ArrayList<BlockEntityRenderer<*>> = ArrayList(section.blockEntities.count)
|
val entities: ArrayList<BlockEntityRenderer<*>> = ArrayList(section.blockEntities.count)
|
||||||
|
|
||||||
val position = BlockPosition()
|
val position = BlockPosition()
|
||||||
|
val inSectionPosition = InChunkSectionPosition()
|
||||||
val neighbourBlocks: Array<BlockState?> = arrayOfNulls(Directions.SIZE)
|
val neighbourBlocks: Array<BlockState?> = arrayOfNulls(Directions.SIZE)
|
||||||
val light = ByteArray(Directions.SIZE + 1) // last index (6) for the current block
|
val light = ByteArray(Directions.SIZE + 1) // last index (6) for the current block
|
||||||
|
|
||||||
@ -79,15 +81,17 @@ class SolidSectionMesher(
|
|||||||
|
|
||||||
val floatOffset = FloatArray(3)
|
val floatOffset = FloatArray(3)
|
||||||
|
|
||||||
val ao = Array(Directions.SIZE) { IntArray(4) }
|
val ao = if (ambientOcclusion) AmbientOcclusion(section) else null
|
||||||
|
|
||||||
val props = WorldRenderProps(position, floatOffset, mesh, random, neighbourBlocks, light, ao)
|
val props = WorldRenderProps(position, inSectionPosition, floatOffset, mesh, random, neighbourBlocks, light, ao)
|
||||||
|
|
||||||
for (y in blocks.minPosition.y..blocks.maxPosition.y) {
|
for (y in blocks.minPosition.y..blocks.maxPosition.y) {
|
||||||
|
inSectionPosition.y = y
|
||||||
position.y = offsetY + y
|
position.y = offsetY + y
|
||||||
floatOffset[1] = (position.y - cameraOffset.y).toFloat()
|
floatOffset[1] = (position.y - cameraOffset.y).toFloat()
|
||||||
val fastBedrock = y == 0 && isLowestSection && fastBedrock
|
val fastBedrock = y == 0 && isLowestSection && fastBedrock
|
||||||
for (x in blocks.minPosition.x..blocks.maxPosition.x) {
|
for (x in blocks.minPosition.x..blocks.maxPosition.x) {
|
||||||
|
inSectionPosition.x = x
|
||||||
position.x = offsetX + x
|
position.x = offsetX + x
|
||||||
floatOffset[0] = (position.x - cameraOffset.x).toFloat()
|
floatOffset[0] = (position.x - cameraOffset.x).toFloat()
|
||||||
for (z in blocks.minPosition.z..blocks.maxPosition.z) {
|
for (z in blocks.minPosition.z..blocks.maxPosition.z) {
|
||||||
@ -104,6 +108,7 @@ class SolidSectionMesher(
|
|||||||
|
|
||||||
light[SELF_LIGHT_INDEX] = section.light[index]
|
light[SELF_LIGHT_INDEX] = section.light[index]
|
||||||
position.z = offsetZ + z
|
position.z = offsetZ + z
|
||||||
|
inSectionPosition.z = z
|
||||||
floatOffset[2] = (position.z - cameraOffset.z).toFloat()
|
floatOffset[2] = (position.z - cameraOffset.z).toFloat()
|
||||||
|
|
||||||
val maxHeight = chunk.light.heightmap[baseIndex]
|
val maxHeight = chunk.light.heightmap[baseIndex]
|
||||||
@ -136,9 +141,7 @@ class SolidSectionMesher(
|
|||||||
floatOffset[2] += offset.z
|
floatOffset[2] += offset.z
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ambientOcclusion) {
|
ao?.clear()
|
||||||
AmbientOcclusionUtil.apply(section, x, y, z, ao)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val tints = tints.getBlockTint(state, chunk, x, position.y, z)
|
val tints = tints.getBlockTint(state, chunk, x, position.y, z)
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.light.ao
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.direction.Directions
|
||||||
|
import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
||||||
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusionUtil.applyBottom
|
||||||
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusionUtil.applyEast
|
||||||
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusionUtil.applyNorth
|
||||||
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusionUtil.applySouth
|
||||||
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusionUtil.applyTop
|
||||||
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusionUtil.applyWest
|
||||||
|
|
||||||
|
class AmbientOcclusion(
|
||||||
|
val section: ChunkSection,
|
||||||
|
) {
|
||||||
|
private var input = Array(Directions.SIZE) { IntArray(AmbientOcclusionUtil.LEVELS) }
|
||||||
|
private var output = Array(Directions.SIZE) { AmbientOcclusionUtil.EMPTY }
|
||||||
|
private var dirty = 0x00
|
||||||
|
|
||||||
|
|
||||||
|
fun apply(direction: Directions, position: BlockPosition) = apply(direction, position.x, position.y, position.z)
|
||||||
|
|
||||||
|
fun apply(direction: Directions, x: Int, y: Int, z: Int): IntArray {
|
||||||
|
val mask = 1 shl direction.ordinal
|
||||||
|
if (dirty and mask != 0) return output[direction.ordinal] // already calculated
|
||||||
|
|
||||||
|
val input = input[direction.ordinal]
|
||||||
|
|
||||||
|
dirty = dirty or mask
|
||||||
|
val output = when (direction) {
|
||||||
|
Directions.DOWN -> applyBottom(section, x, y, z, input)
|
||||||
|
Directions.UP -> applyTop(section, x, y, z, input)
|
||||||
|
|
||||||
|
Directions.NORTH -> applyNorth(section, x, y, z, input)
|
||||||
|
Directions.SOUTH -> applySouth(section, x, y, z, input)
|
||||||
|
|
||||||
|
Directions.WEST -> applyWest(section, x, y, z, input)
|
||||||
|
Directions.EAST -> applyEast(section, x, y, z, input)
|
||||||
|
}
|
||||||
|
this.output[direction.ordinal] = output
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
dirty = 0x00
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@
|
|||||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.light
|
package de.bixilon.minosoft.gui.rendering.light.ao
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.direction.Directions.Companion.O_DOWN
|
import de.bixilon.minosoft.data.direction.Directions.Companion.O_DOWN
|
||||||
import de.bixilon.minosoft.data.direction.Directions.Companion.O_EAST
|
import de.bixilon.minosoft.data.direction.Directions.Companion.O_EAST
|
||||||
@ -24,11 +24,14 @@ import de.bixilon.minosoft.data.world.chunk.ChunkSection
|
|||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
|
|
||||||
object AmbientOcclusionUtil {
|
object AmbientOcclusionUtil {
|
||||||
|
const val LEVELS = 4
|
||||||
const val LEVEL_NONE = 0
|
const val LEVEL_NONE = 0
|
||||||
const val LEVEL_1 = 1
|
const val LEVEL_1 = 1
|
||||||
const val LEVEL_2 = 2
|
const val LEVEL_2 = 2
|
||||||
const val LEVEL_3 = 3
|
const val LEVEL_3 = 3
|
||||||
|
|
||||||
|
val EMPTY = IntArray(LEVELS) { LEVEL_NONE }
|
||||||
|
|
||||||
fun ChunkSection?.trace(x: Int, y: Int, z: Int): Int {
|
fun ChunkSection?.trace(x: Int, y: Int, z: Int): Int {
|
||||||
if (this == null) return 0
|
if (this == null) return 0
|
||||||
var x = x
|
var x = x
|
||||||
@ -37,6 +40,8 @@ object AmbientOcclusionUtil {
|
|||||||
|
|
||||||
var section: ChunkSection? = this
|
var section: ChunkSection? = this
|
||||||
|
|
||||||
|
if (x < -1 || x > 16 || y < -1 || y > 16 || z < -1 || z > 16) throw IllegalArgumentException("x=$x, y=$y, z=$z")
|
||||||
|
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
section = section?.neighbours?.get(O_WEST)
|
section = section?.neighbours?.get(O_WEST)
|
||||||
x = ProtocolDefinition.SECTION_MAX_X
|
x = ProtocolDefinition.SECTION_MAX_X
|
||||||
@ -74,16 +79,9 @@ object AmbientOcclusionUtil {
|
|||||||
return side1 + side2 + corner
|
return side1 + side2 + corner
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IntArray.clear() {
|
|
||||||
this[0] = LEVEL_NONE
|
|
||||||
this[1] = LEVEL_NONE
|
|
||||||
this[2] = LEVEL_NONE
|
|
||||||
this[3] = LEVEL_NONE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setY(section: ChunkSection?, x: Int, y: Int, z: Int, flip: Boolean, ao: IntArray) {
|
fun setY(section: ChunkSection?, x: Int, y: Int, z: Int, flip: Boolean, ao: IntArray): IntArray {
|
||||||
ao.clear()
|
if (section == null || section.blocks.isEmpty) return EMPTY
|
||||||
if (section == null || section.blocks.isEmpty) return
|
|
||||||
|
|
||||||
val west = section.trace(x - 1, y, z + 0)
|
val west = section.trace(x - 1, y, z + 0)
|
||||||
val north = section.trace(x + 0, y, z - 1)
|
val north = section.trace(x + 0, y, z - 1)
|
||||||
@ -94,9 +92,11 @@ object AmbientOcclusionUtil {
|
|||||||
ao[2] = calculateLevel(east, south, section.trace(x + 1, y, z + 1))
|
ao[2] = calculateLevel(east, south, section.trace(x + 1, y, z + 1))
|
||||||
ao[if (flip) 3 else 1] = calculateLevel(north, east, section.trace(x + 1, y, z - 1))
|
ao[if (flip) 3 else 1] = calculateLevel(north, east, section.trace(x + 1, y, z - 1))
|
||||||
ao[if (flip) 1 else 3] = calculateLevel(south, west, section.trace(x - 1, y, z + 1))
|
ao[if (flip) 1 else 3] = calculateLevel(south, west, section.trace(x - 1, y, z + 1))
|
||||||
|
|
||||||
|
return ao
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyBottom(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray) {
|
fun applyBottom(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray): IntArray {
|
||||||
var section: ChunkSection? = section
|
var section: ChunkSection? = section
|
||||||
var y = y - 1
|
var y = y - 1
|
||||||
if (y < 0) {
|
if (y < 0) {
|
||||||
@ -104,10 +104,10 @@ object AmbientOcclusionUtil {
|
|||||||
y = ProtocolDefinition.SECTION_MAX_Y
|
y = ProtocolDefinition.SECTION_MAX_Y
|
||||||
}
|
}
|
||||||
|
|
||||||
setY(section, x, y, z, true, ao)
|
return setY(section, x, y, z, true, ao)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyTop(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray) {
|
fun applyTop(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray): IntArray {
|
||||||
var section: ChunkSection? = section
|
var section: ChunkSection? = section
|
||||||
var y = y + 1
|
var y = y + 1
|
||||||
if (y > ProtocolDefinition.SECTION_MAX_Y) {
|
if (y > ProtocolDefinition.SECTION_MAX_Y) {
|
||||||
@ -115,12 +115,11 @@ object AmbientOcclusionUtil {
|
|||||||
y = 0
|
y = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
setY(section, x, y, z, false, ao)
|
return setY(section, x, y, z, false, ao)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setZ(section: ChunkSection?, x: Int, y: Int, z: Int, flip: Boolean, ao: IntArray) {
|
fun setZ(section: ChunkSection?, x: Int, y: Int, z: Int, flip: Boolean, ao: IntArray): IntArray {
|
||||||
ao.clear()
|
if (section == null || section.blocks.isEmpty) return EMPTY
|
||||||
if (section == null || section.blocks.isEmpty) return
|
|
||||||
|
|
||||||
val down = section.trace(x + 0, y - 1, z)
|
val down = section.trace(x + 0, y - 1, z)
|
||||||
val west = section.trace(x - 1, y + 0, z)
|
val west = section.trace(x - 1, y + 0, z)
|
||||||
@ -131,10 +130,12 @@ object AmbientOcclusionUtil {
|
|||||||
ao[if (flip) 3 else 1] = calculateLevel(west, up, section.trace(x - 1, y + 1, z))
|
ao[if (flip) 3 else 1] = calculateLevel(west, up, section.trace(x - 1, y + 1, z))
|
||||||
ao[2] = calculateLevel(up, east, section.trace(x + 1, y + 1, z))
|
ao[2] = calculateLevel(up, east, section.trace(x + 1, y + 1, z))
|
||||||
ao[if (flip) 1 else 3] = calculateLevel(east, down, section.trace(x + 1, y - 1, z))
|
ao[if (flip) 1 else 3] = calculateLevel(east, down, section.trace(x + 1, y - 1, z))
|
||||||
|
|
||||||
|
return ao
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun applyNorth(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray) {
|
fun applyNorth(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray): IntArray {
|
||||||
var section: ChunkSection? = section
|
var section: ChunkSection? = section
|
||||||
var z = z - 1
|
var z = z - 1
|
||||||
if (z < 0) {
|
if (z < 0) {
|
||||||
@ -142,10 +143,10 @@ object AmbientOcclusionUtil {
|
|||||||
z = ProtocolDefinition.SECTION_MAX_Z
|
z = ProtocolDefinition.SECTION_MAX_Z
|
||||||
}
|
}
|
||||||
|
|
||||||
setZ(section, x, y, z, true, ao)
|
return setZ(section, x, y, z, true, ao)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applySouth(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray) {
|
fun applySouth(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray): IntArray {
|
||||||
var section: ChunkSection? = section
|
var section: ChunkSection? = section
|
||||||
var z = z + 1
|
var z = z + 1
|
||||||
if (z > ProtocolDefinition.SECTION_MAX_Z) {
|
if (z > ProtocolDefinition.SECTION_MAX_Z) {
|
||||||
@ -153,12 +154,11 @@ object AmbientOcclusionUtil {
|
|||||||
z = 0
|
z = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
setZ(section, x, y, z, false, ao)
|
return setZ(section, x, y, z, false, ao)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setX(section: ChunkSection?, x: Int, y: Int, z: Int, flip: Boolean, ao: IntArray) {
|
fun setX(section: ChunkSection?, x: Int, y: Int, z: Int, flip: Boolean, ao: IntArray): IntArray {
|
||||||
ao.clear()
|
if (section == null || section.blocks.isEmpty) return EMPTY
|
||||||
if (section == null || section.blocks.isEmpty) return
|
|
||||||
|
|
||||||
val down = section.trace(x + 0, y - 1, z)
|
val down = section.trace(x + 0, y - 1, z)
|
||||||
val north = section.trace(x, y + 0, z - 1)
|
val north = section.trace(x, y + 0, z - 1)
|
||||||
@ -169,9 +169,11 @@ object AmbientOcclusionUtil {
|
|||||||
ao[if (flip) 3 else 1] = calculateLevel(north, up, section.trace(x, y + 1, z - 1))
|
ao[if (flip) 3 else 1] = calculateLevel(north, up, section.trace(x, y + 1, z - 1))
|
||||||
ao[2] = calculateLevel(up, south, section.trace(x, y + 1, z + 1))
|
ao[2] = calculateLevel(up, south, section.trace(x, y + 1, z + 1))
|
||||||
ao[if (flip) 1 else 3] = calculateLevel(south, down, section.trace(x, y - 1, z + 1))
|
ao[if (flip) 1 else 3] = calculateLevel(south, down, section.trace(x, y - 1, z + 1))
|
||||||
|
|
||||||
|
return ao
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyWest(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray) {
|
fun applyWest(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray): IntArray {
|
||||||
var section: ChunkSection? = section
|
var section: ChunkSection? = section
|
||||||
var x = x - 1
|
var x = x - 1
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
@ -179,10 +181,10 @@ object AmbientOcclusionUtil {
|
|||||||
x = ProtocolDefinition.SECTION_MAX_X
|
x = ProtocolDefinition.SECTION_MAX_X
|
||||||
}
|
}
|
||||||
|
|
||||||
setX(section, x, y, z, false, ao)
|
return setX(section, x, y, z, false, ao)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyEast(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray) {
|
fun applyEast(section: ChunkSection, x: Int, y: Int, z: Int, ao: IntArray): IntArray {
|
||||||
var section: ChunkSection? = section
|
var section: ChunkSection? = section
|
||||||
var x = x + 1
|
var x = x + 1
|
||||||
if (x > ProtocolDefinition.SECTION_MAX_X) {
|
if (x > ProtocolDefinition.SECTION_MAX_X) {
|
||||||
@ -190,17 +192,6 @@ object AmbientOcclusionUtil {
|
|||||||
x = 0
|
x = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
setX(section, x, y, z, true, ao)
|
return setX(section, x, y, z, true, ao)
|
||||||
}
|
|
||||||
|
|
||||||
fun apply(section: ChunkSection, x: Int, y: Int, z: Int, ao: Array<IntArray>) {
|
|
||||||
applyBottom(section, x, y, z, ao[O_DOWN])
|
|
||||||
applyTop(section, x, y, z, ao[O_UP])
|
|
||||||
|
|
||||||
applyNorth(section, x, y, z, ao[O_NORTH])
|
|
||||||
applySouth(section, x, y, z, ao[O_SOUTH])
|
|
||||||
|
|
||||||
applyWest(section, x, y, z, ao[O_WEST])
|
|
||||||
applyEast(section, x, y, z, ao[O_EAST])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,6 +19,7 @@ import de.bixilon.minosoft.data.direction.Directions
|
|||||||
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
import de.bixilon.minosoft.data.entities.block.BlockEntity
|
||||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.BlockVertexConsumer
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.BlockVertexConsumer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusionUtil
|
||||||
import de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull.FaceCulling
|
import de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull.FaceCulling
|
||||||
import de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull.side.SideProperties
|
import de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull.side.SideProperties
|
||||||
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
|
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
|
||||||
@ -56,16 +57,22 @@ class BakedModel(
|
|||||||
|
|
||||||
for ((directionIndex, faces) in faces.withIndex()) {
|
for ((directionIndex, faces) in faces.withIndex()) {
|
||||||
val neighbour = neighbours[directionIndex]
|
val neighbour = neighbours[directionIndex]
|
||||||
val direction = Directions.VALUES[directionIndex].inverted
|
val direction = Directions.VALUES[directionIndex]
|
||||||
|
val inverted = direction.inverted
|
||||||
|
|
||||||
val ao = ao[directionIndex]
|
|
||||||
|
|
||||||
for (face in faces) {
|
for (face in faces) {
|
||||||
if (FaceCulling.canCull(state, face.properties, direction, neighbour)) {
|
if (FaceCulling.canCull(state, face.properties, inverted, neighbour)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
face.render(offset, mesh, light, tints, ao)
|
var aoRaw = AmbientOcclusionUtil.EMPTY
|
||||||
|
|
||||||
|
if (ao != null && face.properties != null) {
|
||||||
|
aoRaw = ao.apply(direction, props.inSectionPosition)
|
||||||
|
}
|
||||||
|
|
||||||
|
face.render(offset, mesh, light, tints, aoRaw)
|
||||||
|
|
||||||
rendered = true
|
rendered = true
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,17 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.render
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||||
|
import de.bixilon.minosoft.data.world.positions.InChunkSectionPosition
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.BlockVertexConsumer
|
import de.bixilon.minosoft.gui.rendering.chunk.mesh.BlockVertexConsumer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.light.ao.AmbientOcclusion
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class WorldRenderProps(
|
class WorldRenderProps(
|
||||||
@JvmField
|
@JvmField
|
||||||
val position: BlockPosition,
|
val position: BlockPosition,
|
||||||
@JvmField
|
@JvmField
|
||||||
|
val inSectionPosition: InChunkSectionPosition,
|
||||||
|
@JvmField
|
||||||
val offset: FloatArray,
|
val offset: FloatArray,
|
||||||
@JvmField
|
@JvmField
|
||||||
val mesh: BlockVertexConsumer,
|
val mesh: BlockVertexConsumer,
|
||||||
@ -32,5 +36,5 @@ class WorldRenderProps(
|
|||||||
@JvmField
|
@JvmField
|
||||||
val light: ByteArray,
|
val light: ByteArray,
|
||||||
@JvmField
|
@JvmField
|
||||||
var ao: Array<IntArray>,
|
val ao: AmbientOcclusion?,
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user