mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 04:00:30 +00:00
Move the rendering monitor code to the client side
It's kinda funny looking at all the pre-CC:T proxy code, how much this has come full circle. I think this design is nicer than what 1.12 did, but it's still slighly embarassing.
This commit is contained in:
parent
b36b96e0bc
commit
48285404b9
@ -13,12 +13,12 @@ import dan200.computercraft.client.render.CableHighlightRenderer;
|
||||
import dan200.computercraft.client.render.ItemPocketRenderer;
|
||||
import dan200.computercraft.client.render.ItemPrintoutRenderer;
|
||||
import dan200.computercraft.client.render.MonitorHighlightRenderer;
|
||||
import dan200.computercraft.client.render.monitor.MonitorRenderState;
|
||||
import dan200.computercraft.client.sound.SpeakerManager;
|
||||
import dan200.computercraft.shared.CommonHooks;
|
||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
||||
@ -58,7 +58,7 @@ public final class ClientHooks {
|
||||
}
|
||||
|
||||
public static void onWorldUnload() {
|
||||
ClientMonitor.destroyAll();
|
||||
MonitorRenderState.destroyAll();
|
||||
SpeakerManager.reset();
|
||||
ClientPocketComputers.reset();
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Vector3f;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
import dan200.computercraft.client.render.monitor.MonitorRenderState;
|
||||
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
|
||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.client.util.DirectBuffers;
|
||||
@ -31,6 +32,7 @@ import net.minecraft.Util;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
@ -64,18 +66,19 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
|
||||
if (originTerminal == null) return;
|
||||
var origin = originTerminal.getOrigin();
|
||||
var renderState = originTerminal.getRenderState(MonitorRenderState::new);
|
||||
var monitorPos = monitor.getBlockPos();
|
||||
|
||||
// Ensure each monitor terminal is rendered only once. We allow rendering a specific tile
|
||||
// multiple times in a single frame to ensure compatibility with shaders which may run a
|
||||
// pass multiple times.
|
||||
var renderFrame = FrameInfo.getRenderFrame();
|
||||
if (originTerminal.lastRenderFrame == renderFrame && !monitorPos.equals(originTerminal.lastRenderPos)) {
|
||||
if (renderState.lastRenderFrame == renderFrame && !monitorPos.equals(renderState.lastRenderPos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
originTerminal.lastRenderFrame = renderFrame;
|
||||
originTerminal.lastRenderPos = monitorPos;
|
||||
renderState.lastRenderFrame = renderFrame;
|
||||
renderState.lastRenderPos = monitorPos;
|
||||
|
||||
var originPos = origin.getBlockPos();
|
||||
|
||||
@ -116,7 +119,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
|
||||
var matrix = transform.last().pose();
|
||||
|
||||
renderTerminal(matrix, originTerminal, terminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale));
|
||||
renderTerminal(matrix, originTerminal, renderState, terminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale));
|
||||
|
||||
transform.popPose();
|
||||
} else {
|
||||
@ -130,34 +133,36 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
private static void renderTerminal(Matrix4f matrix, ClientMonitor monitor, Terminal terminal, float xMargin, float yMargin) {
|
||||
private static void renderTerminal(
|
||||
Matrix4f matrix, ClientMonitor monitor, MonitorRenderState renderState, Terminal terminal, float xMargin, float yMargin
|
||||
) {
|
||||
int width = terminal.getWidth(), height = terminal.getHeight();
|
||||
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
||||
|
||||
var renderType = MonitorRenderer.current();
|
||||
var renderType = currentRenderer();
|
||||
var redraw = monitor.pollTerminalChanged();
|
||||
if (monitor.createBuffer(renderType)) redraw = true;
|
||||
if (renderState.createBuffer(renderType)) redraw = true;
|
||||
|
||||
switch (renderType) {
|
||||
case TBO -> {
|
||||
if (redraw) {
|
||||
var terminalBuffer = getBuffer(width * height * 3);
|
||||
MonitorTextureBufferShader.setTerminalData(terminalBuffer, terminal);
|
||||
DirectBuffers.setBufferData(GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW);
|
||||
DirectBuffers.setBufferData(GL31.GL_TEXTURE_BUFFER, renderState.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW);
|
||||
|
||||
var uniformBuffer = getBuffer(MonitorTextureBufferShader.UNIFORM_SIZE);
|
||||
MonitorTextureBufferShader.setUniformData(uniformBuffer, terminal);
|
||||
DirectBuffers.setBufferData(GL31.GL_UNIFORM_BUFFER, monitor.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW);
|
||||
DirectBuffers.setBufferData(GL31.GL_UNIFORM_BUFFER, renderState.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
// Nobody knows what they're doing!
|
||||
var active = GlStateManager._getActiveTexture();
|
||||
RenderSystem.activeTexture(MonitorTextureBufferShader.TEXTURE_INDEX);
|
||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, monitor.tboTexture);
|
||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, renderState.tboTexture);
|
||||
RenderSystem.activeTexture(active);
|
||||
|
||||
var shader = RenderTypes.getMonitorTextureBufferShader();
|
||||
shader.setupUniform(monitor.tboUniform);
|
||||
shader.setupUniform(renderState.tboUniform);
|
||||
|
||||
var buffer = Tesselator.getInstance().getBuilder();
|
||||
buffer.begin(RenderTypes.MONITOR_TBO.mode(), RenderTypes.MONITOR_TBO.format());
|
||||
@ -168,8 +173,8 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
RenderTypes.MONITOR_TBO.end(buffer, 0, 0, 0);
|
||||
}
|
||||
case VBO -> {
|
||||
var backgroundBuffer = assertNonNull(monitor.backgroundBuffer);
|
||||
var foregroundBuffer = assertNonNull(monitor.foregroundBuffer);
|
||||
var backgroundBuffer = assertNonNull(renderState.backgroundBuffer);
|
||||
var foregroundBuffer = assertNonNull(renderState.foregroundBuffer);
|
||||
if (redraw) {
|
||||
var size = DirectFixedWidthFontRenderer.getVertexCount(terminal);
|
||||
|
||||
@ -238,7 +243,6 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
}
|
||||
|
||||
private static ByteBuffer getBuffer(int capacity) {
|
||||
|
||||
var buffer = backingBuffer;
|
||||
if (buffer == null || buffer.capacity() < capacity) {
|
||||
buffer = backingBuffer = buffer == null ? MemoryTracker.create(capacity) : MemoryTracker.resize(buffer, capacity);
|
||||
@ -252,4 +256,30 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
public int getViewDistance() {
|
||||
return ComputerCraft.monitorDistance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current renderer to use.
|
||||
*
|
||||
* @return The current renderer. Will not return {@link MonitorRenderer#BEST}.
|
||||
*/
|
||||
public static MonitorRenderer currentRenderer() {
|
||||
var current = ComputerCraft.monitorRenderer;
|
||||
if (current == MonitorRenderer.BEST) current = ComputerCraft.monitorRenderer = bestRenderer();
|
||||
return current;
|
||||
}
|
||||
|
||||
private static MonitorRenderer bestRenderer() {
|
||||
if (!GL.getCapabilities().OpenGL31) {
|
||||
ComputerCraft.log.warn("Texture buffers are not supported on your graphics card. Falling back to VBO monitor renderer.");
|
||||
return MonitorRenderer.VBO;
|
||||
}
|
||||
|
||||
if (ShaderMod.INSTANCE.isShaderMod()) {
|
||||
ComputerCraft.log.warn("Optifine is loaded, assuming shaders are being used. Falling back to VBO monitor renderer.");
|
||||
return MonitorRenderer.VBO;
|
||||
}
|
||||
|
||||
return MonitorRenderer.TBO;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.render.monitor;
|
||||
|
||||
import com.google.errorprone.annotations.concurrent.GuardedBy;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import dan200.computercraft.client.util.DirectBuffers;
|
||||
import dan200.computercraft.client.util.DirectVertexBuffer;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MonitorRenderState implements ClientMonitor.RenderState {
|
||||
@GuardedBy("allMonitors")
|
||||
private static final Set<MonitorRenderState> allMonitors = new HashSet<>();
|
||||
|
||||
public long lastRenderFrame = -1;
|
||||
public @Nullable BlockPos lastRenderPos = null;
|
||||
|
||||
public int tboBuffer;
|
||||
public int tboTexture;
|
||||
public int tboUniform;
|
||||
public @Nullable DirectVertexBuffer backgroundBuffer;
|
||||
public @Nullable DirectVertexBuffer foregroundBuffer;
|
||||
|
||||
/**
|
||||
* Create the appropriate buffer if needed.
|
||||
*
|
||||
* @param renderer The renderer to use.
|
||||
* @return If a buffer was created. This will return {@code false} if we already have an appropriate buffer,
|
||||
* or this mode does not require one.
|
||||
*/
|
||||
public boolean createBuffer(MonitorRenderer renderer) {
|
||||
switch (renderer) {
|
||||
case TBO: {
|
||||
if (tboBuffer != 0) return false;
|
||||
|
||||
deleteBuffers();
|
||||
|
||||
tboBuffer = DirectBuffers.createBuffer();
|
||||
DirectBuffers.setEmptyBufferData(GL31.GL_TEXTURE_BUFFER, tboBuffer, GL15.GL_STATIC_DRAW);
|
||||
tboTexture = GlStateManager._genTexture();
|
||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, tboTexture);
|
||||
GL31.glTexBuffer(GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer);
|
||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, 0);
|
||||
|
||||
tboUniform = DirectBuffers.createBuffer();
|
||||
DirectBuffers.setEmptyBufferData(GL31.GL_UNIFORM_BUFFER, tboUniform, GL15.GL_STATIC_DRAW);
|
||||
|
||||
addMonitor();
|
||||
return true;
|
||||
}
|
||||
|
||||
case VBO:
|
||||
if (backgroundBuffer != null) return false;
|
||||
|
||||
deleteBuffers();
|
||||
backgroundBuffer = new DirectVertexBuffer();
|
||||
foregroundBuffer = new DirectVertexBuffer();
|
||||
addMonitor();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void addMonitor() {
|
||||
synchronized (allMonitors) {
|
||||
allMonitors.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteBuffers() {
|
||||
if (tboBuffer != 0) {
|
||||
DirectBuffers.deleteBuffer(GL31.GL_TEXTURE_BUFFER, tboBuffer);
|
||||
tboBuffer = 0;
|
||||
}
|
||||
|
||||
if (tboTexture != 0) {
|
||||
GlStateManager._deleteTexture(tboTexture);
|
||||
tboTexture = 0;
|
||||
}
|
||||
|
||||
if (tboUniform != 0) {
|
||||
DirectBuffers.deleteBuffer(GL31.GL_UNIFORM_BUFFER, tboUniform);
|
||||
tboUniform = 0;
|
||||
}
|
||||
|
||||
if (backgroundBuffer != null) {
|
||||
backgroundBuffer.close();
|
||||
backgroundBuffer = null;
|
||||
}
|
||||
|
||||
if (foregroundBuffer != null) {
|
||||
foregroundBuffer.close();
|
||||
foregroundBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (tboBuffer != 0 || backgroundBuffer != null) {
|
||||
synchronized (allMonitors) {
|
||||
allMonitors.remove(this);
|
||||
}
|
||||
|
||||
deleteBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
public static void destroyAll() {
|
||||
synchronized (allMonitors) {
|
||||
for (var iterator = allMonitors.iterator(); iterator.hasNext(); ) {
|
||||
var monitor = iterator.next();
|
||||
monitor.deleteBuffers();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,39 +5,19 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import dan200.computercraft.client.util.DirectBuffers;
|
||||
import dan200.computercraft.client.util.DirectVertexBuffer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
|
||||
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class ClientMonitor {
|
||||
private static final Set<ClientMonitor> allMonitors = new HashSet<>();
|
||||
|
||||
private final TileMonitor origin;
|
||||
|
||||
public long lastRenderFrame = -1;
|
||||
public @Nullable BlockPos lastRenderPos = null;
|
||||
|
||||
public int tboBuffer;
|
||||
public int tboTexture;
|
||||
public int tboUniform;
|
||||
public @Nullable DirectVertexBuffer backgroundBuffer;
|
||||
public @Nullable DirectVertexBuffer foregroundBuffer;
|
||||
private @Nullable NetworkedTerminal terminal;
|
||||
private boolean terminalChanged;
|
||||
private @Nullable RenderState state;
|
||||
|
||||
public ClientMonitor(TileMonitor origin) {
|
||||
this.origin = origin;
|
||||
@ -48,103 +28,21 @@ public final class ClientMonitor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the appropriate buffer if needed.
|
||||
* Get or create the current render state.
|
||||
*
|
||||
* @param renderer The renderer to use. This can be fetched from {@link MonitorRenderer#current()}.
|
||||
* @return If a buffer was created. This will return {@code false} if we already have an appropriate buffer,
|
||||
* or this mode does not require one.
|
||||
* @param create A factory to create the render state.
|
||||
* @param <T> The current render state. This type parameter should only be inhabited by a single class.
|
||||
* @return This monitor's render state.
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public boolean createBuffer(MonitorRenderer renderer) {
|
||||
switch (renderer) {
|
||||
case TBO: {
|
||||
if (tboBuffer != 0) return false;
|
||||
|
||||
deleteBuffers();
|
||||
|
||||
tboBuffer = DirectBuffers.createBuffer();
|
||||
DirectBuffers.setEmptyBufferData(GL31.GL_TEXTURE_BUFFER, tboBuffer, GL15.GL_STATIC_DRAW);
|
||||
tboTexture = GlStateManager._genTexture();
|
||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, tboTexture);
|
||||
GL31.glTexBuffer(GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer);
|
||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, 0);
|
||||
|
||||
tboUniform = DirectBuffers.createBuffer();
|
||||
DirectBuffers.setEmptyBufferData(GL31.GL_UNIFORM_BUFFER, tboUniform, GL15.GL_STATIC_DRAW);
|
||||
|
||||
addMonitor();
|
||||
return true;
|
||||
}
|
||||
|
||||
case VBO:
|
||||
if (backgroundBuffer != null) return false;
|
||||
|
||||
deleteBuffers();
|
||||
backgroundBuffer = new DirectVertexBuffer();
|
||||
foregroundBuffer = new DirectVertexBuffer();
|
||||
addMonitor();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends RenderState> T getRenderState(Supplier<T> create) {
|
||||
var state = this.state;
|
||||
return (T) (state != null ? state : (this.state = create.get()));
|
||||
}
|
||||
|
||||
private void addMonitor() {
|
||||
synchronized (allMonitors) {
|
||||
allMonitors.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteBuffers() {
|
||||
|
||||
if (tboBuffer != 0) {
|
||||
DirectBuffers.deleteBuffer(GL31.GL_TEXTURE_BUFFER, tboBuffer);
|
||||
tboBuffer = 0;
|
||||
}
|
||||
|
||||
if (tboTexture != 0) {
|
||||
GlStateManager._deleteTexture(tboTexture);
|
||||
tboTexture = 0;
|
||||
}
|
||||
|
||||
if (tboUniform != 0) {
|
||||
DirectBuffers.deleteBuffer(GL31.GL_UNIFORM_BUFFER, tboUniform);
|
||||
tboUniform = 0;
|
||||
}
|
||||
|
||||
if (backgroundBuffer != null) {
|
||||
backgroundBuffer.close();
|
||||
backgroundBuffer = null;
|
||||
}
|
||||
|
||||
if (foregroundBuffer != null) {
|
||||
foregroundBuffer.close();
|
||||
foregroundBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void destroy() {
|
||||
if (tboBuffer != 0 || backgroundBuffer != null) {
|
||||
synchronized (allMonitors) {
|
||||
allMonitors.remove(this);
|
||||
}
|
||||
|
||||
deleteBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static void destroyAll() {
|
||||
synchronized (allMonitors) {
|
||||
for (var iterator = allMonitors.iterator(); iterator.hasNext(); ) {
|
||||
var monitor = iterator.next();
|
||||
monitor.deleteBuffers();
|
||||
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
void destroy() {
|
||||
if (state != null) state.close();
|
||||
state = null;
|
||||
}
|
||||
|
||||
public boolean pollTerminalChanged() {
|
||||
@ -169,4 +67,15 @@ public final class ClientMonitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface representing the current state of the monitor renderer.
|
||||
* <p>
|
||||
* This interface should only be inhabited by {@link dan200.computercraft.client.render.monitor.MonitorRenderState}:
|
||||
* it exists solely to avoid referencing client-side classes in common code.
|
||||
*/
|
||||
public interface RenderState extends AutoCloseable {
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
}
|
||||
|
@ -5,15 +5,10 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
||||
import dan200.computercraft.shared.integration.ShaderMod;
|
||||
import org.lwjgl.opengl.GL;
|
||||
|
||||
/**
|
||||
* The render type to use for monitors.
|
||||
*
|
||||
* @see TileEntityMonitorRenderer
|
||||
* @see dan200.computercraft.client.render.TileEntityMonitorRenderer
|
||||
* @see ClientMonitor
|
||||
*/
|
||||
public enum MonitorRenderer {
|
||||
@ -34,30 +29,5 @@ public enum MonitorRenderer {
|
||||
*
|
||||
* @see com.mojang.blaze3d.vertex.VertexBuffer
|
||||
*/
|
||||
VBO;
|
||||
|
||||
/**
|
||||
* Get the current renderer to use.
|
||||
*
|
||||
* @return The current renderer. Will not return {@link MonitorRenderer#BEST}.
|
||||
*/
|
||||
public static MonitorRenderer current() {
|
||||
var current = ComputerCraft.monitorRenderer;
|
||||
if (current == BEST) current = ComputerCraft.monitorRenderer = best();
|
||||
return current;
|
||||
}
|
||||
|
||||
private static MonitorRenderer best() {
|
||||
if (!GL.getCapabilities().OpenGL31) {
|
||||
ComputerCraft.log.warn("Texture buffers are not supported on your graphics card. Falling back to VBO monitor renderer.");
|
||||
return VBO;
|
||||
}
|
||||
|
||||
if (ShaderMod.INSTANCE.isShaderMod()) {
|
||||
ComputerCraft.log.warn("Optifine is loaded, assuming shaders are being used. Falling back to VBO monitor renderer.");
|
||||
return VBO;
|
||||
}
|
||||
|
||||
return TBO;
|
||||
}
|
||||
VBO,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user