mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-30 14:55:01 +01:00
Merge remote-tracking branch 'origin/1.18/dev' into 1.18/fabric/dev
Conflicts: build.gradle gradle.properties src/main/java/com/jozufozu/flywheel/core/QuadConverter.java src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java src/main/java/com/jozufozu/flywheel/mixin/InstanceAddMixin.java src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java
This commit is contained in:
commit
7c757fee80
38 changed files with 318 additions and 341 deletions
|
@ -13,6 +13,17 @@ insert_final_newline = true
|
||||||
[*.json]
|
[*.json]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
max_line_length = 500
|
||||||
|
ij_json_keep_blank_lines_in_code = 0
|
||||||
|
ij_json_keep_indents_on_empty_lines = false
|
||||||
|
ij_json_keep_line_breaks = true
|
||||||
|
ij_json_space_after_colon = true
|
||||||
|
ij_json_space_after_comma = true
|
||||||
|
ij_json_space_before_colon = true
|
||||||
|
ij_json_space_before_comma = false
|
||||||
|
ij_json_spaces_within_braces = true
|
||||||
|
ij_json_spaces_within_brackets = false
|
||||||
|
ij_json_wrap_long_lines = false
|
||||||
|
|
||||||
[*.java]
|
[*.java]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
@ -59,6 +59,10 @@ body:
|
||||||
label: Mod Version
|
label: Mod Version
|
||||||
description: The version of the mod you were using when the bug occured
|
description: The version of the mod you were using when the bug occured
|
||||||
options:
|
options:
|
||||||
|
- "0.6.8"
|
||||||
|
- "0.6.7"
|
||||||
|
- "0.6.6"
|
||||||
|
- "0.6.5"
|
||||||
- "0.6.4"
|
- "0.6.4"
|
||||||
- "0.6.3"
|
- "0.6.3"
|
||||||
- "0.6.2"
|
- "0.6.2"
|
||||||
|
@ -77,6 +81,8 @@ body:
|
||||||
label: Minecraft Version
|
label: Minecraft Version
|
||||||
description: The version of Minecraft you were using when the bug occured
|
description: The version of Minecraft you were using when the bug occured
|
||||||
options:
|
options:
|
||||||
|
- "1.19.2"
|
||||||
|
- "1.18.2"
|
||||||
- "1.18.1"
|
- "1.18.1"
|
||||||
- "1.17.1"
|
- "1.17.1"
|
||||||
validations:
|
validations:
|
||||||
|
|
|
@ -71,6 +71,14 @@ dependencies {
|
||||||
modCompileOnly 'io.vram:frex-fabric-mc118:6.0.263'
|
modCompileOnly 'io.vram:frex-fabric-mc118:6.0.263'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loom {
|
||||||
|
runs {
|
||||||
|
client {
|
||||||
|
property('flw.loadRenderDoc', 'true')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
inputs.property 'version', project.version
|
inputs.property 'version', project.version
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx3G
|
||||||
org.gradle.daemon = false
|
org.gradle.daemon = false
|
||||||
|
|
||||||
# mod version info
|
# mod version info
|
||||||
mod_version = 0.6.4
|
mod_version = 0.6.8
|
||||||
artifact_minecraft_version = 1.18.2
|
artifact_minecraft_version = 1.18.2
|
||||||
|
|
||||||
minecraft_version = 1.18.2
|
minecraft_version = 1.18.2
|
||||||
|
@ -12,7 +12,7 @@ fabric_version = 0.56.1+1.18.2
|
||||||
# build dependency versions
|
# build dependency versions
|
||||||
loom_version = 0.12-SNAPSHOT
|
loom_version = 0.12-SNAPSHOT
|
||||||
cursegradle_version = 1.4.0
|
cursegradle_version = 1.4.0
|
||||||
parchment_version = 2022.07.10
|
parchment_version = 2022.11.06
|
||||||
|
|
||||||
# curseforge info
|
# curseforge info
|
||||||
projectId = 486392
|
projectId = 486392
|
||||||
|
|
|
@ -7,13 +7,12 @@ import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
* Tracks bound buffers/vbos because GlStateManager doesn't do that for us.
|
* Tracks bound buffers/vbos because GlStateManager doesn't do that for us.
|
||||||
*/
|
*/
|
||||||
public class GlStateTracker {
|
public class GlStateTracker {
|
||||||
|
private static final int[] BUFFERS = new int[GlBufferType.values().length];
|
||||||
private static final int[] buffers = new int[GlBufferType.values().length];
|
|
||||||
private static int vao;
|
private static int vao;
|
||||||
private static int program;
|
private static int program;
|
||||||
|
|
||||||
public static int getBuffer(GlBufferType type) {
|
public static int getBuffer(GlBufferType type) {
|
||||||
return buffers[type.ordinal()];
|
return BUFFERS[type.ordinal()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getVertexArray() {
|
public static int getVertexArray() {
|
||||||
|
@ -24,36 +23,36 @@ public class GlStateTracker {
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void _setBuffer(GlBufferType type, int buffer) {
|
public static void _setBuffer(GlBufferType type, int id) {
|
||||||
buffers[type.ordinal()] = buffer;
|
BUFFERS[type.ordinal()] = id;
|
||||||
}
|
|
||||||
|
|
||||||
public static void _setProgram(int id) {
|
|
||||||
program = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void _setVertexArray(int id) {
|
public static void _setVertexArray(int id) {
|
||||||
vao = id;
|
vao = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static State getRestoreState() {
|
public static void _setProgram(int id) {
|
||||||
return new State(buffers.clone(), vao, program);
|
program = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static record State(int[] buffers, int vao, int program) {
|
public static State getRestoreState() {
|
||||||
|
return new State(BUFFERS.clone(), vao, program);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record State(int[] buffers, int vao, int program) {
|
||||||
public void restore() {
|
public void restore() {
|
||||||
|
if (vao != GlStateTracker.vao) {
|
||||||
|
GlStateManager._glBindVertexArray(vao);
|
||||||
|
}
|
||||||
|
|
||||||
GlBufferType[] values = GlBufferType.values();
|
GlBufferType[] values = GlBufferType.values();
|
||||||
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
if (buffers[i] != GlStateTracker.buffers[i]) {
|
if (buffers[i] != GlStateTracker.BUFFERS[i] && values[i] != GlBufferType.ELEMENT_ARRAY_BUFFER) {
|
||||||
GlStateManager._glBindBuffer(values[i].glEnum, buffers[i]);
|
GlStateManager._glBindBuffer(values[i].glEnum, buffers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vao != GlStateTracker.vao) {
|
|
||||||
GlStateManager._glBindVertexArray(vao);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (program != GlStateTracker.program) {
|
if (program != GlStateTracker.program) {
|
||||||
GlStateManager._glUseProgram(program);
|
GlStateManager._glUseProgram(program);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class MappedBuffer extends VecBuffer implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
|
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
|
||||||
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
|
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
|
||||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||||
|
@ -20,6 +22,7 @@ public class DrawBuffer {
|
||||||
private ByteBuffer backingBuffer;
|
private ByteBuffer backingBuffer;
|
||||||
private int expectedVertices;
|
private int expectedVertices;
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
public DrawBuffer(RenderType parent) {
|
public DrawBuffer(RenderType parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +42,10 @@ public class DrawBuffer {
|
||||||
|
|
||||||
VertexFormat format = parent.format();
|
VertexFormat format = parent.format();
|
||||||
|
|
||||||
int byteSize = format.getVertexSize() * vertexCount;
|
// Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least
|
||||||
|
// enough buffer space for one more vertex. Rubidium checks for this extra space when popNextBuffer
|
||||||
|
// is called and reallocates the buffer if there is not space for one more vertex.
|
||||||
|
int byteSize = format.getVertexSize() * (vertexCount + 1);
|
||||||
|
|
||||||
if (backingBuffer == null) {
|
if (backingBuffer == null) {
|
||||||
backingBuffer = MemoryTracker.create(byteSize);
|
backingBuffer = MemoryTracker.create(byteSize);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -359,4 +360,14 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
LightUpdater.get(value.world).removeListener(value);
|
LightUpdater.get(value.world).removeListener(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void queueAddAll(Collection<? extends T> objects) {
|
||||||
|
if (!Backend.isOn() || objects.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (queuedAdditions) {
|
||||||
|
queuedAdditions.addAll(objects);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,7 @@ import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public class EntityInstanceManager extends InstanceManager<Entity> {
|
public class EntityInstanceManager extends InstanceManager<Entity> {
|
||||||
|
@ -29,18 +27,13 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean canCreateInstance(Entity entity) {
|
protected boolean canCreateInstance(Entity entity) {
|
||||||
if (!entity.isAlive()) return false;
|
if (!entity.isAlive()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Level world = entity.level;
|
Level world = entity.level;
|
||||||
|
|
||||||
if (Backend.isFlywheelWorld(world)) {
|
return Backend.isFlywheelWorld(world);
|
||||||
BlockPos pos = entity.blockPosition();
|
|
||||||
|
|
||||||
BlockGetter existingChunk = world.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4);
|
|
||||||
|
|
||||||
return existingChunk != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
public void render() {
|
public void render() {
|
||||||
if (invalid()) return;
|
if (invalid()) return;
|
||||||
|
|
||||||
|
// XXX VAO is bound and not reset or restored
|
||||||
vao.bind();
|
vao.bind();
|
||||||
|
|
||||||
renderSetup();
|
renderSetup();
|
||||||
|
@ -69,11 +70,13 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
vao = new GlVertexArray();
|
vao = new GlVertexArray();
|
||||||
|
|
||||||
model = modelAllocator.alloc(modelData, arenaModel -> {
|
model = modelAllocator.alloc(modelData, arenaModel -> {
|
||||||
|
// XXX VAO is bound and not reset or restored
|
||||||
vao.bind();
|
vao.bind();
|
||||||
|
|
||||||
arenaModel.setupState(vao);
|
arenaModel.setupState(vao);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// XXX VAO is bound and not reset or restored
|
||||||
vao.bind();
|
vao.bind();
|
||||||
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
||||||
|
|
||||||
|
@ -108,6 +111,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
removeDeletedInstances();
|
removeDeletedInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX ARRAY_BUFFER is bound and reset
|
||||||
instanceVBO.bind();
|
instanceVBO.bind();
|
||||||
if (!realloc()) {
|
if (!realloc()) {
|
||||||
|
|
||||||
|
|
|
@ -68,15 +68,23 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
return vertexCount;
|
return vertexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Overriden in CrumblingGroup
|
||||||
|
// XXX Runs inside of restore state
|
||||||
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
||||||
type.setupRenderState();
|
type.setupRenderState();
|
||||||
Textures.bindActiveTextures();
|
Textures.bindActiveTextures(); // XXX Changes active unit and bound textures
|
||||||
renderAll(viewProjection, camX, camY, camZ, layer);
|
renderAll(viewProjection, camX, camY, camZ, layer); // XXX May change ARRAY_BUFFER binding (reset or not reset), VAO binding (not reset), shader binding (not reset), call Model.createEBO
|
||||||
type.clearRenderState();
|
type.clearRenderState();
|
||||||
|
// XXX Should texture bindings be reset or restored?
|
||||||
|
// XXX Should the active unit be reset or restored?
|
||||||
|
// XXX Should the VAO binding be reset or restored?
|
||||||
|
// XXX Should the ARRAY_BUFFER binding be reset or restored?
|
||||||
|
// XXX Should the shader binding be reset or restored?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Internal GL state changes are inconsistent; sometimes bindings are reset to 0, sometimes not
|
||||||
protected void renderAll(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
protected void renderAll(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
||||||
initializeInstancers();
|
initializeInstancers(); // XXX May change ARRAY_BUFFER binding (reset or not reset), VAO binding (not reset), call Model.createEBO
|
||||||
|
|
||||||
vertexCount = 0;
|
vertexCount = 0;
|
||||||
instanceCount = 0;
|
instanceCount = 0;
|
||||||
|
@ -88,6 +96,7 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
P program = owner.context.getProgram(ProgramContext.create(entry.getKey()
|
P program = owner.context.getProgram(ProgramContext.create(entry.getKey()
|
||||||
.getProgramSpec(), Formats.POS_TEX_NORMAL, layer));
|
.getProgramSpec(), Formats.POS_TEX_NORMAL, layer));
|
||||||
|
|
||||||
|
// XXX Shader is bound and not reset or restored
|
||||||
program.bind();
|
program.bind();
|
||||||
program.uploadViewProjection(viewProjection);
|
program.uploadViewProjection(viewProjection);
|
||||||
program.uploadCameraPos(camX, camY, camZ);
|
program.uploadCameraPos(camX, camY, camZ);
|
||||||
|
@ -95,7 +104,7 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
setup(program);
|
setup(program);
|
||||||
|
|
||||||
for (GPUInstancer<?> instancer : material.getAllInstancers()) {
|
for (GPUInstancer<?> instancer : material.getAllInstancers()) {
|
||||||
instancer.render();
|
instancer.render(); // XXX May change VAO binding (not reset), ARRAY_BUFFER binding (reset)
|
||||||
vertexCount += instancer.getVertexCount();
|
vertexCount += instancer.getVertexCount();
|
||||||
instanceCount += instancer.getInstanceCount();
|
instanceCount += instancer.getInstanceCount();
|
||||||
}
|
}
|
||||||
|
@ -103,19 +112,19 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeInstancers() {
|
private void initializeInstancers() {
|
||||||
ModelAllocator allocator = getModelAllocator();
|
ModelAllocator allocator = getModelAllocator(); // XXX May change ARRAY_BUFFER binding (not reset)
|
||||||
|
|
||||||
// initialize all uninitialized instancers...
|
// initialize all uninitialized instancers...
|
||||||
for (InstancedMaterial<?> material : materials.values()) {
|
for (InstancedMaterial<?> material : materials.values()) {
|
||||||
for (GPUInstancer<?> instancer : material.uninitialized) {
|
for (GPUInstancer<?> instancer : material.uninitialized) {
|
||||||
instancer.init(allocator);
|
instancer.init(allocator); // XXX May change VAO binding (not reset), ARRAY_BUFFER binding (not reset), call Model.createEBO
|
||||||
}
|
}
|
||||||
material.uninitialized.clear();
|
material.uninitialized.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allocator instanceof ModelPool pool) {
|
if (allocator instanceof ModelPool pool) {
|
||||||
// ...and then flush the model arena in case anything was marked for upload
|
// ...and then flush the model arena in case anything was marked for upload
|
||||||
pool.flush();
|
pool.flush(); // XXX May change ARRAY_BUFFER binding (reset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.MaterialGroup;
|
import com.jozufozu.flywheel.api.MaterialGroup;
|
||||||
import com.jozufozu.flywheel.backend.RenderLayer;
|
import com.jozufozu.flywheel.backend.RenderLayer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||||
import com.jozufozu.flywheel.backend.instancing.Engine;
|
import com.jozufozu.flywheel.backend.instancing.Engine;
|
||||||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||||
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||||
|
@ -74,6 +75,9 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void render(TaskEngine taskEngine, RenderLayerEvent event) {
|
public void render(TaskEngine taskEngine, RenderLayerEvent event) {
|
||||||
|
// XXX Restore state
|
||||||
|
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
||||||
|
|
||||||
double camX;
|
double camX;
|
||||||
double camY;
|
double camY;
|
||||||
double camZ;
|
double camZ;
|
||||||
|
@ -93,6 +97,8 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
getGroupsToRender(event.getLayer()).forEach(group -> group.render(viewProjection, camX, camY, camZ, event.getLayer()));
|
getGroupsToRender(event.getLayer()).forEach(group -> group.render(viewProjection, camX, camY, camZ, event.getLayer()));
|
||||||
|
|
||||||
|
restoreState.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stream<InstancedMaterialGroup<P>> getGroupsToRender(@Nullable RenderLayer layer) {
|
private Stream<InstancedMaterialGroup<P>> getGroupsToRender(@Nullable RenderLayer layer) {
|
||||||
|
|
|
@ -1,25 +1,29 @@
|
||||||
package com.jozufozu.flywheel.backend.model;
|
package com.jozufozu.flywheel.backend.model;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
public class ElementBuffer {
|
public class ElementBuffer {
|
||||||
|
|
||||||
private final GlBuffer buffer;
|
protected final int elementCount;
|
||||||
public final int elementCount;
|
protected final VertexFormat.IndexType eboIndexType;
|
||||||
public final GlNumericType eboIndexType;
|
private final int glBuffer;
|
||||||
|
|
||||||
public ElementBuffer(GlBuffer backing, int elementCount, GlNumericType indexType) {
|
public ElementBuffer(int backing, int elementCount, VertexFormat.IndexType indexType) {
|
||||||
this.buffer = backing;
|
|
||||||
this.eboIndexType = indexType;
|
|
||||||
this.elementCount = elementCount;
|
this.elementCount = elementCount;
|
||||||
|
this.eboIndexType = indexType;
|
||||||
|
this.glBuffer = backing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind() {
|
public void bind() {
|
||||||
buffer.bind();
|
GlBufferType.ELEMENT_ARRAY_BUFFER.bind(glBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unbind() {
|
public int getElementCount() {
|
||||||
buffer.unbind();
|
return elementCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VertexFormat.IndexType getEboIndexType() {
|
||||||
|
return eboIndexType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.jozufozu.flywheel.backend.model;
|
package com.jozufozu.flywheel.backend.model;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
|
|
||||||
public enum FallbackAllocator implements ModelAllocator {
|
public enum FallbackAllocator implements ModelAllocator {
|
||||||
|
@ -7,7 +8,7 @@ public enum FallbackAllocator implements ModelAllocator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferedModel alloc(Model model, Callback allocationCallback) {
|
public BufferedModel alloc(Model model, Callback allocationCallback) {
|
||||||
IndexedModel out = new IndexedModel(model);
|
IndexedModel out = new IndexedModel(model, Formats.POS_TEX_NORMAL);
|
||||||
allocationCallback.onAlloc(out);
|
allocationCallback.onAlloc(out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.jozufozu.flywheel.core.model.Model;
|
||||||
*/
|
*/
|
||||||
public class IndexedModel implements BufferedModel {
|
public class IndexedModel implements BufferedModel {
|
||||||
|
|
||||||
|
protected final VertexType type;
|
||||||
protected final Model model;
|
protected final Model model;
|
||||||
protected final GlPrimitive primitiveMode;
|
protected final GlPrimitive primitiveMode;
|
||||||
protected ElementBuffer ebo;
|
protected ElementBuffer ebo;
|
||||||
|
@ -27,6 +28,11 @@ public class IndexedModel implements BufferedModel {
|
||||||
protected boolean deleted;
|
protected boolean deleted;
|
||||||
|
|
||||||
public IndexedModel(Model model) {
|
public IndexedModel(Model model) {
|
||||||
|
this(model, model.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexedModel(Model model, VertexType type) {
|
||||||
|
this.type = type;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.primitiveMode = GlPrimitive.TRIANGLES;
|
this.primitiveMode = GlPrimitive.TRIANGLES;
|
||||||
|
|
||||||
|
@ -38,7 +44,8 @@ public class IndexedModel implements BufferedModel {
|
||||||
|
|
||||||
// mirror it in system memory, so we can write to it, and upload our model.
|
// mirror it in system memory, so we can write to it, and upload our model.
|
||||||
try (MappedBuffer buffer = vbo.getBuffer()) {
|
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||||
model.writeInto(buffer.unwrap());
|
type.createWriter(buffer.unwrap())
|
||||||
|
.writeVertexList(model.getReader());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.LOGGER.error(String.format("Error uploading model '%s':", model.name()), e);
|
Flywheel.LOGGER.error(String.format("Error uploading model '%s':", model.name()), e);
|
||||||
}
|
}
|
||||||
|
@ -52,27 +59,26 @@ public class IndexedModel implements BufferedModel {
|
||||||
* The VBO/VAO should be bound externally.
|
* The VBO/VAO should be bound externally.
|
||||||
*/
|
*/
|
||||||
public void setupState(GlVertexArray vao) {
|
public void setupState(GlVertexArray vao) {
|
||||||
|
// XXX ARRAY_BUFFER is bound and not reset or restored
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vao.enableArrays(getAttributeCount());
|
vao.enableArrays(getAttributeCount());
|
||||||
vao.bindAttributes(0, getType().getLayout());
|
vao.bindAttributes(0, getType().getLayout());
|
||||||
|
ebo.bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawCall() {
|
public void drawCall() {
|
||||||
ebo.bind();
|
GL20.glDrawElements(primitiveMode.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0);
|
||||||
GL20.glDrawElements(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws many instances of this model, assuming the appropriate state is already bound.
|
* Draws many instances of this model, assuming the appropriate state is already bound.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void drawInstances(int instanceCount) {
|
public void drawInstances(int instanceCount) {
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
|
|
||||||
ebo.bind();
|
GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, instanceCount);
|
||||||
|
|
||||||
GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDeleted() {
|
public boolean isDeleted() {
|
||||||
|
@ -81,7 +87,7 @@ public class IndexedModel implements BufferedModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VertexType getType() {
|
public VertexType getType() {
|
||||||
return model.getType();
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVertexCount() {
|
public int getVertexCount() {
|
||||||
|
|
|
@ -42,6 +42,7 @@ public class ModelPool implements ModelAllocator {
|
||||||
|
|
||||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
|
|
||||||
|
// XXX ARRAY_BUFFER is bound and not reset or restored
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vbo.setGrowthMargin(stride * 64);
|
vbo.setGrowthMargin(stride * 64);
|
||||||
}
|
}
|
||||||
|
@ -68,6 +69,7 @@ public class ModelPool implements ModelAllocator {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
if (anyToRemove) processDeletions();
|
if (anyToRemove) processDeletions();
|
||||||
|
|
||||||
|
// XXX ARRAY_BUFFER is bound and reset
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
if (realloc()) {
|
if (realloc()) {
|
||||||
uploadAll();
|
uploadAll();
|
||||||
|
@ -182,25 +184,25 @@ public class ModelPool implements ModelAllocator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setupState(GlVertexArray vao) {
|
public void setupState(GlVertexArray vao) {
|
||||||
|
// XXX ARRAY_BUFFER is bound and not reset or restored
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vao.enableArrays(getAttributeCount());
|
vao.enableArrays(getAttributeCount());
|
||||||
vao.bindAttributes(0, vertexType.getLayout());
|
vao.bindAttributes(0, vertexType.getLayout());
|
||||||
|
ebo.bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawCall() {
|
public void drawCall() {
|
||||||
GL32.glDrawElementsBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, first);
|
GL32.glDrawElementsBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawInstances(int instanceCount) {
|
public void drawInstances(int instanceCount) {
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
|
|
||||||
ebo.bind();
|
|
||||||
|
|
||||||
//Backend.log.info(StringUtil.args("drawElementsInstancedBaseVertex", GlPrimitive.TRIANGLES, ebo.elementCount, ebo.eboIndexType, 0, instanceCount, first));
|
//Backend.log.info(StringUtil.args("drawElementsInstancedBaseVertex", GlPrimitive.TRIANGLES, ebo.elementCount, ebo.eboIndexType, 0, instanceCount, first));
|
||||||
|
|
||||||
GL32.glDrawElementsInstancedBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount, first);
|
GL32.glDrawElementsInstancedBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.getElementCount(), ebo.getEboIndexType().asGLType, 0, instanceCount, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -58,6 +58,7 @@ public class VBOModel implements BufferedModel {
|
||||||
* The VBO/VAO should be bound externally.
|
* The VBO/VAO should be bound externally.
|
||||||
*/
|
*/
|
||||||
public void setupState(GlVertexArray vao) {
|
public void setupState(GlVertexArray vao) {
|
||||||
|
// XXX ARRAY_BUFFER is bound and not reset or restored
|
||||||
vbo.bind();
|
vbo.bind();
|
||||||
vao.enableArrays(getAttributeCount());
|
vao.enableArrays(getAttributeCount());
|
||||||
vao.bindAttributes(0, getLayout());
|
vao.bindAttributes(0, getLayout());
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class FlwConfig {
|
||||||
protected final Map<String, Option<?>> optionMapView = Collections.unmodifiableMap(optionMap);
|
protected final Map<String, Option<?>> optionMapView = Collections.unmodifiableMap(optionMap);
|
||||||
|
|
||||||
/** Select the backend to use. */
|
/** Select the backend to use. */
|
||||||
public final EnumOption<BackendType> backend = addOption(new EnumOption<>("engine", BackendType.INSTANCING));
|
public final EnumOption<BackendType> backend = addOption(new EnumOption<>("backend", BackendType.INSTANCING));
|
||||||
/** Enable or disable a debug overlay that colors pixels by their normal. */
|
/** Enable or disable a debug overlay that colors pixels by their normal. */
|
||||||
public final BooleanOption debugNormals = addOption(new BooleanOption("debugNormals", false));
|
public final BooleanOption debugNormals = addOption(new BooleanOption("debugNormals", false));
|
||||||
/** Enable or disable instance update limiting with distance. */
|
/** Enable or disable instance update limiting with distance. */
|
||||||
|
|
|
@ -20,12 +20,12 @@ import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
|
||||||
* A helper class for loading and accessing json models.
|
* A helper class for loading and accessing json models.
|
||||||
* <br>
|
* <br>
|
||||||
* Creating a PartialModel will make the associated modelLocation automatically load.
|
* Creating a PartialModel will make the associated modelLocation automatically load.
|
||||||
* PartialModels must be initialized during {@link net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent FMLClientSetupEvent}.
|
* PartialModels must be initialized the mod class constructor.
|
||||||
* <br>
|
* <br>
|
||||||
* Once {@link ModelBakeEvent} finishes, all PartialModels (with valid modelLocations)
|
* Once {@link ModelBakeEvent} finishes, all PartialModels (with valid modelLocations)
|
||||||
* will have their bakedModel fields populated.
|
* will have their bakedModel fields populated.
|
||||||
* <br>
|
* <br>
|
||||||
* Attempting to create a PartialModel after ModelRegistryEvent will cause an error.
|
* Attempting to create a PartialModel after {@link ModelRegistryEvent} will cause an error.
|
||||||
*/
|
*/
|
||||||
public class PartialModel {
|
public class PartialModel {
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,32 @@
|
||||||
package com.jozufozu.flywheel.core;
|
package com.jozufozu.flywheel.core;
|
||||||
|
|
||||||
import java.nio.Buffer;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import java.nio.ByteBuffer;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import java.nio.ByteOrder;
|
import org.lwjgl.opengl.GL32;
|
||||||
import java.util.EnumMap;
|
import org.lwjgl.opengl.GL32C;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.lwjgl.system.MemoryStack;
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
||||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to manage EBOs that index quads as triangles.
|
* A class to manage EBOs that index quads as triangles.
|
||||||
*/
|
*/
|
||||||
public class QuadConverter {
|
public class QuadConverter {
|
||||||
|
|
||||||
public static final int STARTING_CAPACITY = 42; // 255 / 6 = 42
|
|
||||||
|
|
||||||
private static QuadConverter INSTANCE;
|
private static QuadConverter INSTANCE;
|
||||||
|
|
||||||
@Nonnull
|
@NotNull
|
||||||
public static QuadConverter getInstance() {
|
public static QuadConverter getInstance() {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
INSTANCE = new QuadConverter(STARTING_CAPACITY);
|
INSTANCE = new QuadConverter();
|
||||||
}
|
}
|
||||||
|
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
|
@ -42,129 +37,79 @@ public class QuadConverter {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<GlNumericType, GlBuffer> ebos;
|
private final Int2ReferenceMap<ElementBuffer> cache = new Int2ReferenceArrayMap<>();
|
||||||
int[] capacities;
|
private final int ebo;
|
||||||
|
private int quadCapacity;
|
||||||
|
|
||||||
public QuadConverter(int initialCapacity) {
|
public QuadConverter() {
|
||||||
this.ebos = new EnumMap<>(GlNumericType.class);
|
this.ebo = GL32.glGenBuffers();
|
||||||
initCapacities();
|
this.quadCapacity = 0;
|
||||||
|
|
||||||
fillBuffer(initialCapacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ElementBuffer quads2Tris(int quads) {
|
public ElementBuffer quads2Tris(int quads) {
|
||||||
int indexCount = quads * 6;
|
if (quads > quadCapacity) {
|
||||||
GlNumericType type = getSmallestIndexType(indexCount);
|
grow(quads * 2);
|
||||||
|
|
||||||
if (quads > getCapacity(type)) {
|
|
||||||
fillBuffer(quads, indexCount, type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ElementBuffer(getBuffer(type), indexCount, type);
|
return cache.computeIfAbsent(quads, this::createElementBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initCapacities() {
|
@NotNull
|
||||||
this.capacities = new int[GlNumericType.values().length];
|
private ElementBuffer createElementBuffer(int quads) {
|
||||||
|
return new ElementBuffer(ebo, quads * 6, VertexFormat.IndexType.INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCapacity(GlNumericType type) {
|
private void grow(int quads) {
|
||||||
return capacities[type.ordinal()];
|
int byteSize = quads * 6 * GlNumericType.UINT.getByteWidth();
|
||||||
}
|
final long ptr = MemoryUtil.nmemAlloc(byteSize);
|
||||||
|
|
||||||
private void updateCapacity(GlNumericType type, int capacity) {
|
fillBuffer(ptr, quads);
|
||||||
if (getCapacity(type) < capacity) {
|
|
||||||
capacities[type.ordinal()] = capacity;
|
// XXX ARRAY_BUFFER is bound and reset
|
||||||
}
|
final var bufferType = GlBufferType.ARRAY_BUFFER;
|
||||||
|
final int oldBuffer = bufferType.getBoundBuffer();
|
||||||
|
bufferType.bind(ebo);
|
||||||
|
GL32C.nglBufferData(bufferType.glEnum, byteSize, ptr, GlBufferUsage.STATIC_DRAW.glEnum);
|
||||||
|
bufferType.bind(oldBuffer);
|
||||||
|
|
||||||
|
MemoryUtil.nmemFree(ptr);
|
||||||
|
|
||||||
|
this.quadCapacity = quads;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
ebos.values()
|
GL32.glDeleteBuffers(ebo);
|
||||||
.forEach(GlBuffer::delete);
|
this.cache.clear();
|
||||||
ebos.clear();
|
this.quadCapacity = 0;
|
||||||
initCapacities();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillBuffer(int quads) {
|
private void fillBuffer(long ptr, int quads) {
|
||||||
int indexCount = quads * 6;
|
int numVertices = 4 * quads;
|
||||||
|
int baseVertex = 0;
|
||||||
|
while (baseVertex < numVertices) {
|
||||||
|
writeQuadIndicesUnsafe(ptr, baseVertex);
|
||||||
|
|
||||||
fillBuffer(quads, indexCount, getSmallestIndexType(indexCount));
|
baseVertex += 4;
|
||||||
}
|
ptr += 6 * 4;
|
||||||
|
|
||||||
private void fillBuffer(int quads, int indexCount, GlNumericType type) {
|
|
||||||
MemoryStack stack = MemoryStack.stackPush();
|
|
||||||
int bytes = indexCount * type.getByteWidth();
|
|
||||||
|
|
||||||
ByteBuffer indices;
|
|
||||||
if (bytes > stack.getSize()) {
|
|
||||||
indices = MemoryUtil.memAlloc(bytes); // not enough space on the preallocated stack
|
|
||||||
} else {
|
|
||||||
stack.push();
|
|
||||||
indices = stack.malloc(bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indices.order(ByteOrder.nativeOrder());
|
|
||||||
|
|
||||||
fillBuffer(indices, type, quads);
|
|
||||||
|
|
||||||
GlBuffer buffer = getBuffer(type);
|
|
||||||
|
|
||||||
buffer.bind();
|
|
||||||
buffer.upload(indices);
|
|
||||||
buffer.unbind();
|
|
||||||
|
|
||||||
if (bytes > stack.getSize()) {
|
|
||||||
MemoryUtil.memFree(indices);
|
|
||||||
} else {
|
|
||||||
stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCapacity(type, quads);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillBuffer(ByteBuffer indices, GlNumericType type, int quads) {
|
private void writeQuadIndicesUnsafe(long ptr, int baseVertex) {
|
||||||
for (int i = 0, max = 4 * quads; i < max; i += 4) {
|
// triangle a
|
||||||
// triangle a
|
MemoryUtil.memPutInt(ptr, baseVertex);
|
||||||
type.castAndBuffer(indices, i);
|
MemoryUtil.memPutInt(ptr + 4, baseVertex + 1);
|
||||||
type.castAndBuffer(indices, i + 1);
|
MemoryUtil.memPutInt(ptr + 8, baseVertex + 2);
|
||||||
type.castAndBuffer(indices, i + 2);
|
// triangle b
|
||||||
// triangle b
|
MemoryUtil.memPutInt(ptr + 12, baseVertex);
|
||||||
type.castAndBuffer(indices, i);
|
MemoryUtil.memPutInt(ptr + 16, baseVertex + 2);
|
||||||
type.castAndBuffer(indices, i + 2);
|
MemoryUtil.memPutInt(ptr + 20, baseVertex + 3);
|
||||||
type.castAndBuffer(indices, i + 3);
|
|
||||||
}
|
|
||||||
((Buffer) indices).flip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GlBuffer getBuffer(GlNumericType type) {
|
// make sure this gets reset first, so it has a chance to repopulate
|
||||||
return ebos.computeIfAbsent(type, $ -> new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given the needed number of indices, what is the smallest bit width type that can index everything? <br>
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* | indexCount | type |
|
|
||||||
* |--------------|-------|
|
|
||||||
* | [0, 255) | byte |
|
|
||||||
* | [256, 65536) | short |
|
|
||||||
* | [65537, ) | int |
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
private static GlNumericType getSmallestIndexType(int indexCount) {
|
|
||||||
// indexCount = indexCount >>> 8;
|
|
||||||
// if (indexCount == 0) {
|
|
||||||
// return GlNumericType.UBYTE;
|
|
||||||
// }
|
|
||||||
// indexCount = indexCount >>> 8;
|
|
||||||
// if (indexCount == 0) {
|
|
||||||
// return GlNumericType.USHORT;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return GlNumericType.UINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure this gets reset first so it has a chance to repopulate
|
|
||||||
public static void onRendererReload(ReloadRenderersEvent event) {
|
public static void onRendererReload(ReloadRenderersEvent event) {
|
||||||
if (INSTANCE != null) INSTANCE.delete();
|
if (INSTANCE != null) {
|
||||||
|
INSTANCE.delete();
|
||||||
|
INSTANCE = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ public class CrumblingGroup<P extends CrumblingProgram> extends InstancedMateria
|
||||||
super(owner, type);
|
super(owner, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX See notes of overriden method
|
||||||
@Override
|
@Override
|
||||||
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
|
||||||
type.setupRenderState();
|
type.setupRenderState();
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||||
import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine;
|
import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine;
|
||||||
|
@ -16,6 +17,7 @@ import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
|
||||||
import com.jozufozu.flywheel.util.Lazy;
|
import com.jozufozu.flywheel.util.Lazy;
|
||||||
import com.jozufozu.flywheel.util.Pair;
|
import com.jozufozu.flywheel.util.Pair;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
@ -30,6 +32,7 @@ import net.minecraft.client.resources.model.ModelBakery;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.server.level.BlockDestructionProgress;
|
import net.minecraft.server.level.BlockDestructionProgress;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for rendering the block breaking overlay for instanced block entities.
|
* Responsible for rendering the block breaking overlay for instanced block entities.
|
||||||
|
@ -48,13 +51,21 @@ public class CrumblingRenderer {
|
||||||
INVALIDATOR = state.second();
|
INVALIDATOR = state.second();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renderBreaking(RenderLayerEvent event) {
|
public static void render(ClientLevel level, Camera camera, PoseStack stack) {
|
||||||
if (!Backend.canUseInstancing(event.getWorld())) return;
|
if (!Backend.canUseInstancing(level)) return;
|
||||||
|
|
||||||
Int2ObjectMap<List<BlockEntity>> activeStages = getActiveStageBlockEntities(event.getWorld());
|
|
||||||
|
|
||||||
|
Int2ObjectMap<List<BlockEntity>> activeStages = getActiveStageBlockEntities(level);
|
||||||
if (activeStages.isEmpty()) return;
|
if (activeStages.isEmpty()) return;
|
||||||
|
|
||||||
|
Vec3 cameraPos = camera.getPosition();
|
||||||
|
|
||||||
|
// XXX Restore state
|
||||||
|
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
||||||
|
CrumblingRenderer.renderBreaking(activeStages, new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z));
|
||||||
|
restoreState.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void renderBreaking(Int2ObjectMap<List<BlockEntity>> activeStages, RenderLayerEvent event) {
|
||||||
State state = STATE.get();
|
State state = STATE.get();
|
||||||
InstanceManager<BlockEntity> instanceManager = state.instanceManager;
|
InstanceManager<BlockEntity> instanceManager = state.instanceManager;
|
||||||
InstancingEngine<CrumblingProgram> materials = state.materialManager;
|
InstancingEngine<CrumblingProgram> materials = state.materialManager;
|
||||||
|
@ -71,6 +82,7 @@ public class CrumblingRenderer {
|
||||||
|
|
||||||
instanceManager.beginFrame(SerialTaskEngine.INSTANCE, info);
|
instanceManager.beginFrame(SerialTaskEngine.INSTANCE, info);
|
||||||
|
|
||||||
|
// XXX Each call applies another restore state even though we are already inside of a restore state
|
||||||
materials.render(SerialTaskEngine.INSTANCE, event);
|
materials.render(SerialTaskEngine.INSTANCE, event);
|
||||||
|
|
||||||
instanceManager.invalidate();
|
instanceManager.invalidate();
|
||||||
|
@ -78,6 +90,9 @@ public class CrumblingRenderer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Inconsistent GL state cleanup
|
||||||
|
// If texture binding and active unit need to be restored, store them in variables before GL state is changed
|
||||||
|
// instead of guessing that unit 0 and crumbling tex 0 are correct
|
||||||
GlTextureUnit.T0.makeActive();
|
GlTextureUnit.T0.makeActive();
|
||||||
AbstractTexture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
|
AbstractTexture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
|
||||||
if (breaking != null) RenderSystem.bindTexture(breaking.getId());
|
if (breaking != null) RenderSystem.bindTexture(breaking.getId());
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.jozufozu.flywheel.core.hardcoded;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
||||||
|
@ -51,4 +52,20 @@ public class ModelPart implements Model {
|
||||||
public VertexList getReader() {
|
public VertexList getReader() {
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexType getType() {
|
||||||
|
return Formats.POS_TEX_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
if (reader instanceof AutoCloseable closeable) {
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
|
@ -12,10 +13,8 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||||
* A model of a single block.
|
* A model of a single block.
|
||||||
*/
|
*/
|
||||||
public class BlockModel implements Model {
|
public class BlockModel implements Model {
|
||||||
private static final PoseStack IDENTITY = new PoseStack();
|
|
||||||
|
|
||||||
private final VertexList reader;
|
private final VertexList reader;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public BlockModel(BlockState state) {
|
public BlockModel(BlockState state) {
|
||||||
|
@ -25,12 +24,21 @@ public class BlockModel implements Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModel(BakedModel model, BlockState referenceState) {
|
public BlockModel(BakedModel model, BlockState referenceState) {
|
||||||
this(model, referenceState, IDENTITY);
|
this(new BakedModelBuilder(model).withReferenceState(referenceState), referenceState.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) {
|
public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) {
|
||||||
reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilder(model, referenceState, ms));
|
this(new BakedModelBuilder(model).withReferenceState(referenceState)
|
||||||
name = referenceState.toString();
|
.withPoseStack(ms), referenceState.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockModel(Bufferable bufferable, String name) {
|
||||||
|
this(bufferable.build(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockModel(ShadeSeparatedBufferBuilder bufferBuilder, String name) {
|
||||||
|
this.name = name;
|
||||||
|
reader = Formats.BLOCK.createReader(bufferBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,4 +55,20 @@ public class BlockModel implements Model {
|
||||||
public VertexList getReader() {
|
public VertexList getReader() {
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VertexType getType() {
|
||||||
|
return Formats.BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
if (reader instanceof AutoCloseable closeable) {
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.nio.ByteBuffer;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
|
||||||
import com.jozufozu.flywheel.core.QuadConverter;
|
import com.jozufozu.flywheel.core.QuadConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,10 +41,9 @@ public interface Model {
|
||||||
*/
|
*/
|
||||||
int vertexCount();
|
int vertexCount();
|
||||||
|
|
||||||
default VertexType getType() {
|
VertexType getType();
|
||||||
return Formats.POS_TEX_NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// XXX Since this is public API (technically) we cannot make assumptions about what GL state this method can use or modify unless a contract is established.
|
||||||
/**
|
/**
|
||||||
* Create an element buffer object that indexes the vertices of this model.
|
* Create an element buffer object that indexes the vertices of this model.
|
||||||
*
|
*
|
||||||
|
@ -61,6 +59,8 @@ public interface Model {
|
||||||
.quads2Tris(vertexCount() / 4);
|
.quads2Tris(vertexCount() / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void delete();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size in bytes that this model's data takes up.
|
* The size in bytes that this model's data takes up.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
||||||
|
|
||||||
public class WorldModel implements Model {
|
|
||||||
|
|
||||||
private final VertexList reader;
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
public WorldModel(BufferBuilder bufferBuilder, String name) {
|
|
||||||
this.reader = Formats.BLOCK.createReader(bufferBuilder);
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VertexType getType() {
|
|
||||||
return Formats.BLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int vertexCount() {
|
|
||||||
return reader.getVertexCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VertexList getReader() {
|
|
||||||
return reader;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -86,7 +86,7 @@ public final class WorldModelBuilder implements Bufferable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorldModel intoMesh(String name) {
|
public BlockModel intoMesh(String name) {
|
||||||
return new WorldModel(ModelUtil.getBufferBuilder(this), name);
|
return new BlockModel(ModelUtil.getBufferBuilder(this), name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
||||||
|
|
||||||
public abstract class AbstractVertexList implements VertexList, AutoCloseable {
|
public abstract class AbstractVertexList implements VertexList, AutoCloseable {
|
||||||
|
|
||||||
|
@ -22,15 +21,6 @@ public abstract class AbstractVertexList implements VertexList, AutoCloseable {
|
||||||
init(copyFrom);
|
init(copyFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractVertexList(BufferBuilder builder) {
|
|
||||||
var pair = builder.popNextBuffer();
|
|
||||||
ByteBuffer copyFrom = pair.getSecond();
|
|
||||||
this.contents = MemoryTracker.create(copyFrom.capacity());
|
|
||||||
this.vertexCount = pair.getFirst().vertexCount();
|
|
||||||
this.base = MemoryUtil.memAddress(this.contents);
|
|
||||||
init(copyFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(ByteBuffer copyFrom) {
|
private void init(ByteBuffer copyFrom) {
|
||||||
this.contents.order(copyFrom.order());
|
this.contents.order(copyFrom.order());
|
||||||
this.contents.put(copyFrom);
|
this.contents.put(copyFrom);
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
package com.jozufozu.flywheel.core.vertex;
|
package com.jozufozu.flywheel.core.vertex;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
|
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
|
||||||
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
|
|
||||||
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
|
|
||||||
import com.jozufozu.flywheel.util.RenderMath;
|
import com.jozufozu.flywheel.util.RenderMath;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
||||||
|
|
||||||
public class BlockVertexList extends AbstractVertexList {
|
public class BlockVertexList extends AbstractVertexList {
|
||||||
|
|
||||||
private final int stride;
|
private final int stride;
|
||||||
|
|
||||||
public BlockVertexList(BufferBuilder builder) {
|
public BlockVertexList(ByteBuffer copyFrom, int vertexCount, int stride) {
|
||||||
super(builder);
|
super(copyFrom, vertexCount);
|
||||||
this.stride = BufferBuilderHelper.getVertexFormat(builder)
|
this.stride = stride;
|
||||||
.getVertexSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -94,9 +92,9 @@ public class BlockVertexList extends AbstractVertexList {
|
||||||
|
|
||||||
private final int unshadedStartVertex;
|
private final int unshadedStartVertex;
|
||||||
|
|
||||||
public Shaded(ShadeSeparatedBufferBuilder builder) {
|
public Shaded(ByteBuffer copyFrom, int vertexCount, int stride, int unshadedStartVertex) {
|
||||||
super(builder);
|
super(copyFrom, vertexCount, stride);
|
||||||
unshadedStartVertex = builder.getUnshadedStartVertex();
|
this.unshadedStartVertex = unshadedStartVertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,7 +13,6 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
public class ForgeEvents {
|
public class ForgeEvents {
|
||||||
|
|
||||||
public static void addToDebugScreen(List<String> right) {
|
public static void addToDebugScreen(List<String> right) {
|
||||||
|
|
||||||
InstancedRenderDispatcher.getDebugString(right);
|
InstancedRenderDispatcher.getDebugString(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package com.jozufozu.flywheel.mixin;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
|
||||||
import com.mojang.blaze3d.vertex.BufferUploader;
|
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
|
||||||
|
|
||||||
@Mixin(BufferUploader.class)
|
|
||||||
public class BufferUploaderMixin {
|
|
||||||
|
|
||||||
@Shadow
|
|
||||||
@Nullable
|
|
||||||
private static VertexFormat lastFormat;
|
|
||||||
|
|
||||||
@Inject(method = "reset", at = @At("HEAD"))
|
|
||||||
private static void stopBufferUploaderFromClearingBufferStateIfNothingIsBound(CallbackInfo ci) {
|
|
||||||
// Trust our tracker over BufferUploader's.
|
|
||||||
if (GlStateTracker.getVertexArray() == 0) {
|
|
||||||
lastFormat = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.jozufozu.flywheel.mixin;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import net.minecraft.client.main.Main;
|
||||||
|
|
||||||
|
@Mixin(value = Main.class, remap = false)
|
||||||
|
public class ClientMainMixin {
|
||||||
|
|
||||||
|
@Inject(method = "main", at = @At("HEAD"))
|
||||||
|
private static void injectRenderDoc(CallbackInfo ci) {
|
||||||
|
// Only try to load RenderDoc if a system property is set.
|
||||||
|
if (System.getProperty("flw.loadRenderDoc") == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
System.loadLibrary("renderdoc");
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
// Oh well, we tried.
|
||||||
|
// On Windows, RenderDoc installs to "C:\Program Files\RenderDoc\"
|
||||||
|
System.err.println("Is RenderDoc in your PATH?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,21 +3,17 @@ package com.jozufozu.flywheel.mixin;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Group;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||||
import com.jozufozu.flywheel.fabric.event.FlywheelEvents;
|
import com.jozufozu.flywheel.fabric.event.FlywheelEvents;
|
||||||
import com.mojang.blaze3d.vertex.BufferUploader;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
|
|
||||||
|
@ -31,7 +27,6 @@ import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.culling.Frustum;
|
import net.minecraft.client.renderer.culling.Frustum;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
|
|
||||||
@Mixin(value = LevelRenderer.class, priority = 1001) // Higher priority to go after sodium
|
@Mixin(value = LevelRenderer.class, priority = 1001) // Higher priority to go after sodium
|
||||||
public class LevelRendererMixin {
|
public class LevelRendererMixin {
|
||||||
|
@ -48,41 +43,9 @@ public class LevelRendererMixin {
|
||||||
FlywheelEvents.BEGIN_FRAME.invoker().handleEvent(new BeginFrameEvent(level, camera, frustum));
|
FlywheelEvents.BEGIN_FRAME.invoker().handleEvent(new BeginFrameEvent(level, camera, frustum));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
|
||||||
private boolean flywheel$LayerRendered;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This only gets injected if renderChunkLayer is not Overwritten
|
|
||||||
*/
|
|
||||||
@Group(name = "flywheel$renderLayer", min = 1, max = 2)
|
|
||||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ShaderInstance;clear()V"), method = "renderChunkLayer")
|
|
||||||
private void renderLayer(RenderType type, PoseStack stack, double camX, double camY, double camZ, Matrix4f p_172999_, CallbackInfo ci) {
|
|
||||||
flywheel$renderLayer(type, stack, camX, camY, camZ);
|
|
||||||
flywheel$LayerRendered = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This always gets injected.
|
|
||||||
*/
|
|
||||||
@Group(name = "flywheel$renderLayer")
|
|
||||||
@Inject(at = @At("TAIL"), method = "renderChunkLayer")
|
@Inject(at = @At("TAIL"), method = "renderChunkLayer")
|
||||||
private void renderLayerSodium(RenderType type, PoseStack stack, double camX, double camY, double camZ, Matrix4f p_172999_, CallbackInfo ci) {
|
private void renderLayer(RenderType type, PoseStack stack, double camX, double camY, double camZ, Matrix4f projection, CallbackInfo ci) {
|
||||||
if (!flywheel$LayerRendered) {
|
|
||||||
flywheel$renderLayer(type, stack, camX, camY, camZ);
|
|
||||||
}
|
|
||||||
flywheel$LayerRendered = false;
|
|
||||||
BufferUploader.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unique
|
|
||||||
private void flywheel$renderLayer(RenderType type, PoseStack stack, double camX, double camY, double camZ) {
|
|
||||||
RenderBuffers renderBuffers = this.renderBuffers;
|
|
||||||
|
|
||||||
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
|
||||||
|
|
||||||
FlywheelEvents.RENDER_LAYER.invoker().handleEvent(new RenderLayerEvent(level, type, stack, renderBuffers, camX, camY, camZ));
|
FlywheelEvents.RENDER_LAYER.invoker().handleEvent(new RenderLayerEvent(level, type, stack, renderBuffers, camX, camY, camZ));
|
||||||
|
|
||||||
restoreState.restore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(at = @At("TAIL"), method = "allChanged")
|
@Inject(at = @At("TAIL"), method = "allChanged")
|
||||||
|
@ -92,17 +55,10 @@ public class LevelRendererMixin {
|
||||||
FlywheelEvents.RELOAD_RENDERERS.invoker().handleEvent(new ReloadRenderersEvent(level));
|
FlywheelEvents.RELOAD_RENDERERS.invoker().handleEvent(new ReloadRenderersEvent(level));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;checkPoseStack(Lcom/mojang/blaze3d/vertex/PoseStack;)V", ordinal = 2 // after the game renders the breaking overlay normally
|
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;checkPoseStack(Lcom/mojang/blaze3d/vertex/PoseStack;)V", ordinal = 2 // after the game renders the breaking overlay normally
|
||||||
), method = "renderLevel")
|
), method = "renderLevel")
|
||||||
private void renderBlockBreaking(PoseStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, Camera info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) {
|
private void renderBlockBreaking(PoseStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) {
|
||||||
if (!Backend.isOn()) return;
|
CrumblingRenderer.render(level, camera, stack);
|
||||||
|
|
||||||
Vec3 cameraPos = info.getPosition();
|
|
||||||
|
|
||||||
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
|
|
||||||
CrumblingRenderer.renderBreaking(new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z));
|
|
||||||
restoreState.restore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instancing
|
// Instancing
|
||||||
|
|
|
@ -14,11 +14,14 @@ import net.minecraft.client.renderer.RenderType;
|
||||||
public class RenderTypeMixin implements RenderTypeExtension {
|
public class RenderTypeMixin implements RenderTypeExtension {
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private final DrawBuffer flywheel$drawBuffer = new DrawBuffer((RenderType) (Object) this);
|
private DrawBuffer flywheel$drawBuffer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public DrawBuffer flywheel$getDrawBuffer() {
|
public DrawBuffer flywheel$getDrawBuffer() {
|
||||||
|
if (flywheel$drawBuffer == null) {
|
||||||
|
flywheel$drawBuffer = new DrawBuffer((RenderType) (Object) this);
|
||||||
|
}
|
||||||
return flywheel$drawBuffer;
|
return flywheel$drawBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.mixin;
|
package com.jozufozu.flywheel.mixin.instancemanage;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.mixin;
|
package com.jozufozu.flywheel.mixin.instancemanage;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.mixin;
|
package com.jozufozu.flywheel.mixin.instancemanage;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
|
@ -7,16 +7,13 @@
|
||||||
"BlockEntityRenderDispatcherAccessor",
|
"BlockEntityRenderDispatcherAccessor",
|
||||||
"BlockEntityTypeMixin",
|
"BlockEntityTypeMixin",
|
||||||
"BufferBuilderMixin",
|
"BufferBuilderMixin",
|
||||||
"BufferUploaderMixin",
|
|
||||||
"CameraMixin",
|
"CameraMixin",
|
||||||
"ClientLevelMixin",
|
"ClientLevelMixin",
|
||||||
"ChunkRebuildHooksMixin",
|
"ClientMainMixin",
|
||||||
"EntityTypeMixin",
|
"EntityTypeMixin",
|
||||||
"FixFabulousDepthMixin",
|
"FixFabulousDepthMixin",
|
||||||
"FrustumMixin",
|
"FrustumMixin",
|
||||||
"GlStateManagerMixin",
|
"GlStateManagerMixin",
|
||||||
"InstanceAddMixin",
|
|
||||||
"InstanceRemoveMixin",
|
|
||||||
"LevelRendererAccessor",
|
"LevelRendererAccessor",
|
||||||
"LevelRendererMixin",
|
"LevelRendererMixin",
|
||||||
"PausedPartialTickAccessor",
|
"PausedPartialTickAccessor",
|
||||||
|
@ -24,6 +21,9 @@
|
||||||
"RenderTypeMixin",
|
"RenderTypeMixin",
|
||||||
"atlas.AtlasDataMixin",
|
"atlas.AtlasDataMixin",
|
||||||
"atlas.SheetDataAccessor",
|
"atlas.SheetDataAccessor",
|
||||||
|
"instancemanage.ChunkRebuildHooksMixin",
|
||||||
|
"instancemanage.InstanceAddMixin",
|
||||||
|
"instancemanage.InstanceRemoveMixin",
|
||||||
"light.LightUpdateMixin",
|
"light.LightUpdateMixin",
|
||||||
"light.NetworkLightUpdateMixin",
|
"light.NetworkLightUpdateMixin",
|
||||||
"matrix.Matrix3fMixin",
|
"matrix.Matrix3fMixin",
|
||||||
|
|
Loading…
Reference in a new issue