1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 20:20:30 +00:00

Make the shader mod system a little more flexible

Mostly for multi-loader support, but also /technically/ makes it easier
to support multiple loaders in the future.
This commit is contained in:
Jonathan Coates 2022-11-09 21:05:27 +00:00
parent 8a7156785d
commit 0c4fd2b29e
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
6 changed files with 94 additions and 37 deletions

View File

@ -8,8 +8,6 @@ package dan200.computercraft.impl;
import org.jetbrains.annotations.ApiStatus;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
@ -32,17 +30,15 @@ public final class Services {
* @throws IllegalStateException When the service cannot be loaded.
*/
public static <T> T load(Class<T> klass) {
List<T> services = new ArrayList<>(1);
for (var provider : ServiceLoader.load(klass)) services.add(provider);
switch (services.size()) {
case 1:
return services.get(0);
case 0:
throw new IllegalStateException("Cannot find service for " + klass.getName());
default:
var serviceTypes = services.stream().map(x -> x.getClass().getName()).collect(Collectors.joining(", "));
var services = ServiceLoader.load(klass).stream().toList();
return switch (services.size()) {
case 1 -> services.get(0).get();
case 0 -> throw new IllegalStateException("Cannot find service for " + klass.getName());
default -> {
var serviceTypes = services.stream().map(x -> x.type().getName()).collect(Collectors.joining(", "));
throw new IllegalStateException("Multiple services for " + klass.getName() + ": " + serviceTypes);
}
}
};
}
/**

View File

@ -3,8 +3,9 @@
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration;
package dan200.computercraft.client.integration;
import com.google.auto.service.AutoService;
import com.mojang.blaze3d.vertex.VertexFormat;
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
@ -13,28 +14,20 @@ import net.irisshaders.iris.api.v0.IrisTextVertexSink;
import net.minecraftforge.fml.ModList;
import java.nio.ByteBuffer;
import java.util.Optional;
import java.util.function.IntFunction;
public class ShaderMod {
public static final ShaderMod INSTANCE
= ModList.get().isLoaded("oculus") ? new IrisImpl()
: new ShaderMod();
public boolean isShaderMod() {
return Optifine.isLoaded();
/**
* A {@link ShaderMod} for Oculus (the Forge Iris port).
*/
@AutoService(ShaderMod.Provider.class)
public class IrisShaderMod implements ShaderMod.Provider {
@Override
public Optional<ShaderMod> get() {
return ModList.get().isLoaded("oculus") ? Optional.of(new Impl()) : Optional.empty();
}
public boolean isRenderingShadowPass() {
return false;
}
public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, IntFunction<ByteBuffer> makeBuffer) {
return new DirectFixedWidthFontRenderer.ByteBufferEmitter(
makeBuffer.apply(RenderTypes.TERMINAL.format().getVertexSize() * vertexCount * 4)
);
}
private static final class IrisImpl extends ShaderMod {
private static final class Impl extends ShaderMod {
@Override
public boolean isRenderingShadowPass() {
return IrisApi.getInstance().isRenderingShadowPass();

View File

@ -3,7 +3,7 @@
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration;
package dan200.computercraft.client.integration;
/**
* Detect whether Optifine is installed.

View File

@ -0,0 +1,67 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.integration;
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
import dan200.computercraft.client.util.DirectVertexBuffer;
import java.nio.ByteBuffer;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.function.IntFunction;
/**
* Find the currently loaded shader mod (if present) and provides utilities for interacting with it.
*/
public class ShaderMod {
public static ShaderMod get() {
return Storage.INSTANCE;
}
/**
* Determine if shaders may be used in the current session.
*
* @return Whether a shader mod is loaded.
*/
public boolean isShaderMod() {
return Optifine.isLoaded();
}
/**
* Check whether we're currently rendering shadows. Rendering may fall back to a faster but less detailed pass.
*
* @return Whether we're rendering shadows.
*/
public boolean isRenderingShadowPass() {
return false;
}
/**
* Get an appropriate quad emitter for use with {@link DirectVertexBuffer} and {@link DirectFixedWidthFontRenderer} .
*
* @param vertexCount The number of vertices.
* @param makeBuffer A function to allocate a temporary buffer.
* @return The quad emitter.
*/
public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, IntFunction<ByteBuffer> makeBuffer) {
return new DirectFixedWidthFontRenderer.ByteBufferEmitter(
makeBuffer.apply(RenderTypes.TERMINAL.format().getVertexSize() * vertexCount * 4)
);
}
public interface Provider {
Optional<ShaderMod> get();
}
private static class Storage {
static final ShaderMod INSTANCE = ServiceLoader.load(Provider.class)
.stream()
.flatMap(x -> x.get().get().stream())
.findFirst()
.orElseGet(ShaderMod::new);
}
}

View File

@ -16,6 +16,7 @@ import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.client.integration.ShaderMod;
import dan200.computercraft.client.render.monitor.MonitorRenderState;
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
@ -23,7 +24,6 @@ import dan200.computercraft.client.util.DirectBuffers;
import dan200.computercraft.client.util.DirectVertexBuffer;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.config.Config;
import dan200.computercraft.shared.integration.ShaderMod;
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
@ -112,7 +112,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
// Draw the contents
var terminal = originTerminal.getTerminal();
if (terminal != null && !ShaderMod.INSTANCE.isRenderingShadowPass()) {
if (terminal != null && !ShaderMod.get().isRenderingShadowPass()) {
// Draw a terminal
int width = terminal.getWidth(), height = terminal.getHeight();
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
@ -233,7 +233,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
}
private static void renderToBuffer(DirectVertexBuffer vbo, int size, Consumer<DirectFixedWidthFontRenderer.QuadEmitter> draw) {
var sink = ShaderMod.INSTANCE.getQuadEmitter(size, TileEntityMonitorRenderer::getBuffer);
var sink = ShaderMod.get().getQuadEmitter(size, TileEntityMonitorRenderer::getBuffer);
var buffer = sink.buffer();
draw.accept(sink);
@ -279,8 +279,8 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
return MonitorRenderer.VBO;
}
if (ShaderMod.INSTANCE.isShaderMod()) {
LOG.warn("Optifine is loaded, assuming shaders are being used. Falling back to VBO monitor renderer.");
if (ShaderMod.get().isShaderMod()) {
LOG.warn("A shader mod is loaded, assuming shaders are being used. Falling back to VBO monitor renderer.");
return MonitorRenderer.VBO;
}

View File

@ -519,6 +519,7 @@ public class TileMonitor extends TileGeneric {
}
public IPeripheral peripheral() {
createServerMonitor();
if (peripheral != null) return peripheral;
return peripheral = new MonitorPeripheral(this);
}