[WIP] Cactus, netherrack, round logs work

+ lots more cleanup
+ Optifine x-ray fix
This commit is contained in:
octarine-noise
2021-05-13 00:44:45 +02:00
parent dbc421c18e
commit 9899816029
40 changed files with 1059 additions and 401 deletions

View File

@@ -2,7 +2,8 @@ package mods.betterfoliage.render.lighting
import mods.betterfoliage.model.HalfBakedQuad
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.EPSILON
import mods.betterfoliage.util.EPSILON_ONE
import mods.betterfoliage.util.EPSILON_ZERO
import mods.betterfoliage.util.minBy
import net.minecraft.client.renderer.color.BlockColors
import net.minecraft.util.Direction
@@ -41,6 +42,12 @@ class VanillaQuadLighting {
abstract class VanillaVertexLighter {
abstract fun updateLightmapAndColor(quad: HalfBakedQuad, lighting: VanillaQuadLighting)
/**
* Update lighting for each vertex with AO values from one of the corners.
* Does not calculate missing AO values!
* @param quad the quad to shade
* @param func selector function from vertex position to directed corner index of desired AO values
*/
inline fun VanillaQuadLighting.updateWithCornerAo(quad: HalfBakedQuad, func: (Double3)->Int?) {
quad.raw.verts.forEachIndexed { idx, vertex ->
func(vertex.xyz)?.let {
@@ -51,9 +58,13 @@ abstract class VanillaVertexLighter {
}
}
/**
* Replicates vanilla shading for full blocks. Interpolation for non-full blocks
* is not implemented.
*/
object VanillaFullBlockLighting : VanillaVertexLighter() {
override fun updateLightmapAndColor(quad: HalfBakedQuad, lighting: VanillaQuadLighting) {
// TODO bounds checking
// TODO bounds checking & interpolation
val face = quad.raw.face()
lighting.calc.fillLightData(face, true)
lighting.updateWithCornerAo(quad) { nearestCornerOnFace(it, face) }
@@ -62,7 +73,7 @@ object VanillaFullBlockLighting : VanillaVertexLighter() {
}
}
object RoundLeafLighting : VanillaVertexLighter() {
object RoundLeafLightingPreferUp : VanillaVertexLighter() {
override fun updateLightmapAndColor(quad: HalfBakedQuad, lighting: VanillaQuadLighting) {
val angles = getAngles45(quad)?.let { normalFaces ->
lighting.calc.fillLightData(normalFaces.first)
@@ -79,6 +90,28 @@ object RoundLeafLighting : VanillaVertexLighter() {
}
}
/**
* Lights vertices with the AO values from the nearest corner on either of
* the 2 faces the quad normal points towards.
*/
object RoundLeafLighting : VanillaVertexLighter() {
override fun updateLightmapAndColor(quad: HalfBakedQuad, lighting: VanillaQuadLighting) {
val angles = getAngles45(quad)?.let { normalFaces ->
lighting.calc.fillLightData(normalFaces.first)
lighting.calc.fillLightData(normalFaces.second)
lighting.updateWithCornerAo(quad) { vertex ->
val cornerUndir = AoSideHelper.getCornerUndir(vertex.x, vertex.y, vertex.z)
val preferredFace = normalFaces.minBy { faceDistance(it, vertex) }
AoSideHelper.boxCornersDirFromUndir[preferredFace.ordinal][cornerUndir]
}
lighting.updateBlockTint(quad.baked.tintIndex)
}
}
}
/**
* Lights vertices with the AO values from the nearest corner on the preferred face.
*/
class LightingPreferredFace(val face: Direction) : VanillaVertexLighter() {
override fun updateLightmapAndColor(quad: HalfBakedQuad, lighting: VanillaQuadLighting) {
lighting.calc.fillLightData(face)
@@ -87,6 +120,38 @@ class LightingPreferredFace(val face: Direction) : VanillaVertexLighter() {
}
}
object ColumnLighting : VanillaVertexLighter() {
override fun updateLightmapAndColor(quad: HalfBakedQuad, lighting: VanillaQuadLighting) {
// faces pointing in cardinal directions
getNormalFace(quad)?.let { face ->
lighting.calc.fillLightData(face)
lighting.updateWithCornerAo(quad) { nearestCornerOnFace(it, face) }
lighting.updateBlockTint(quad.baked.tintIndex)
return
}
// faces pointing at 45deg angles
getAngles45(quad)?.let { (face1, face2) ->
lighting.calc.fillLightData(face1)
lighting.calc.fillLightData(face2)
quad.raw.verts.forEachIndexed { idx, vertex ->
val cornerUndir = AoSideHelper.getCornerUndir(vertex.xyz.x, vertex.xyz.y, vertex.xyz.z)
val cornerDir1 = AoSideHelper.boxCornersDirFromUndir[face1.ordinal][cornerUndir]
val cornerDir2 = AoSideHelper.boxCornersDirFromUndir[face2.ordinal][cornerUndir]
if (cornerDir1 == null || cornerDir2 == null) return@let
val ao1 = lighting.calc.aoData[cornerDir1]
val ao2 = lighting.calc.aoData[cornerDir2]
lighting.packedLight[idx] = ((ao1.packedLight + ao2.packedLight) shr 1) and 0xFF00FF
lighting.colorMultiplier[idx] = (ao1.colorMultiplier + ao2.colorMultiplier) * 0.5f
}
lighting.updateBlockTint(quad.baked.tintIndex)
return
}
// something is wrong...
lighting.updateWithCornerAo(quad) { nearestCornerOnFace(it, quad.raw.face()) }
lighting.updateBlockTint(quad.baked.tintIndex)
}
}
/**
* Return the directed box corner index for the corner nearest the given vertex,
* which is on the given face. May return null if the vertex is closest to
@@ -107,9 +172,9 @@ fun getAngles45(quad: HalfBakedQuad): Pair<Direction, Direction>? {
val normal = quad.raw.normal
// one of the components must be close to zero
val zeroAxis = when {
abs(normal.x) < EPSILON -> Axis.X
abs(normal.y) < EPSILON -> Axis.Y
abs(normal.z) < EPSILON -> Axis.Z
abs(normal.x) < EPSILON_ZERO -> Axis.X
abs(normal.y) < EPSILON_ZERO -> Axis.Y
abs(normal.z) < EPSILON_ZERO -> Axis.Z
else -> return null
}
// the other two must be of similar magnitude
@@ -118,7 +183,7 @@ fun getAngles45(quad: HalfBakedQuad): Pair<Direction, Direction>? {
Axis.Y -> abs(abs(normal.x) - abs(normal.z))
Axis.Z -> abs(abs(normal.x) - abs(normal.y))
}
if (diff > EPSILON) return null
if (diff > EPSILON_ZERO) return null
return when(zeroAxis) {
Axis.X -> Pair(if (normal.y > 0.0f) UP else DOWN, if (normal.z > 0.0f) SOUTH else NORTH)
Axis.Y -> Pair(if (normal.x > 0.0f) EAST else WEST, if (normal.z > 0.0f) SOUTH else NORTH)
@@ -126,6 +191,18 @@ fun getAngles45(quad: HalfBakedQuad): Pair<Direction, Direction>? {
}
}
fun getNormalFace(quad: HalfBakedQuad) = quad.raw.normal.let { normal ->
when {
normal.x > EPSILON_ONE -> EAST
normal.x < -EPSILON_ONE -> WEST
normal.y > EPSILON_ONE -> UP
normal.y < -EPSILON_ONE -> DOWN
normal.z > EPSILON_ONE -> SOUTH
normal.z < -EPSILON_ONE -> NORTH
else -> null
}
}
fun faceDistance(face: Direction, pos: Double3) = when(face) {
WEST -> pos.x; EAST -> 1.0 - pos.x
DOWN -> pos.y; UP -> 1.0 - pos.y