mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-06 04:16:36 +01:00
The boring way
- Just use vanilla's implementation for crumbling.
This commit is contained in:
parent
f3f02963a7
commit
21d7c26ad1
4 changed files with 34 additions and 80 deletions
|
@ -6,7 +6,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.jozufozu.flywheel.api.backend.Engine;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
|
@ -22,12 +21,11 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
|||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
public class InstancingCrumble {
|
||||
public class InstancedCrumbling {
|
||||
@NotNull
|
||||
public static Map<ShaderState, Int2ObjectMap<Map<BlockPos, List<Runnable>>>> doCrumblingSort(List<Engine.CrumblingBlock> instances) {
|
||||
Map<ShaderState, Int2ObjectMap<Map<BlockPos, List<Runnable>>>> out = new HashMap<>();
|
||||
public static Map<ShaderState, Int2ObjectMap<List<Runnable>>> doCrumblingSort(List<Engine.CrumblingBlock> instances) {
|
||||
Map<ShaderState, Int2ObjectMap<List<Runnable>>> out = new HashMap<>();
|
||||
|
||||
for (Engine.CrumblingBlock triple : instances) {
|
||||
int progress = triple.progress();
|
||||
|
@ -36,8 +34,6 @@ public class InstancingCrumble {
|
|||
continue;
|
||||
}
|
||||
|
||||
BlockPos position = triple.pos();
|
||||
|
||||
for (Instance instance : triple.instances()) {
|
||||
// Filter out instances that weren't created by this engine.
|
||||
// If all is well, we probably shouldn't take the `continue`
|
||||
|
@ -55,8 +51,7 @@ public class InstancingCrumble {
|
|||
|
||||
for (DrawCall draw : draws) {
|
||||
out.computeIfAbsent(draw.shaderState, $ -> new Int2ObjectArrayMap<>())
|
||||
.computeIfAbsent(progress, $ -> new HashMap<>())
|
||||
.computeIfAbsent(position, $ -> new ArrayList<>())
|
||||
.computeIfAbsent(progress, $ -> new ArrayList<>())
|
||||
.add(() -> draw.renderOne(impl));
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +59,7 @@ public class InstancingCrumble {
|
|||
return out;
|
||||
}
|
||||
|
||||
public static void render(List<Engine.CrumblingBlock> crumblingBlocks, BlockPos renderOrigin) {
|
||||
public static void render(List<Engine.CrumblingBlock> crumblingBlocks) {
|
||||
// Sort draw calls into buckets, so we don't have to do as many shader binds.
|
||||
var byShaderState = doCrumblingSort(crumblingBlocks);
|
||||
|
||||
|
@ -88,16 +83,14 @@ public class InstancingCrumble {
|
|||
.get(shader.vertexType(), shader.instanceType(), Contexts.CRUMBLING);
|
||||
UniformBuffer.syncAndBind(program);
|
||||
|
||||
int crumblingBlockPosUniform = program.getUniformLocation("_flw_crumblingBlockPos");
|
||||
|
||||
InstancingEngine.uploadMaterialIDUniform(program, material);
|
||||
|
||||
int renderTex = getDiffuseTexture(material);
|
||||
|
||||
for (Int2ObjectMap.Entry<Map<BlockPos, List<Runnable>>> progressEntry : byProgress.int2ObjectEntrySet()) {
|
||||
var byPos = progressEntry.getValue();
|
||||
for (Int2ObjectMap.Entry<List<Runnable>> progressEntry : byProgress.int2ObjectEntrySet()) {
|
||||
var drawCalls = progressEntry.getValue();
|
||||
|
||||
if (byPos.isEmpty()) {
|
||||
if (drawCalls.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -109,12 +102,7 @@ public class InstancingCrumble {
|
|||
GlTextureUnit.T1.makeActive();
|
||||
RenderSystem.bindTexture(renderTex);
|
||||
|
||||
for (var blockPosEntry : byPos.entrySet()) {
|
||||
var center = blockPosEntry.getKey().getCenter();
|
||||
GL32.glUniform3f(crumblingBlockPosUniform, (float) center.x - renderOrigin.getX(), (float) center.y - renderOrigin.getY(), (float) center.z - renderOrigin.getZ());
|
||||
|
||||
blockPosEntry.getValue().forEach(Runnable::run);
|
||||
}
|
||||
drawCalls.forEach(Runnable::run);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -76,7 +76,7 @@ public class InstancingEngine extends AbstractEngine {
|
|||
// Need to wait for flush before we can inspect instancer state.
|
||||
executor.syncUntil(flushFlag::isRaised);
|
||||
|
||||
InstancingCrumble.render(crumblingBlocks, this.renderOrigin);
|
||||
InstancedCrumbling.render(crumblingBlocks);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -7,39 +7,17 @@ layout (depth_greater) out float gl_FragDepth;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
uniform vec3 _flw_crumblingBlockPos;
|
||||
|
||||
uniform sampler2D flw_diffuseTex;
|
||||
uniform sampler2D flw_crumblingTex;
|
||||
|
||||
in vec2 _flw_crumblingFlip;
|
||||
in vec2 _flw_crumblingTexCoord;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
vec4 flw_crumblingSampleColor;
|
||||
|
||||
vec2 flattenedPos(vec3 pos, vec3 normal) {
|
||||
pos = pos - _flw_crumblingBlockPos;
|
||||
|
||||
// https://community.khronos.org/t/52861
|
||||
vec3 Q1 = dFdx(pos);
|
||||
vec3 Q2 = dFdy(pos);
|
||||
vec2 st1 = dFdx(flw_vertexTexCoord);
|
||||
vec2 st2 = dFdy(flw_vertexTexCoord);
|
||||
|
||||
vec3 T = normalize(Q1*st2.t - Q2*st1.t);
|
||||
vec3 B = normalize(-Q1*st2.s + Q2*st1.s);
|
||||
|
||||
mat3 tbn = mat3(T, B, normal);
|
||||
|
||||
// transpose is the same as inverse for orthonormal matrices
|
||||
return ((transpose(tbn) * pos).xy + vec2(0.5)) * _flw_crumblingFlip;
|
||||
}
|
||||
|
||||
void flw_initFragment() {
|
||||
vec2 crumblingTexCoord = flattenedPos(flw_vertexPos.xyz, flw_vertexNormal);
|
||||
|
||||
flw_crumblingSampleColor = texture(flw_crumblingTex, crumblingTexCoord);
|
||||
flw_crumblingSampleColor = texture(flw_crumblingTex, _flw_crumblingTexCoord);
|
||||
flw_sampleColor = texture(flw_diffuseTex, flw_vertexTexCoord);
|
||||
|
||||
// Let the other components modify the diffuse color as they normally would.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "flywheel:api/vertex.glsl"
|
||||
#include "flywheel:util/fog.glsl"
|
||||
|
||||
out vec2 _flw_crumblingFlip;
|
||||
out vec2 _flw_crumblingTexCoord;
|
||||
|
||||
const int DOWN = 0;
|
||||
const int UP = 1;
|
||||
|
@ -10,20 +10,13 @@ const int SOUTH = 3;
|
|||
const int WEST = 4;
|
||||
const int EAST = 5;
|
||||
|
||||
const vec2 FLIPS_BY_FACE[6] = vec2[](
|
||||
vec2(1., -1.),
|
||||
vec2(-1., -1.),
|
||||
vec2(-1., -1.),
|
||||
vec2(-1., -1.),
|
||||
vec2(1., -1.),
|
||||
vec2(1., -1.)
|
||||
);
|
||||
|
||||
// based on net.minecraftforge.client.ForgeHooksClient.getNearestStable
|
||||
int getNearestFacing(vec3 normal) {
|
||||
float maxAlignment = -2;
|
||||
int face = 2;
|
||||
|
||||
// Calculate the alignment of the normal vector with each axis.
|
||||
// Note that `-dot(normal, axis) == dot(normal, -axis)`.
|
||||
vec3 alignment = vec3(
|
||||
dot(normal, vec3(1., 0., 0.)),
|
||||
dot(normal, vec3(0., 1., 0.)),
|
||||
|
@ -46,44 +39,39 @@ int getNearestFacing(vec3 normal) {
|
|||
maxAlignment = alignment.z;
|
||||
face = SOUTH;
|
||||
}
|
||||
if (alignment.x > maxAlignment) {
|
||||
if (-alignment.x > maxAlignment) {
|
||||
maxAlignment = -alignment.x;
|
||||
face = WEST;
|
||||
}
|
||||
if (alignment.x > maxAlignment) {
|
||||
maxAlignment = alignment.x;
|
||||
face = EAST;
|
||||
}
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
vec2 calculateFlip(vec3 normal) {
|
||||
int face = getNearestFacing(normal);
|
||||
return FLIPS_BY_FACE[face];
|
||||
}
|
||||
vec2 getCrumblingTexCoord() {
|
||||
switch (getNearestFacing(flw_vertexNormal)) {
|
||||
case DOWN: return vec2(flw_vertexPos.x, -flw_vertexPos.z);
|
||||
case UP: return vec2(flw_vertexPos.x, flw_vertexPos.z);
|
||||
case NORTH: return vec2(-flw_vertexPos.x, -flw_vertexPos.y);
|
||||
case SOUTH: return vec2(flw_vertexPos.x, -flw_vertexPos.y);
|
||||
case WEST: return vec2(-flw_vertexPos.z, -flw_vertexPos.y);
|
||||
case EAST: return vec2(flw_vertexPos.z, -flw_vertexPos.y);
|
||||
}
|
||||
|
||||
// This is disgusting so if an issue comes up just throw this away and fix the branching version above.
|
||||
vec2 calculateFlipBranchless(vec3 normal) {
|
||||
vec3 alignment = vec3(
|
||||
dot(normal, vec3(1., 0., 0.)),
|
||||
dot(normal, vec3(0., 1., 0.)),
|
||||
dot(normal, vec3(0., 0., 1.))
|
||||
);
|
||||
|
||||
vec3 absAlignment = abs(alignment);
|
||||
|
||||
// x is the max alignment that would cause U to be -1.
|
||||
// y is the max alignment that would cause U to be 1.
|
||||
vec2 maxNegativeMaxPositive = max(vec2(absAlignment.z, alignment.y), vec2(-alignment.y, absAlignment.x));
|
||||
|
||||
bool flipU = maxNegativeMaxPositive.x > maxNegativeMaxPositive.y;
|
||||
|
||||
return vec2(mix(1., -1., flipU), -1.);
|
||||
// default to north
|
||||
return vec2(-flw_vertexPos.x, -flw_vertexPos.y);
|
||||
}
|
||||
|
||||
void flw_initVertex() {
|
||||
// Calculate the flips in model space so that the crumbling effect doesn't have discontinuities.
|
||||
_flw_crumblingFlip = calculateFlipBranchless(flw_vertexNormal);
|
||||
// no-op
|
||||
}
|
||||
|
||||
void flw_contextVertex() {
|
||||
_flw_crumblingTexCoord = getCrumblingTexCoord();
|
||||
|
||||
flw_distance = fog_distance(flw_vertexPos.xyz, flywheel.cameraPos.xyz, flywheel.fogShape);
|
||||
gl_Position = flywheel.viewProjection * flw_vertexPos;
|
||||
flw_vertexNormal = normalize(flw_vertexNormal);
|
||||
|
|
Loading…
Reference in a new issue