Merge remote-tracking branch 'origin/1.18/dev' into 1.18/fabric/dev

Conflicts:
	src/main/java/com/jozufozu/flywheel/mixin/RenderHooksMixin.java
	src/main/resources/flywheel.mixins.json
This commit is contained in:
PepperCode1 2022-01-06 14:03:34 -08:00
commit 05c6d9d685
22 changed files with 192 additions and 73 deletions

View file

@ -30,7 +30,7 @@ public interface DynamicInstance extends Instance {
* <br> You might want to opt out of this if you want your animations to remain smooth * <br> You might want to opt out of this if you want your animations to remain smooth
* even when far away from the camera. It is recommended to keep this as is, however. * even when far away from the camera. It is recommended to keep this as is, however.
* *
* @return <code>true</code> if your instance should be slow ticked. * @return {@code true} if your instance should be slow ticked.
*/ */
default boolean decreaseFramerateWithDistance() { default boolean decreaseFramerateWithDistance() {
return true; return true;

View file

@ -38,7 +38,7 @@ public interface TickableInstance extends Instance {
* <br> You might want to opt out of this if you want your animations to remain smooth * <br> You might want to opt out of this if you want your animations to remain smooth
* even when far away from the camera. It is recommended to keep this as is, however. * even when far away from the camera. It is recommended to keep this as is, however.
* *
* @return <code>true</code> if your instance should be slow ticked. * @return {@code true} if your instance should be slow ticked.
*/ */
default boolean decreaseTickRateWithDistance() { default boolean decreaseTickRateWithDistance() {
return true; return true;

View file

@ -1,10 +1,6 @@
package com.jozufozu.flywheel.backend; package com.jozufozu.flywheel.backend;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -55,7 +51,7 @@ public class Backend {
* (Meshlet, MDI, GL31 Draw Instanced are planned), this will name which one is in use. * (Meshlet, MDI, GL31 Draw Instanced are planned), this will name which one is in use.
*/ */
public String getBackendDescriptor() { public String getBackendDescriptor() {
return engine.getProperName(); return engine == null ? "" : engine.getProperName();
} }
public FlwEngine getEngine() { public FlwEngine getEngine() {

View file

@ -4,7 +4,11 @@ import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Optional; import java.util.Optional;
import java.util.function.BooleanSupplier;
import com.jozufozu.flywheel.util.Lazy;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -15,6 +19,23 @@ public class OptifineHandler {
private static Package optifine; private static Package optifine;
private static OptifineHandler handler; private static OptifineHandler handler;
private static final Lazy<BooleanSupplier> isShadowPass = Lazy.of(() -> {
try {
Class<?> ofShaders = Class.forName("net.optifine.shaders.Shaders");
Field field = ofShaders.getDeclaredField("isShadowPass");
field.setAccessible(true);
return () -> {
try {
return field.getBoolean(null);
} catch (IllegalAccessException ignored) {
return false;
}
};
} catch (Exception ignored) {
return () -> false;
}
});
public final boolean usingShaders; public final boolean usingShaders;
public OptifineHandler(boolean usingShaders) { public OptifineHandler(boolean usingShaders) {
@ -40,6 +61,10 @@ public class OptifineHandler {
.orElse(false); .orElse(false);
} }
public static boolean isShadowPass() {
return isShadowPass.get().getAsBoolean();
}
public static void init() { public static void init() {
optifine = Package.getPackage(OPTIFINE_ROOT_PACKAGE); optifine = Package.getPackage(OPTIFINE_ROOT_PACKAGE);

View file

@ -12,10 +12,17 @@ public class GlVertexArray extends GlObject {
setHandle(GlStateManager._glGenVertexArrays()); setHandle(GlStateManager._glGenVertexArrays());
} }
public static void bind(int vao) {
GlStateManager._glBindVertexArray(vao);
BufferUploaderAccessor.flywheel$setLastVAO(vao);
}
public void bind() { public void bind() {
int handle = handle(); bind(handle());
GlStateManager._glBindVertexArray(handle); }
BufferUploaderAccessor.flywheel$setLastVAO(handle);
public static int getBoundVertexArray() {
return BufferUploaderAccessor.flywheel$getLastVAO();
} }
public static void unbind() { public static void unbind() {

View file

@ -50,4 +50,12 @@ public enum GlBufferType {
case GL15C.GL_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$setLastVBO(0); case GL15C.GL_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$setLastVBO(0);
} }
} }
public int getBoundBuffer() {
return switch (this.glEnum) {
case GL15C.GL_ELEMENT_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$getLastEBO();
case GL15C.GL_ARRAY_BUFFER -> BufferUploaderAccessor.flywheel$getLastVBO();
default -> -1;
};
}
} }

View file

@ -4,7 +4,7 @@ import org.lwjgl.opengl.GLCapabilities;
/** /**
* This interface should be implemented by enums such that the * This interface should be implemented by enums such that the
* last defined variant <em>always</em> returns <code>true</code>. * last defined variant <em>always</em> returns {@code true}
*/ */
public interface GlVersioned { public interface GlVersioned {
/** /**

View file

@ -65,13 +65,13 @@ public abstract class AbstractInstance implements Instance, LightListener {
* When an instance is reset, the instance is deleted and re-created. * When an instance is reset, the instance is deleted and re-created.
* *
* <p> * <p>
* Just before {@link #update()} would be called, <code>shouldReset()</code> is checked. * Just before {@link #update()} would be called, {@code shouldReset()} is checked.
* If this function returns <code>true</code>, then this instance will be {@link #remove removed}, * If this function returns {@code true}, then this instance will be {@link #remove removed},
* and another instance will be constructed to replace it. This allows for more sane resource * and another instance will be constructed to replace it. This allows for more sane resource
* acquisition compared to trying to update everything within the lifetime of an instance. * acquisition compared to trying to update everything within the lifetime of an instance.
* </p> * </p>
* *
* @return <code>true</code> if this instance should be discarded and refreshed. * @return {@code true} if this instance should be discarded and refreshed.
*/ */
public boolean shouldReset() { public boolean shouldReset() {
return false; return false;

View file

@ -90,12 +90,12 @@ public class InstanceWorld {
* </p> * </p>
*/ */
public void beginFrame(BeginFrameEvent event) { public void beginFrame(BeginFrameEvent event) {
engine.beginFrame(event.getInfo()); engine.beginFrame(event.getCamera());
taskEngine.syncPoint(); taskEngine.syncPoint();
blockEntityInstanceManager.beginFrame(taskEngine, event.getInfo()); blockEntityInstanceManager.beginFrame(taskEngine, event.getCamera());
entityInstanceManager.beginFrame(taskEngine, event.getInfo()); entityInstanceManager.beginFrame(taskEngine, event.getCamera());
} }
/** /**

View file

@ -48,12 +48,12 @@ public abstract class BlockEntityInstance<T extends BlockEntity> extends Abstrac
} }
/** /**
* Just before {@link #update()} would be called, <code>shouldReset()</code> is checked. * Just before {@link #update()} would be called, {@code shouldReset()} is checked.
* If this function returns <code>true</code>, then this instance will be {@link #remove removed}, * If this function returns {@code true}, then this instance will be {@link #remove removed},
* and another instance will be constructed to replace it. This allows for more sane resource * and another instance will be constructed to replace it. This allows for more sane resource
* acquisition compared to trying to update everything within the lifetime of an instance. * acquisition compared to trying to update everything within the lifetime of an instance.
* *
* @return <code>true</code> if this instance should be discarded and refreshed. * @return {@code true} if this instance should be discarded and refreshed.
*/ */
public boolean shouldReset() { public boolean shouldReset() {
return blockEntity.getBlockState() != blockState; return blockEntity.getBlockState() != blockState;

View file

@ -80,6 +80,10 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
*/ */
@Override @Override
public void render(TaskEngine taskEngine, RenderLayerEvent event) { public void render(TaskEngine taskEngine, RenderLayerEvent event) {
int ebo = GlBufferType.ELEMENT_ARRAY_BUFFER.getBoundBuffer();
int vbo = GlBufferType.ARRAY_BUFFER.getBoundBuffer();
int vao = GlVertexArray.getBoundVertexArray();
double camX; double camX;
double camY; double camY;
double camZ; double camZ;
@ -100,9 +104,9 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
getGroupsToRender(event.getLayer()).forEach(group -> group.render(viewProjection, camX, camY, camZ)); getGroupsToRender(event.getLayer()).forEach(group -> group.render(viewProjection, camX, camY, camZ));
GlBufferType.ELEMENT_ARRAY_BUFFER.unbind(); GlBufferType.ELEMENT_ARRAY_BUFFER.bind(ebo);
GlBufferType.ARRAY_BUFFER.unbind(); GlBufferType.ARRAY_BUFFER.bind(vbo);
GlVertexArray.unbind(); GlVertexArray.bind(vao);
} }
private Stream<InstancedMaterialGroup<P>> getGroupsToRender(@Nullable RenderLayer layer) { private Stream<InstancedMaterialGroup<P>> getGroupsToRender(@Nullable RenderLayer layer) {

View file

@ -217,7 +217,7 @@ public class SourceFile {
} }
/** /**
* Scan the source for <code>#use "..."</code> directives. * Scan the source for {@code #use "..."} directives.
* Records the contents of the directive into an {@link Import} object, and marks the directive for elision. * Records the contents of the directive into an {@link Import} object, and marks the directive for elision.
* @param elisions * @param elisions
*/ */

View file

@ -0,0 +1,16 @@
package com.jozufozu.flywheel.core;
import net.minecraft.client.Camera;
public class LastActiveCamera {
private static Camera camera;
public static void _setActiveCamera(Camera camera) {
LastActiveCamera.camera = camera;
}
public static Camera getActiveCamera() {
return camera;
}
}

View file

@ -14,14 +14,14 @@ public interface FlatLit<D extends InstanceData & FlatLit<D>> {
/** /**
* @param blockLight An integer in the range [0, 15] representing the * @param blockLight An integer in the range [0, 15] representing the
* amount of block light this instance should receive. * amount of block light this instance should receive.
* @return <code>this</code> * @return {@code this}
*/ */
D setBlockLight(int blockLight); D setBlockLight(int blockLight);
/** /**
* @param skyLight An integer in the range [0, 15] representing the * @param skyLight An integer in the range [0, 15] representing the
* amount of sky light this instance should receive. * amount of sky light this instance should receive.
* @return <code>this</code> * @return {@code this}
*/ */
D setSkyLight(int skyLight); D setSkyLight(int skyLight);

View file

@ -16,7 +16,7 @@ public class WorldModel implements Model {
private final String name; private final String name;
/** /**
* It is expected that <code>renderWorld.getShade(...)</code> returns a constant. * It is expected that {@code renderWorld.getShade(...)} returns a constant.
*/ */
public WorldModel(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, String name) { public WorldModel(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, String name) {
reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilderFromTemplate(renderWorld, layer, blocks)); reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilderFromTemplate(renderWorld, layer, blocks));

View file

@ -15,11 +15,11 @@ import net.minecraft.resources.ResourceLocation;
* An object describing a shader program that can be loaded by flywheel. * An object describing a shader program that can be loaded by flywheel.
* *
* <p> * <p>
* These are defined through json. All ProgramSpecs in <code>assets/modid/flywheel/programs</code> are parsed and * These are defined through json. All ProgramSpecs in {@code assets/modid/flywheel/programs} are parsed and
* processed. One ProgramSpec typically specifies one "material" that can be used in game to render things. * processed. One ProgramSpec typically specifies one "material" that can be used in game to render things.
* </p> * </p>
* <p> * <p>
* All shader source files in <code>assets/modid/flywheel/shaders</code> are completely loaded and parsed into * All shader source files in {@code assets/modid/flywheel/shaders} are completely loaded and parsed into
* {@link SourceFile SourceFiles}, but not compiled until one of them is * {@link SourceFile SourceFiles}, but not compiled until one of them is
* referenced by a ProgramSpec. * referenced by a ProgramSpec.
* </p> * </p>

View file

@ -9,28 +9,28 @@ import net.minecraft.world.phys.Vec3;
public class BeginFrameEvent extends EventContext { public class BeginFrameEvent extends EventContext {
private final ClientLevel world; private final ClientLevel world;
private final Camera info; private final Camera camera;
private final Frustum clippingHelper; private final Frustum frustum;
public BeginFrameEvent(ClientLevel world, Camera info, Frustum clippingHelper) { public BeginFrameEvent(ClientLevel world, Camera camera, Frustum frustum) {
this.world = world; this.world = world;
this.info = info; this.camera = camera;
this.clippingHelper = clippingHelper; this.frustum = frustum;
} }
public ClientLevel getWorld() { public ClientLevel getWorld() {
return world; return world;
} }
public Camera getInfo() { public Camera getCamera() {
return info; return camera;
} }
public Frustum getClippingHelper() { public Frustum getFrustum() {
return clippingHelper; return frustum;
} }
public Vec3 getCameraPos() { public Vec3 getCameraPos() {
return info.getPosition(); return camera.getPosition();
} }
} }

View file

@ -21,4 +21,19 @@ public interface BufferUploaderAccessor {
static void flywheel$setLastEBO(int id) { static void flywheel$setLastEBO(int id) {
throw new AssertionError(); throw new AssertionError();
} }
@Accessor("lastIndexBufferObject")
static int flywheel$getLastEBO() {
throw new AssertionError();
}
@Accessor("lastVertexBufferObject")
static int flywheel$getLastVBO() {
throw new AssertionError();
}
@Accessor("lastVertexArrayObject")
static int flywheel$getLastVAO() {
throw new AssertionError();
}
} }

View file

@ -0,0 +1,21 @@
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 com.jozufozu.flywheel.core.LastActiveCamera;
import net.minecraft.client.Camera;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
@Mixin(Camera.class)
public class CameraMixin {
@Inject(method = "setup", at = @At("TAIL"))
private void setup(BlockGetter level, Entity entity, boolean is3rdPerson, boolean isMirrored, float pt, CallbackInfo ci) {
LastActiveCamera._setActiveCamera((Camera)(Object) this);
}
}

View file

@ -0,0 +1,25 @@
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 com.jozufozu.flywheel.backend.OptifineHandler;
import com.jozufozu.flywheel.core.LastActiveCamera;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.fabric.event.FlywheelEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.culling.Frustum;
@Mixin(Frustum.class)
public class FrustumMixin {
@Inject(method = "prepare", at = @At("TAIL"))
private void onPrepare(double x, double y, double z, CallbackInfo ci) {
if (OptifineHandler.isShadowPass()) {
FlywheelEvents.BEGIN_FRAME.invoker().handleEvent(new BeginFrameEvent(Minecraft.getInstance().level, LastActiveCamera.getActiveCamera(), (Frustum) (Object) this));
}
}
}

View file

@ -30,7 +30,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@Mixin(LevelRenderer.class) @Mixin(LevelRenderer.class)
public class RenderHooksMixin { public class LevelRendererMixin {
@Shadow @Shadow
private ClientLevel level; private ClientLevel level;
@ -49,7 +49,7 @@ public class RenderHooksMixin {
* layer-correct custom rendering. RenderWorldLast is not refined enough for rendering world objects. * layer-correct custom rendering. RenderWorldLast is not refined enough for rendering world objects.
* This should probably be a forge event. * This should probably be a forge event.
*/ */
@Inject(at = @At("TAIL"), method = "renderChunkLayer") @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) { private void renderLayer(RenderType type, PoseStack stack, double camX, double camY, double camZ, Matrix4f p_172999_, CallbackInfo ci) {
RenderBuffers renderBuffers = this.renderBuffers; RenderBuffers renderBuffers = this.renderBuffers;

View file

@ -1,33 +1,35 @@
{ {
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "com.jozufozu.flywheel.mixin", "package": "com.jozufozu.flywheel.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"client": [ "client": [
"BlockEntityTypeMixin", "BlockEntityTypeMixin",
"BufferBuilderMixin", "BufferBuilderMixin",
"BufferUploaderAccessor", "BufferUploaderAccessor",
"CancelEntityRenderMixin", "CameraMixin",
"ChunkRebuildHooksMixin", "CancelEntityRenderMixin",
"EntityTypeMixin", "ChunkRebuildHooksMixin",
"FixFabulousDepthMixin", "EntityTypeMixin",
"InstanceAddMixin", "FixFabulousDepthMixin",
"InstanceRemoveMixin", "FrustumMixin",
"LevelRendererAccessor", "InstanceAddMixin",
"PausedPartialTickAccessor", "InstanceRemoveMixin",
"RenderHooksMixin", "LevelRendererAccessor",
"RenderTexturesMixin", "LevelRendererMixin",
"ShaderCloseMixin", "PausedPartialTickAccessor",
"ShaderInstanceAccessor", "RenderTexturesMixin",
"atlas.AtlasDataMixin", "ShaderCloseMixin",
"atlas.SheetDataAccessor", "ShaderInstanceAccessor",
"light.LightUpdateMixin", "atlas.AtlasDataMixin",
"light.NetworkLightUpdateMixin", "atlas.SheetDataAccessor",
"matrix.Matrix3fMixin", "light.LightUpdateMixin",
"matrix.Matrix4fMixin", "light.NetworkLightUpdateMixin",
"matrix.PoseStackMixin" "matrix.Matrix3fMixin",
], "matrix.Matrix4fMixin",
"injectors": { "matrix.PoseStackMixin"
"defaultRequire": 1 ],
} "injectors": {
"defaultRequire": 1
}
} }