mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 09:26:11 -04:00
skeletal: change normal encoding, shade lighting interpolation
This commit is contained in:
parent
b6b0a82ca9
commit
219a8085f8
@ -14,17 +14,21 @@
|
||||
package de.bixilon.minosoft.gui.rendering.skeletal.mesh
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import kotlin.math.abs
|
||||
|
||||
object SkeletalMeshUtil {
|
||||
private fun encodePart(part: Float): Int {
|
||||
val unsigned = (part + 1.0f) / 2.0f // remove negative sign
|
||||
return (unsigned * 15.0f).toInt() and 0x0F
|
||||
|
||||
private fun encodeY(part: Float): Int {
|
||||
if (part <= -1.0f) return 0
|
||||
if (part >= 1.0f) return 0x0F
|
||||
if (part < 0.0f) return ((part + 1.0f) * 8.0f).toInt() and 0x0F
|
||||
return 8 + (part * 7.0f).toInt()
|
||||
}
|
||||
|
||||
fun encodeNormal(normal: Vec3): Int {
|
||||
val x = encodePart(normal.x)
|
||||
val y = encodePart(normal.y)
|
||||
val z = encodePart(normal.z)
|
||||
val x = (abs(normal.x) * 15.0f).toInt()
|
||||
val y = encodeY(normal.y)
|
||||
val z = (abs(normal.z) * 15.0f).toInt()
|
||||
|
||||
return (y shl 8) or (z shl 4) or (x)
|
||||
}
|
||||
|
@ -10,16 +10,18 @@
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
#define DEGREE_90 1.5707964f
|
||||
|
||||
float decodeNormalPart(uint data) {
|
||||
return (data / 15.0f) * 2.0f - 1.0f;
|
||||
if (data <= 8u) return (data / 8.0f) - 1.0f;
|
||||
return (data - 8u) / 7.0f;
|
||||
}
|
||||
|
||||
vec3 decodeNormal(uint normal) {
|
||||
uint x = normal & 0x0Fu;
|
||||
uint y = normal >> 8u & 0x0Fu;
|
||||
uint z = normal >> 4u & 0x0Fu;
|
||||
return vec3(decodeNormalPart(x), decodeNormalPart(y), decodeNormalPart(z));
|
||||
return vec3(x / 15.0f, decodeNormalPart(y), z / 15.0f);
|
||||
}
|
||||
|
||||
vec3 transformNormal(vec3 normal, mat4 transform) {
|
||||
@ -27,12 +29,26 @@ vec3 transformNormal(vec3 normal, mat4 transform) {
|
||||
return mat3(transform) * normal;
|
||||
}
|
||||
|
||||
float getShade(vec3 normal) {
|
||||
// TODO: interpolate between 3 sides
|
||||
if (normal.y < -0.5f) return 0.5f;
|
||||
if (normal.y > 0.5f) return 1.0f;
|
||||
if (normal.x < -0.5f || normal.x > 0.5f) return 0.6f;
|
||||
if (normal.z < -0.5f || normal.z > 0.5f) return 0.8f;
|
||||
|
||||
return 1.0f;
|
||||
float interpolateShade(float delta, float max) {
|
||||
if (delta < 0.0f) delta = -delta;
|
||||
if (delta <= 0.0f) return 0.0f;
|
||||
if (delta >= 1.0f) return max;
|
||||
return delta * max;
|
||||
}
|
||||
|
||||
float getShade(vec3 normal) {
|
||||
float aX = asin(normal.x) / DEGREE_90;
|
||||
float aY = asin(normal.y) / DEGREE_90;
|
||||
float aZ = asin(normal.z) / DEGREE_90;
|
||||
|
||||
float x = interpolateShade(aX, 0.6f);
|
||||
float y;
|
||||
if (normal.y < 0.0f) {
|
||||
y = interpolateShade(-aY, 0.5f);
|
||||
} else {
|
||||
y = interpolateShade(aY, 1.0f);
|
||||
}
|
||||
float z = interpolateShade(aZ, 0.8f);
|
||||
|
||||
return (x + y + z);
|
||||
}
|
||||
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2023 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.models.block.state.baked
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.asin
|
||||
|
||||
class SkeletalShadeTest {
|
||||
private val DEGREE_90 = 1.5707964f
|
||||
|
||||
|
||||
fun interpolateShade(delta: Float, max: Float): Float {
|
||||
var delta = delta
|
||||
if (delta < 0.0f) delta = -delta
|
||||
if (delta <= 0.0f) return 0.0f
|
||||
if (delta >= 1.0f) return max
|
||||
return delta * max
|
||||
}
|
||||
|
||||
fun getShade(normal: Vec3): Float {
|
||||
normal.normalizeAssign() // for testing purposes
|
||||
// Take code from skeletal/shade.glsl
|
||||
|
||||
val aX = asin(normal.x) / DEGREE_90
|
||||
val aY = asin(normal.y) / DEGREE_90
|
||||
val aZ = asin(normal.z) / DEGREE_90
|
||||
|
||||
val x = interpolateShade(aX, 0.6f)
|
||||
val y: Float
|
||||
y = if (normal.y < 0.0f) {
|
||||
interpolateShade(-aY, 0.5f)
|
||||
} else {
|
||||
interpolateShade(aY, 1.0f)
|
||||
}
|
||||
val z = interpolateShade(aZ, 0.8f)
|
||||
|
||||
return x + y + z
|
||||
}
|
||||
|
||||
@Test
|
||||
fun up() {
|
||||
assertEquals(1.0f, getShade(Vec3(0, 1, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun down() {
|
||||
assertEquals(0.5f, getShade(Vec3(0, -1, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun north() {
|
||||
assertEquals(0.8f, getShade(Vec3(0, 0, 1)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun south() {
|
||||
assertEquals(0.8f, getShade(Vec3(0, 0, -1)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun west() {
|
||||
assertEquals(0.6f, getShade(Vec3(1, 0, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun east() {
|
||||
assertEquals(0.6f, getShade(Vec3(-1, 0, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun northWest() {
|
||||
assertEquals(0.7f, getShade(Vec3(1, 0, 1)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun eastSouth() {
|
||||
assertEquals(0.7f, getShade(Vec3(-1, 0, -1)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun westUp() {
|
||||
assertEquals(0.8f, getShade(Vec3(1, 1, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun westDown() {
|
||||
assertEquals(0.55f, getShade(Vec3(-1, -1, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun westNorthUp() {
|
||||
assertEquals(0.94f, getShade(Vec3(1, 1, 1)))
|
||||
}
|
||||
|
||||
private fun assertEquals(expected: Float, actual: Float) {
|
||||
if (abs(expected - actual) < 0.03f) return
|
||||
throw AssertionError("Expected $expected but got $actual")
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user