mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-07 02:34:58 +01:00
Making materials matter more
- Materials are given the opportunity to setup/clear render state - Materials bind textures - Compile all combinations of shader components at load - Drastically simplify compilation context objects - Material shaders control cutout and fog - Remove all GameState related classes - Remove CoreShaderInfoMap - Sneaky optimization to instance storage - Simplify RenderLists
This commit is contained in:
parent
d0c6669a49
commit
0360c1faf8
38 changed files with 408 additions and 575 deletions
|
@ -12,14 +12,12 @@ import com.jozufozu.flywheel.config.BackendTypeArgument;
|
|||
import com.jozufozu.flywheel.config.FlwCommands;
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.GameStateRegistry;
|
||||
import com.jozufozu.flywheel.core.Models;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.jozufozu.flywheel.core.QuadConverter;
|
||||
import com.jozufozu.flywheel.core.StitchedSprite;
|
||||
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||
import com.jozufozu.flywheel.core.shader.NormalDebugStateProvider;
|
||||
import com.jozufozu.flywheel.event.EntityWorldHandler;
|
||||
import com.jozufozu.flywheel.event.ForgeEvents;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
|
@ -111,8 +109,6 @@ public class Flywheel {
|
|||
|
||||
Components.init();
|
||||
|
||||
GameStateRegistry.register(NormalDebugStateProvider.INSTANCE);
|
||||
|
||||
VanillaInstances.init();
|
||||
|
||||
// https://github.com/Jozufozu/Flywheel/issues/69
|
||||
|
|
|
@ -4,4 +4,6 @@ import net.minecraft.core.BlockPos;
|
|||
|
||||
public interface Instance {
|
||||
BlockPos getWorldPosition();
|
||||
|
||||
boolean isRemoved();
|
||||
}
|
||||
|
|
|
@ -4,13 +4,18 @@ import com.jozufozu.flywheel.api.RenderStage;
|
|||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public interface Material {
|
||||
RenderStage getRenderStage();
|
||||
|
||||
RenderType getRenderType();
|
||||
RenderType getBatchingRenderType();
|
||||
|
||||
FileResolution getVertexShader();
|
||||
|
||||
FileResolution getFragmentShader();
|
||||
|
||||
void setup();
|
||||
|
||||
void clear();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
package com.jozufozu.flywheel.backend;
|
||||
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||
import com.jozufozu.flywheel.core.compile.ContextShader;
|
||||
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
|
||||
import com.jozufozu.flywheel.core.source.ShaderSources;
|
||||
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
|
||||
import com.jozufozu.flywheel.util.StringUtil;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
@ -40,6 +47,8 @@ public class Loader implements ResourceManagerReloadListener {
|
|||
var errorReporter = new ErrorReporter();
|
||||
ShaderSources sources = new ShaderSources(errorReporter, manager);
|
||||
|
||||
Backend.LOGGER.info("Loaded all shader sources in " + sources.getLoadTime());
|
||||
|
||||
FileResolution.run(errorReporter, sources);
|
||||
|
||||
if (errorReporter.hasErrored()) {
|
||||
|
@ -49,9 +58,28 @@ public class Loader implements ResourceManagerReloadListener {
|
|||
|
||||
sources.postResolve();
|
||||
|
||||
Backend.LOGGER.info("Successfully resolved all source files.");
|
||||
|
||||
FileResolution.checkAll(errorReporter);
|
||||
|
||||
Backend.LOGGER.info("Loaded all shader sources.");
|
||||
Backend.LOGGER.info("All shaders passed checks.");
|
||||
|
||||
long compileStart = System.nanoTime();
|
||||
|
||||
for (Material material : ComponentRegistry.materials) {
|
||||
for (StructType<?> structType : ComponentRegistry.structTypes) {
|
||||
for (VertexType vertexType : ComponentRegistry.vertexTypes) {
|
||||
for (ContextShader contextShader : ComponentRegistry.contextShaders) {
|
||||
var ctx = new ProgramCompiler.Context(vertexType, material, structType.getInstanceShader(), contextShader);
|
||||
ProgramCompiler.INSTANCE.getProgram(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long compileEnd = System.nanoTime();
|
||||
|
||||
Backend.LOGGER.info("Compiled all programs in " + StringUtil.formatTime(compileEnd - compileStart));
|
||||
|
||||
ClientLevel world = Minecraft.getInstance().level;
|
||||
if (Backend.canUseInstancing(world)) {
|
||||
|
|
|
@ -86,7 +86,7 @@ public class GlVertexArray extends GlObject {
|
|||
offsets[i] = offset;
|
||||
strides[i] = stride;
|
||||
|
||||
GL20.glVertexAttribPointer(i++, attribute.size(), attribute.type().getGlEnum(), attribute.normalized(), stride, offset);
|
||||
GL32.glVertexAttribPointer(i++, attribute.size(), attribute.type().getGlEnum(), attribute.normalized(), stride, offset);
|
||||
|
||||
offset += attribute.getByteWidth();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import com.jozufozu.flywheel.backend.Backend;
|
|||
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||
import com.jozufozu.flywheel.core.compile.ShaderCompilationException;
|
||||
import com.jozufozu.flywheel.core.shader.ShaderConstants;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -20,12 +19,10 @@ public class GlShader extends GlObject {
|
|||
|
||||
public final ShaderType type;
|
||||
private final List<ResourceLocation> parts;
|
||||
private final ShaderConstants constants;
|
||||
|
||||
public GlShader(String source, ShaderType type, List<ResourceLocation> parts, ShaderConstants constants) throws ShaderCompilationException {
|
||||
public GlShader(String source, ShaderType type, List<ResourceLocation> parts) throws ShaderCompilationException {
|
||||
this.parts = parts;
|
||||
this.type = type;
|
||||
this.constants = constants;
|
||||
int handle = GL20.glCreateShader(type.glEnum);
|
||||
|
||||
GlCompat.safeShaderSource(handle, source);
|
||||
|
@ -50,7 +47,7 @@ public class GlShader extends GlObject {
|
|||
.map(ResourceLocation::toString)
|
||||
.map(s -> s.replaceAll("/", "_")
|
||||
.replaceAll(":", "\\$"))
|
||||
.collect(Collectors.joining(";")) + ';' + Integer.toHexString(constants.hashCode());
|
||||
.collect(Collectors.joining(";"));
|
||||
}
|
||||
|
||||
private void dumpSource(String source, ShaderType type) {
|
||||
|
|
|
@ -90,6 +90,11 @@ public abstract class AbstractInstance implements Instance, LightListener {
|
|||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLightUpdate(LightLayer type, ImmutableBox changed) {
|
||||
updateLight();
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.jozufozu.flywheel.backend.instancing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerManager;
|
||||
import com.jozufozu.flywheel.light.LightUpdater;
|
||||
|
||||
public abstract class AbstractStorage<T> implements Storage<T> {
|
||||
protected final List<TickableInstance> tickableInstances;
|
||||
protected final List<DynamicInstance> dynamicInstances;
|
||||
protected final InstancerManager instancerManager;
|
||||
|
||||
protected AbstractStorage(InstancerManager instancerManager) {
|
||||
this.instancerManager = instancerManager;
|
||||
|
||||
this.dynamicInstances = new ArrayList<>();
|
||||
this.tickableInstances = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TickableInstance> getInstancesForTicking() {
|
||||
return tickableInstances;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DynamicInstance> getInstancesForUpdate() {
|
||||
return dynamicInstances;
|
||||
}
|
||||
|
||||
protected void setup(AbstractInstance renderer) {
|
||||
renderer.init();
|
||||
renderer.updateLight();
|
||||
LightUpdater.get(renderer.level)
|
||||
.addListener(renderer);
|
||||
if (renderer instanceof TickableInstance r) {
|
||||
tickableInstances.add(r);
|
||||
r.tick();
|
||||
}
|
||||
|
||||
if (renderer instanceof DynamicInstance r) {
|
||||
dynamicInstances.add(r);
|
||||
r.beginFrame();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.instancing;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -12,20 +13,12 @@ import com.jozufozu.flywheel.api.instance.TickableInstance;
|
|||
import com.jozufozu.flywheel.api.instancer.InstancerManager;
|
||||
import com.jozufozu.flywheel.light.LightUpdater;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
|
||||
public abstract class One2OneStorage<T> implements Storage<T> {
|
||||
public abstract class One2OneStorage<T> extends AbstractStorage<T> {
|
||||
private final Map<T, AbstractInstance> instances;
|
||||
private final Object2ObjectOpenHashMap<T, TickableInstance> tickableInstances;
|
||||
private final Object2ObjectOpenHashMap<T, DynamicInstance> dynamicInstances;
|
||||
protected final InstancerManager instancerManager;
|
||||
|
||||
public One2OneStorage(InstancerManager instancerManager) {
|
||||
this.instancerManager = instancerManager;
|
||||
super(instancerManager);
|
||||
this.instances = new HashMap<>();
|
||||
|
||||
this.dynamicInstances = new Object2ObjectOpenHashMap<>();
|
||||
this.tickableInstances = new Object2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,16 +31,6 @@ public abstract class One2OneStorage<T> implements Storage<T> {
|
|||
return instances.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TickableInstance> getInstancesForTicking() {
|
||||
return new ArrayList<>(tickableInstances.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DynamicInstance> getInstancesForUpdate() {
|
||||
return new ArrayList<>(dynamicInstances.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
instances.values().forEach(AbstractInstance::remove);
|
||||
|
@ -74,8 +57,8 @@ public abstract class One2OneStorage<T> implements Storage<T> {
|
|||
}
|
||||
|
||||
instance.remove();
|
||||
dynamicInstances.remove(obj);
|
||||
tickableInstances.remove(obj);
|
||||
dynamicInstances.remove(instance);
|
||||
tickableInstances.remove(instance);
|
||||
LightUpdater.get(instance.level)
|
||||
.removeListener(instance);
|
||||
}
|
||||
|
@ -109,7 +92,7 @@ public abstract class One2OneStorage<T> implements Storage<T> {
|
|||
AbstractInstance out = createRaw(obj);
|
||||
|
||||
if (out != null) {
|
||||
setup(obj, out);
|
||||
setup(out);
|
||||
}
|
||||
|
||||
return out;
|
||||
|
@ -120,7 +103,7 @@ public abstract class One2OneStorage<T> implements Storage<T> {
|
|||
AbstractInstance renderer = createRaw(obj);
|
||||
|
||||
if (renderer != null) {
|
||||
setup(obj, renderer);
|
||||
setup(renderer);
|
||||
instances.put(obj, renderer);
|
||||
}
|
||||
|
||||
|
@ -128,20 +111,4 @@ public abstract class One2OneStorage<T> implements Storage<T> {
|
|||
|
||||
@Nullable
|
||||
protected abstract AbstractInstance createRaw(T obj);
|
||||
|
||||
private void setup(T obj, AbstractInstance renderer) {
|
||||
renderer.init();
|
||||
renderer.updateLight();
|
||||
LightUpdater.get(renderer.level)
|
||||
.addListener(renderer);
|
||||
if (renderer instanceof TickableInstance r) {
|
||||
tickableInstances.put(obj, r);
|
||||
r.tick();
|
||||
}
|
||||
|
||||
if (renderer instanceof DynamicInstance r) {
|
||||
dynamicInstances.put(obj, r);
|
||||
r.beginFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ public class BatchLists {
|
|||
public final Map<RenderType, List<TransformSet<?>>> renderLists = new HashMap<>();
|
||||
|
||||
public void add(TransformSet<?> set) {
|
||||
renderLists.computeIfAbsent(set.material.getRenderType(), k -> new ArrayList<>()).add(set);
|
||||
renderLists.computeIfAbsent(set.material.getBatchingRenderType(), k -> new ArrayList<>())
|
||||
.add(set);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
|||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractStorage;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.Storage;
|
||||
import com.jozufozu.flywheel.light.LightUpdater;
|
||||
|
@ -33,18 +34,13 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static class EffectStorage<T extends Effect> implements Storage<T> {
|
||||
public static class EffectStorage<T extends Effect> extends AbstractStorage<T> {
|
||||
|
||||
private final Multimap<T, AbstractInstance> instances;
|
||||
private final Set<DynamicInstance> dynamicInstances;
|
||||
private final Set<TickableInstance> tickableInstances;
|
||||
private final InstancerManager manager;
|
||||
|
||||
public EffectStorage(InstancerManager manager) {
|
||||
super(manager);
|
||||
this.instances = HashMultimap.create();
|
||||
this.dynamicInstances = new HashSet<>();
|
||||
this.tickableInstances = new HashSet<>();
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,16 +53,6 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
|
|||
return instances.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TickableInstance> getInstancesForTicking() {
|
||||
return new ArrayList<>(tickableInstances);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DynamicInstance> getInstancesForUpdate() {
|
||||
return new ArrayList<>(dynamicInstances);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
instances.values().forEach(AbstractInstance::removeAndMark);
|
||||
|
@ -123,27 +109,11 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
|
|||
}
|
||||
|
||||
private void create(T obj) {
|
||||
var instances = obj.createInstances(manager);
|
||||
var instances = obj.createInstances(instancerManager);
|
||||
|
||||
this.instances.putAll(obj, instances);
|
||||
|
||||
instances.forEach(this::setup);
|
||||
}
|
||||
|
||||
private void setup(AbstractInstance renderer) {
|
||||
renderer.init();
|
||||
renderer.updateLight();
|
||||
LightUpdater.get(renderer.level)
|
||||
.addListener(renderer);
|
||||
if (renderer instanceof TickableInstance r) {
|
||||
tickableInstances.add(r);
|
||||
r.tick();
|
||||
}
|
||||
|
||||
if (renderer instanceof DynamicInstance r) {
|
||||
dynamicInstances.add(r);
|
||||
r.beginFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.jozufozu.flywheel.api.RenderStage;
|
||||
|
@ -13,23 +14,21 @@ import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
|||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.backend.instancing.Engine;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||
import com.jozufozu.flywheel.backend.model.MeshPool;
|
||||
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo;
|
||||
import com.jozufozu.flywheel.core.GameStateRegistry;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
import com.jozufozu.flywheel.core.compile.ContextShader;
|
||||
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.uniform.UniformBuffer;
|
||||
import com.jozufozu.flywheel.util.Textures;
|
||||
import com.jozufozu.flywheel.util.WeakHashSet;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.util.Mth;
|
||||
|
@ -73,20 +72,11 @@ public class InstancingEngine implements Engine {
|
|||
|
||||
@Override
|
||||
public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) {
|
||||
if (!renderLists.process(stage)) {
|
||||
return;
|
||||
}
|
||||
var multimap = renderLists.get(stage);
|
||||
|
||||
var renderList = renderLists.get(stage);
|
||||
for (var entry : renderList.entrySet()) {
|
||||
var multimap = entry.getValue();
|
||||
setup();
|
||||
|
||||
if (multimap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
render(entry.getKey(), multimap);
|
||||
}
|
||||
render(multimap);
|
||||
}
|
||||
|
||||
// TODO: Is this useful? Should it be added to the base interface? Currently it is only used for the old CrumblingRenderer.
|
||||
|
@ -96,28 +86,29 @@ public class InstancingEngine implements Engine {
|
|||
return;
|
||||
}
|
||||
|
||||
for (RenderStage stage : renderLists.stagesToProcess) {
|
||||
var renderList = renderLists.get(stage);
|
||||
for (var entry : renderList.entrySet()) {
|
||||
var multimap = entry.getValue();
|
||||
setup();
|
||||
|
||||
for (var multimap : renderLists.getAll()) {
|
||||
render(multimap);
|
||||
}
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
GlTextureUnit.T2.makeActive();
|
||||
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
|
||||
|
||||
RenderSystem.depthMask(true);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.depthFunc(GL32.GL_LEQUAL);
|
||||
RenderSystem.enableCull();
|
||||
}
|
||||
|
||||
protected void render(ListMultimap<ShaderState, DrawCall> multimap) {
|
||||
if (multimap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
render(entry.getKey(), multimap);
|
||||
}
|
||||
}
|
||||
|
||||
renderLists.stagesToProcess.clear();
|
||||
}
|
||||
|
||||
protected void render(RenderType type, ListMultimap<ShaderState, DrawCall> multimap) {
|
||||
type.setupRenderState();
|
||||
Textures.bindActiveTextures();
|
||||
CoreShaderInfo coreShaderInfo = CoreShaderInfo.get();
|
||||
StateSnapshot state = GameStateRegistry.takeSnapshot();
|
||||
|
||||
for (var entry : multimap.asMap().entrySet()) {
|
||||
var shader = entry.getKey();
|
||||
var drawCalls = entry.getValue();
|
||||
|
@ -128,28 +119,29 @@ public class InstancingEngine implements Engine {
|
|||
continue;
|
||||
}
|
||||
|
||||
setup(shader, coreShaderInfo, state);
|
||||
setup(shader);
|
||||
|
||||
shader.material().setup();
|
||||
|
||||
for (var drawCall : drawCalls) {
|
||||
drawCall.render();
|
||||
}
|
||||
|
||||
shader.material().clear();
|
||||
}
|
||||
}
|
||||
|
||||
type.clearRenderState();
|
||||
}
|
||||
|
||||
protected void setup(ShaderState desc, CoreShaderInfo coreShaderInfo, StateSnapshot ctx) {
|
||||
protected void setup(ShaderState desc) {
|
||||
|
||||
VertexType vertexType = desc.vertex();
|
||||
FileResolution instanceShader = desc.instance()
|
||||
.getInstanceShader();
|
||||
Material material = desc.material();
|
||||
|
||||
var program = ProgramCompiler.INSTANCE.getProgram(new ProgramCompiler.Context(vertexType, material,
|
||||
instanceShader, context, coreShaderInfo.getAdjustedAlphaDiscard(), coreShaderInfo.fogType(), ctx));
|
||||
var ctx = new ProgramCompiler.Context(vertexType, material, instanceShader, context);
|
||||
|
||||
program.bind();
|
||||
ProgramCompiler.INSTANCE.getProgram(ctx)
|
||||
.bind();
|
||||
UniformBuffer.getInstance().sync();
|
||||
}
|
||||
|
||||
|
@ -197,8 +189,6 @@ public class InstancingEngine implements Engine {
|
|||
}
|
||||
uninitializedModels.clear();
|
||||
|
||||
renderLists.prepare();
|
||||
|
||||
MeshPool.getInstance()
|
||||
.flush();
|
||||
}
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.instancing;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.jozufozu.flywheel.api.RenderStage;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
public class RenderLists {
|
||||
|
||||
private final Map<RenderStage, Map<RenderType, ListMultimap<ShaderState, DrawCall>>> renderLists = new EnumMap<>(RenderStage.class);
|
||||
public final Set<RenderStage> stagesToProcess = EnumSet.noneOf(RenderStage.class);
|
||||
public final Map<RenderStage, ListMultimap<ShaderState, DrawCall>> renderLists = new EnumMap<>(RenderStage.class);
|
||||
|
||||
public Map<RenderType, ListMultimap<ShaderState, DrawCall>> get(RenderStage stage) {
|
||||
public ListMultimap<ShaderState, DrawCall> get(RenderStage stage) {
|
||||
var renderList = renderLists.get(stage);
|
||||
if (renderList == null) {
|
||||
return Collections.emptyMap();
|
||||
return ImmutableListMultimap.of();
|
||||
}
|
||||
return renderList;
|
||||
}
|
||||
|
@ -30,28 +25,15 @@ public class RenderLists {
|
|||
public void add(ShaderState shaderState, DrawCall layer) {
|
||||
Material material = shaderState.material();
|
||||
|
||||
renderLists
|
||||
.computeIfAbsent(material.getRenderStage(), k -> new HashMap<>())
|
||||
.computeIfAbsent(material.getRenderType(), k -> ArrayListMultimap.create())
|
||||
renderLists.computeIfAbsent(material.getRenderStage(), k -> ArrayListMultimap.create())
|
||||
.put(shaderState, layer);
|
||||
}
|
||||
|
||||
public void prepare() {
|
||||
stagesToProcess.clear();
|
||||
|
||||
stagesToProcess.addAll(renderLists.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and mark a stage as processed.
|
||||
* @param stage The stage to check.
|
||||
* @return {@code true} if the stage should be processed.
|
||||
*/
|
||||
public boolean process(RenderStage stage) {
|
||||
return stagesToProcess.remove(stage);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return stagesToProcess.isEmpty();
|
||||
return renderLists.isEmpty();
|
||||
}
|
||||
|
||||
public Collection<ListMultimap<ShaderState, DrawCall>> getAll() {
|
||||
return renderLists.values();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,44 +16,55 @@ import com.jozufozu.flywheel.core.compile.ContextShader;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class ComponentRegistry {
|
||||
private static final Registry<UniformProvider> uniformProviders = new Registry<>();
|
||||
|
||||
private static final Set<ResourceLocation> uniformProviderFiles = new HashSet<>();
|
||||
private static final List<UniformProvider> uniformProviders = new ArrayList<>();
|
||||
public static final Set<Material> materials = new HashSet<>();
|
||||
public static final Set<StructType<?>> structTypes = new HashSet<>();
|
||||
public static final Set<VertexType> vertexTypes = new HashSet<>();
|
||||
public static final Set<ContextShader> contextShaders = new HashSet<>();
|
||||
|
||||
// TODO: fill out the rest of the registry
|
||||
|
||||
public static <T extends Material> T register(T material) {
|
||||
materials.add(material);
|
||||
return material;
|
||||
}
|
||||
|
||||
public static <T extends StructType<?>> T register(T type) {
|
||||
|
||||
structTypes.add(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
public static <T extends VertexType> T register(T vertexType) {
|
||||
vertexTypes.add(vertexType);
|
||||
return vertexType;
|
||||
}
|
||||
|
||||
public static ContextShader register(ContextShader contextShader) {
|
||||
contextShaders.add(contextShader);
|
||||
return contextShader;
|
||||
}
|
||||
|
||||
public static <T extends UniformProvider> T register(T provider) {
|
||||
|
||||
var file = provider.getUniformShader();
|
||||
|
||||
ResourceLocation location = file.getFileLoc();
|
||||
if (uniformProviderFiles.contains(location)) {
|
||||
throw new IllegalArgumentException("UniformProvider for '" + location + "' already registered");
|
||||
}
|
||||
|
||||
uniformProviderFiles.add(location);
|
||||
uniformProviders.add(provider);
|
||||
return provider;
|
||||
return uniformProviders.register(provider.getUniformShader()
|
||||
.getFileLoc(), provider);
|
||||
}
|
||||
|
||||
public static Collection<UniformProvider> getAllUniformProviders() {
|
||||
return Collections.unmodifiableCollection(uniformProviders);
|
||||
return Collections.unmodifiableCollection(uniformProviders.objects);
|
||||
}
|
||||
|
||||
private static class Registry<T> {
|
||||
private final Set<ResourceLocation> files = new HashSet<>();
|
||||
private final List<T> objects = new ArrayList<>();
|
||||
|
||||
public <O extends T> O register(ResourceLocation loc, O object) {
|
||||
if (files.contains(loc)) {
|
||||
throw new IllegalArgumentException("Shader file already registered: " + loc);
|
||||
}
|
||||
files.add(loc);
|
||||
objects.add(object);
|
||||
return object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.function.BiConsumer;
|
|||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.core.compile.ContextShader;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceChecks;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
|
@ -24,7 +23,7 @@ public class Components {
|
|||
public static final ViewProvider VIEW_PROVIDER = ComponentRegistry.register(new ViewProvider());
|
||||
public static final FogProvider FOG_PROVIDER = ComponentRegistry.register(new FogProvider());
|
||||
public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(WorldProgram::new, Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
|
||||
public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(CrumblingProgram::new, Files.CRUMBLING_VERTEX, Files.CRUMBLING_FRAGMENT));
|
||||
public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(CrumblingProgram::new, Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
|
||||
|
||||
public static void init() {
|
||||
Files.init();
|
||||
|
@ -42,43 +41,44 @@ public class Components {
|
|||
public static final FileResolution TRANSFORMED = instanceVertex(ResourceUtil.subPath(Names.TRANSFORMED, ".vert"));
|
||||
public static final FileResolution ORIENTED = instanceVertex(ResourceUtil.subPath(Names.ORIENTED, ".vert"));
|
||||
public static final FileResolution DEFAULT_VERTEX = materialVertex(ResourceUtil.subPath(Names.DEFAULT, ".vert"));
|
||||
public static final FileResolution DEFAULT_FRAGMENT = materialFragment(ResourceUtil.subPath(Names.DEFAULT, ".frag"));
|
||||
public static final FileResolution SHADED_VERTEX = materialVertex(ResourceUtil.subPath(Names.SHADED, ".vert"));
|
||||
public static final FileResolution DEFAULT_FRAGMENT = materialFragment(ResourceUtil.subPath(Names.DEFAULT, ".frag"));
|
||||
public static final FileResolution CUTOUT_FRAGMENT = materialFragment(ResourceUtil.subPath(Names.CUTOUT, ".frag"));
|
||||
public static final FileResolution WORLD_VERTEX = contextVertex(ResourceUtil.subPath(Names.WORLD, ".vert"));
|
||||
public static final FileResolution WORLD_FRAGMENT = contextFragment(ResourceUtil.subPath(Names.WORLD, ".frag"));
|
||||
public static final FileResolution CRUMBLING_VERTEX = contextVertex(ResourceUtil.subPath(Names.CRUMBLING, ".vert"));
|
||||
public static final FileResolution CRUMBLING_FRAGMENT = contextFragment(ResourceUtil.subPath(Names.CRUMBLING, ".frag"));
|
||||
|
||||
public static FileResolution uniform(ResourceLocation location) {
|
||||
private static FileResolution uniform(ResourceLocation location) {
|
||||
return FileResolution.get(location);
|
||||
}
|
||||
|
||||
public static FileResolution layoutVertex(ResourceLocation location) {
|
||||
private static FileResolution layoutVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.LAYOUT_VERTEX);
|
||||
}
|
||||
|
||||
public static FileResolution instanceVertex(ResourceLocation location) {
|
||||
private static FileResolution instanceVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.INSTANCE_VERTEX);
|
||||
}
|
||||
|
||||
public static FileResolution materialVertex(ResourceLocation location) {
|
||||
private static FileResolution materialVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.MATERIAL_VERTEX);
|
||||
}
|
||||
|
||||
public static FileResolution materialFragment(ResourceLocation location) {
|
||||
private static FileResolution materialFragment(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.MATERIAL_FRAGMENT);
|
||||
}
|
||||
|
||||
public static FileResolution contextVertex(ResourceLocation location) {
|
||||
private static FileResolution contextVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.CONTEXT_VERTEX);
|
||||
}
|
||||
|
||||
public static FileResolution contextFragment(ResourceLocation location) {
|
||||
private static FileResolution contextFragment(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.CONTEXT_FRAGMENT);
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ public class Components {
|
|||
public static final ResourceLocation ORIENTED = Flywheel.rl("instance/oriented");
|
||||
|
||||
public static final ResourceLocation DEFAULT = Flywheel.rl("material/default");
|
||||
public static final ResourceLocation CUTOUT = Flywheel.rl("material/cutout");
|
||||
public static final ResourceLocation SHADED = Flywheel.rl("material/shaded");
|
||||
public static final ResourceLocation WORLD = Flywheel.rl("context/world");
|
||||
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling");
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import static com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType.COLOR_FOG;
|
||||
import static com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType.FADE_FOG;
|
||||
import static com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType.NO_FOG;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.backend.ShadersModHandler;
|
||||
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
|
||||
public class CoreShaderInfoMap {
|
||||
private static final Map<String, CoreShaderInfo> MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
registerInfo("block", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("new_entity", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("particle", new CoreShaderInfo(0.1f, false, COLOR_FOG));
|
||||
registerInfo("position", new CoreShaderInfo(-1, false, COLOR_FOG));
|
||||
registerInfo("position_color", new CoreShaderInfo(0, false, NO_FOG));
|
||||
registerInfo("position_color_lightmap", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("position_color_tex", new CoreShaderInfo(0.1f, false, NO_FOG));
|
||||
registerInfo("position_color_tex_lightmap", new CoreShaderInfo(0.1f, false, NO_FOG));
|
||||
registerInfo("position_tex", new CoreShaderInfo(0, false, NO_FOG));
|
||||
registerInfo("position_tex_color", new CoreShaderInfo(0.1f, false, NO_FOG));
|
||||
registerInfo("position_tex_color_normal", new CoreShaderInfo(0.1f, false, COLOR_FOG));
|
||||
registerInfo("position_tex_lightmap_color", new CoreShaderInfo(0.1f, false, NO_FOG));
|
||||
registerInfo("rendertype_solid", new CoreShaderInfo(-1, false, COLOR_FOG));
|
||||
registerInfo("rendertype_cutout_mipped", new CoreShaderInfo(ShadersModHandler.isShaderPackInUse() ? 0.1f : 0.5f, false, COLOR_FOG));
|
||||
registerInfo("rendertype_cutout", new CoreShaderInfo(0.1f, false, COLOR_FOG));
|
||||
registerInfo("rendertype_translucent", new CoreShaderInfo(-1, false, COLOR_FOG));
|
||||
registerInfo("rendertype_translucent_moving_block", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("rendertype_translucent_no_crumbling", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("rendertype_armor_cutout_no_cull", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_solid", new CoreShaderInfo(-1, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_cutout", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_cutout_no_cull", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_cutout_no_cull_z_offset", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_item_entity_translucent_cull", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_translucent_cull", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_translucent", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_smooth_cutout", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_beacon_beam", new CoreShaderInfo(-1, false, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_decal", new CoreShaderInfo(0.1f, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_no_outline", new CoreShaderInfo(-1, true, COLOR_FOG));
|
||||
registerInfo("rendertype_entity_shadow", new CoreShaderInfo(-1, false, COLOR_FOG));
|
||||
// Special alpha discard
|
||||
registerInfo("rendertype_entity_alpha", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("rendertype_eyes", new CoreShaderInfo(-1, false, FADE_FOG));
|
||||
registerInfo("rendertype_energy_swirl", new CoreShaderInfo(0.1f, false, FADE_FOG));
|
||||
registerInfo("rendertype_leash", new CoreShaderInfo(-1, false, COLOR_FOG));
|
||||
registerInfo("rendertype_water_mask", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("rendertype_outline", new CoreShaderInfo(0, false, NO_FOG));
|
||||
registerInfo("rendertype_armor_glint", new CoreShaderInfo(0.1f, false, FADE_FOG));
|
||||
registerInfo("rendertype_armor_entity_glint", new CoreShaderInfo(0.1f, false, FADE_FOG));
|
||||
registerInfo("rendertype_glint_translucent", new CoreShaderInfo(0.1f, false, FADE_FOG));
|
||||
registerInfo("rendertype_glint", new CoreShaderInfo(0.1f, false, FADE_FOG));
|
||||
registerInfo("rendertype_glint_direct", new CoreShaderInfo(0.1f, false, FADE_FOG));
|
||||
registerInfo("rendertype_entity_glint", new CoreShaderInfo(0.1f, false, FADE_FOG));
|
||||
registerInfo("rendertype_entity_glint_direct", new CoreShaderInfo(0.1f, false, FADE_FOG));
|
||||
registerInfo("rendertype_text", new CoreShaderInfo(0.1f, false, COLOR_FOG));
|
||||
registerInfo("rendertype_text_intensity", new CoreShaderInfo(0.1f, false, COLOR_FOG));
|
||||
registerInfo("rendertype_text_see_through", new CoreShaderInfo(0.1f, false, NO_FOG));
|
||||
registerInfo("rendertype_text_intensity_see_through", new CoreShaderInfo(0.1f, false, NO_FOG));
|
||||
registerInfo("rendertype_lightning", new CoreShaderInfo(-1, false, FADE_FOG));
|
||||
registerInfo("rendertype_tripwire", new CoreShaderInfo(0.1f, false, COLOR_FOG));
|
||||
registerInfo("rendertype_end_portal", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("rendertype_end_gateway", new CoreShaderInfo(-1, false, NO_FOG));
|
||||
registerInfo("rendertype_lines", new CoreShaderInfo(-1, false, COLOR_FOG));
|
||||
registerInfo("rendertype_crumbling", new CoreShaderInfo(0.1f, false, NO_FOG));
|
||||
|
||||
registerInfo("forge:rendertype_entity_unlit_translucent", new CoreShaderInfo(0.1f, false, COLOR_FOG));
|
||||
}
|
||||
|
||||
public static void registerInfo(String name, CoreShaderInfo info) {
|
||||
MAP.put(name, info);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CoreShaderInfo getInfo(String name) {
|
||||
return MAP.get(name);
|
||||
}
|
||||
|
||||
public record CoreShaderInfo(float alphaDiscard, boolean appliesDiffuse, FogType fogType) {
|
||||
public static final CoreShaderInfo DEFAULT = new CoreShaderInfo(-1, false, NO_FOG);
|
||||
|
||||
public static CoreShaderInfo get() {
|
||||
CoreShaderInfo out = null;
|
||||
ShaderInstance coreShader = RenderSystem.getShader();
|
||||
if (coreShader != null) {
|
||||
String coreShaderName = coreShader.getName();
|
||||
out = getInfo(coreShaderName);
|
||||
}
|
||||
if (out == null) {
|
||||
out = DEFAULT;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public float getAdjustedAlphaDiscard() {
|
||||
float alphaDiscard = alphaDiscard();
|
||||
if (alphaDiscard == 0) {
|
||||
alphaDiscard = 0.0001f;
|
||||
} else if (alphaDiscard < 0) {
|
||||
alphaDiscard = 0;
|
||||
}
|
||||
return alphaDiscard;
|
||||
}
|
||||
|
||||
public enum FogType {
|
||||
NO_FOG,
|
||||
COLOR_FOG,
|
||||
FADE_FOG;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.core.shader.GameStateProvider;
|
||||
import com.jozufozu.flywheel.core.shader.ShaderConstants;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
|
||||
public class GameStateRegistry {
|
||||
|
||||
private static final List<GameStateProvider> PROVIDERS = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Registers a game state provider.
|
||||
* @param provider The provider to register.
|
||||
*/
|
||||
public static void register(GameStateProvider provider) {
|
||||
PROVIDERS.add(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a snapshot of the current game state, storing it in a bit set.
|
||||
* @return An object that represents the current game state.
|
||||
*/
|
||||
public static StateSnapshot takeSnapshot() {
|
||||
BitSet bitSet = new BitSet(PROVIDERS.size());
|
||||
|
||||
for (int i = 0, listSize = PROVIDERS.size(); i < listSize; i++) {
|
||||
if (PROVIDERS.get(i).isTrue()) {
|
||||
bitSet.set(i);
|
||||
}
|
||||
}
|
||||
return new StateSnapshot(bitSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the given snapshot, gathers shader constants to be injected during shader compilation.
|
||||
* @param snapshot The snapshot to use.
|
||||
* @return A list of shader constants.
|
||||
*/
|
||||
public static ShaderConstants getShaderConstants(StateSnapshot snapshot) {
|
||||
BitSet ctx = snapshot.ctx();
|
||||
ShaderConstants shaderConstants = new ShaderConstants();
|
||||
|
||||
for (int i = 0, listSize = PROVIDERS.size(); i < listSize; i++) {
|
||||
if (ctx.get(i)) {
|
||||
PROVIDERS.get(i).alterConstants(shaderConstants);
|
||||
}
|
||||
}
|
||||
return shaderConstants;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package com.jozufozu.flywheel.core;
|
|||
import com.jozufozu.flywheel.api.RenderStage;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.core.material.SimpleMaterial;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.Sheets;
|
||||
|
@ -10,11 +11,33 @@ import net.minecraft.resources.ResourceLocation;
|
|||
|
||||
public class Materials {
|
||||
private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png");
|
||||
public static final Material DEFAULT = ComponentRegistry.register(new SimpleMaterial(RenderStage.AFTER_SOLID_TERRAIN, RenderType.cutout(), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
public static final Material CHEST = ComponentRegistry.register(new SimpleMaterial(RenderStage.AFTER_BLOCK_ENTITIES, Sheets.chestSheet(), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
public static final Material SHULKER = ComponentRegistry.register(new SimpleMaterial(RenderStage.AFTER_BLOCK_ENTITIES, RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
public static final Material BELL = ComponentRegistry.register(new SimpleMaterial(RenderStage.AFTER_BLOCK_ENTITIES, Sheets.solidBlockSheet(), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
public static final Material MINECART = ComponentRegistry.register(new SimpleMaterial(RenderStage.AFTER_ENTITIES, RenderType.entitySolid(MINECART_LOCATION), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
public static final Material DEFAULT = SimpleMaterial.builder()
|
||||
.stage(RenderStage.AFTER_SOLID_TERRAIN)
|
||||
.renderType(RenderType.cutout())
|
||||
.fragmentShader(Components.Files.CUTOUT_FRAGMENT)
|
||||
.register();
|
||||
public static final Material CHEST = SimpleMaterial.builder()
|
||||
.stage(RenderStage.AFTER_BLOCK_ENTITIES)
|
||||
.renderType(Sheets.chestSheet())
|
||||
.diffuseTex(Sheets.CHEST_SHEET)
|
||||
.register();
|
||||
public static final Material SHULKER = SimpleMaterial.builder()
|
||||
.stage(RenderStage.AFTER_BLOCK_ENTITIES)
|
||||
.renderType(Sheets.shulkerBoxSheet())
|
||||
.diffuseTex(Sheets.SHULKER_SHEET)
|
||||
.fragmentShader(Components.Files.CUTOUT_FRAGMENT)
|
||||
.alsoSetup(RenderSystem::disableCull)
|
||||
.alsoClear(RenderSystem::enableCull)
|
||||
.register();
|
||||
public static final Material BELL = SimpleMaterial.builder()
|
||||
.stage(RenderStage.AFTER_BLOCK_ENTITIES)
|
||||
.renderType(Sheets.solidBlockSheet())
|
||||
.register();
|
||||
public static final Material MINECART = SimpleMaterial.builder()
|
||||
.stage(RenderStage.AFTER_ENTITIES)
|
||||
.renderType(RenderType.entitySolid(MINECART_LOCATION))
|
||||
.diffuseTex(MINECART_LOCATION)
|
||||
.register();
|
||||
|
||||
public static void init() {
|
||||
// noop
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.jozufozu.flywheel.core.shader;
|
||||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
|
|
@ -4,9 +4,6 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType;
|
||||
import com.jozufozu.flywheel.core.shader.ShaderConstants;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
|
||||
|
@ -24,10 +21,6 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
|
|||
|
||||
finalSource.append(CompileUtil.generateHeader(GLSLVersion.V420, ShaderType.FRAGMENT));
|
||||
|
||||
var shaderConstants = key.getShaderConstants();
|
||||
shaderConstants.writeInto(finalSource);
|
||||
finalSource.append('\n');
|
||||
|
||||
var ctx = new CompilationContext();
|
||||
|
||||
// MATERIAL
|
||||
|
@ -45,7 +38,7 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
|
|||
finalSource.append(generateFooter());
|
||||
|
||||
try {
|
||||
return new GlShader(finalSource.toString(), ShaderType.FRAGMENT, ImmutableList.of(materialShader.name, contextShaderSource.name), shaderConstants);
|
||||
return new GlShader(finalSource.toString(), ShaderType.FRAGMENT, ImmutableList.of(materialShader.name, contextShaderSource.name));
|
||||
} catch (ShaderCompilationException e) {
|
||||
throw e.withErrorLog(ctx);
|
||||
}
|
||||
|
@ -70,22 +63,10 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
|
|||
|
||||
/**
|
||||
* Represents the conditions under which a shader is compiled.
|
||||
*
|
||||
* @param materialShader The fragment material shader source.
|
||||
* @param alphaDiscard Alpha threshold below which fragments are discarded.
|
||||
* @param fogType Which type of fog should be applied.
|
||||
* @param ctx The shader constants to apply.
|
||||
*/
|
||||
public record Context(SourceFile materialShader, SourceFile contextShader, float alphaDiscard, FogType fogType, StateSnapshot ctx) {
|
||||
public record Context(SourceFile materialShader, SourceFile contextShader) {
|
||||
|
||||
public ShaderConstants getShaderConstants() {
|
||||
ShaderConstants shaderConstants = ctx.getShaderConstants();
|
||||
|
||||
if (alphaDiscard > 0) {
|
||||
shaderConstants.define("ALPHA_DISCARD", alphaDiscard);
|
||||
}
|
||||
shaderConstants.define(fogType.name());
|
||||
|
||||
return shaderConstants;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package com.jozufozu.flywheel.core.compile;
|
|||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.core.CoreShaderInfoMap;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
|
||||
|
@ -52,15 +50,13 @@ public class ProgramCompiler extends Memoizer<ProgramCompiler.Context, GlProgram
|
|||
protected GlProgram _create(ProgramCompiler.Context ctx) {
|
||||
// TODO: try-catch here to prevent crashing if shaders failed to compile
|
||||
Material material = ctx.material;
|
||||
StateSnapshot snapshot = ctx.ctx();
|
||||
FileResolution instanceShader = ctx.instanceShader();
|
||||
ContextShader contextShader = ctx.contextShader;
|
||||
|
||||
var vertex = new VertexCompiler.Context(ctx.vertexType(), instanceShader.getFile(), material.getVertexShader().getFile(),
|
||||
contextShader.getVertexShader(), snapshot);
|
||||
contextShader.getVertexShader());
|
||||
|
||||
var fragment = new FragmentCompiler.Context(material.getFragmentShader().getFile(), contextShader.getFragmentShader(),
|
||||
ctx.alphaDiscard(), ctx.fogType(), snapshot);
|
||||
var fragment = new FragmentCompiler.Context(material.getFragmentShader().getFile(), contextShader.getFragmentShader());
|
||||
|
||||
return new ProgramAssembler(instanceShader.getFileLoc())
|
||||
.attachShader(vertexCompiler.get(vertex))
|
||||
|
@ -85,12 +81,8 @@ public class ProgramCompiler extends Memoizer<ProgramCompiler.Context, GlProgram
|
|||
* @param material The material shader to use.
|
||||
* @param instanceShader The instance shader to use.
|
||||
* @param contextShader The context shader to use.
|
||||
* @param alphaDiscard Alpha threshold below which pixels are discarded.
|
||||
* @param fogType Which type of fog should be applied.
|
||||
* @param ctx A snapshot of the game state.
|
||||
*/
|
||||
public record Context(VertexType vertexType, Material material, FileResolution instanceShader,
|
||||
ContextShader contextShader, float alphaDiscard,
|
||||
CoreShaderInfoMap.CoreShaderInfo.FogType fogType, StateSnapshot ctx) {
|
||||
ContextShader contextShader) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
|
|||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
import com.jozufozu.flywheel.core.source.parse.ShaderField;
|
||||
|
@ -28,10 +27,6 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
|||
|
||||
finalSource.append(CompileUtil.generateHeader(GLSLVersion.V420, ShaderType.VERTEX));
|
||||
|
||||
var shaderConstants = key.ctx.getShaderConstants();
|
||||
shaderConstants.writeInto(finalSource);
|
||||
finalSource.append('\n');
|
||||
|
||||
var index = new CompilationContext();
|
||||
|
||||
// LAYOUT
|
||||
|
@ -82,7 +77,7 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
|||
""");
|
||||
|
||||
try {
|
||||
return new GlShader(finalSource.toString(), ShaderType.VERTEX, ImmutableList.of(layoutShader.name, instanceShader.name, materialShader.name, contextShaderSource.name), shaderConstants);
|
||||
return new GlShader(finalSource.toString(), ShaderType.VERTEX, ImmutableList.of(layoutShader.name, instanceShader.name, materialShader.name, contextShaderSource.name));
|
||||
} catch (ShaderCompilationException e) {
|
||||
throw e.withErrorLog(index);
|
||||
}
|
||||
|
@ -98,8 +93,7 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
|||
* @param instanceShader The instance shader source.
|
||||
* @param materialShader The vertex material shader source.
|
||||
* @param contextShader The context shader source.
|
||||
* @param ctx The shader constants to apply.
|
||||
*/
|
||||
public record Context(VertexType vertexType, SourceFile instanceShader, SourceFile materialShader, SourceFile contextShader, StateSnapshot ctx) {
|
||||
public record Context(VertexType vertexType, SourceFile instanceShader, SourceFile materialShader, SourceFile contextShader) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.jozufozu.flywheel.core.crumbling;
|
||||
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.core.WorldProgram;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
|
|
|
@ -145,14 +145,5 @@ public class CrumblingRenderer {
|
|||
public CrumblingEngine() {
|
||||
super(Components.CRUMBLING);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void render(RenderType type, ListMultimap<ShaderState, DrawCall> multimap) {
|
||||
if (!type.affectsCrumbling()) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.render(type, multimap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,43 @@
|
|||
package com.jozufozu.flywheel.core.material;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.RenderStage;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
|
||||
public class SimpleMaterial implements Material {
|
||||
protected final RenderStage stage;
|
||||
protected final RenderType type;
|
||||
protected final FileResolution vertexShader;
|
||||
protected final FileResolution fragmentShader;
|
||||
protected final ResourceLocation diffuseTex;
|
||||
@Nullable
|
||||
protected final Runnable setup;
|
||||
@Nullable
|
||||
protected final Runnable clear;
|
||||
|
||||
public SimpleMaterial(RenderStage stage, RenderType type, FileResolution vertexShader, FileResolution fragmentShader) {
|
||||
public SimpleMaterial(RenderStage stage, RenderType type, FileResolution vertexShader, FileResolution fragmentShader, ResourceLocation diffuseTex, @Nullable Runnable setup, @Nullable Runnable clear) {
|
||||
this.stage = stage;
|
||||
this.type = type;
|
||||
this.vertexShader = vertexShader;
|
||||
this.fragmentShader = fragmentShader;
|
||||
this.diffuseTex = diffuseTex;
|
||||
this.setup = setup;
|
||||
this.clear = clear;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,7 +46,7 @@ public class SimpleMaterial implements Material {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RenderType getRenderType() {
|
||||
public RenderType getBatchingRenderType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -38,4 +59,88 @@ public class SimpleMaterial implements Material {
|
|||
public FileResolution getFragmentShader() {
|
||||
return fragmentShader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
|
||||
GlTextureUnit.T0.makeActive();
|
||||
RenderSystem.setShaderTexture(0, diffuseTex);
|
||||
Minecraft.getInstance().textureManager.bindForSetup(diffuseTex);
|
||||
|
||||
if (setup != null) {
|
||||
setup.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
GlTextureUnit.T0.makeActive();
|
||||
RenderSystem.setShaderTexture(0, 0);
|
||||
|
||||
if (clear != null) {
|
||||
clear.run();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
protected RenderStage stage = RenderStage.AFTER_SOLID_TERRAIN;
|
||||
protected RenderType type = RenderType.solid();
|
||||
protected FileResolution vertexShader = Components.Files.SHADED_VERTEX;
|
||||
protected FileResolution fragmentShader = Components.Files.DEFAULT_FRAGMENT;
|
||||
protected ResourceLocation diffuseTex = InventoryMenu.BLOCK_ATLAS;
|
||||
protected Runnable setup = null;
|
||||
protected Runnable clear = null;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public Builder stage(RenderStage stage) {
|
||||
this.stage = stage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder renderType(RenderType type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder vertexShader(FileResolution vertexShader) {
|
||||
this.vertexShader = vertexShader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fragmentShader(FileResolution fragmentShader) {
|
||||
this.fragmentShader = fragmentShader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder shaded() {
|
||||
this.vertexShader = Components.Files.SHADED_VERTEX;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder unShaded() {
|
||||
this.vertexShader = Components.Files.DEFAULT_VERTEX;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder diffuseTex(ResourceLocation diffuseTex) {
|
||||
this.diffuseTex = diffuseTex;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder alsoSetup(Runnable runnable) {
|
||||
this.setup = runnable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder alsoClear(Runnable clear) {
|
||||
this.clear = clear;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleMaterial register() {
|
||||
return ComponentRegistry.register(new SimpleMaterial(stage, type, vertexShader, fragmentShader, diffuseTex, setup, clear));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.shader;
|
||||
|
||||
/**
|
||||
* An object that provides a view of the current game state for shader compilation.
|
||||
*/
|
||||
public interface GameStateProvider {
|
||||
|
||||
/**
|
||||
* Get the status of this game state provider.
|
||||
* @return Returning {@code true} will cause #alterConstants to be called before compiling a shader.
|
||||
*/
|
||||
boolean isTrue();
|
||||
|
||||
/**
|
||||
* Alter the constants for shader compilation.
|
||||
* @param constants The shader constants.
|
||||
*/
|
||||
void alterConstants(ShaderConstants constants);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.shader;
|
||||
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
|
||||
public enum NormalDebugStateProvider implements GameStateProvider {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public boolean isTrue() {
|
||||
return FlwConfig.get()
|
||||
.debugNormals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void alterConstants(ShaderConstants constants) {
|
||||
constants.define("DEBUG_NORMAL");
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.shader;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A class for manipulating a list of {@code #define} directives.
|
||||
*
|
||||
* <p>Based loosely on code by jellysquid3.
|
||||
*/
|
||||
public class ShaderConstants {
|
||||
|
||||
private final Map<String, String> definitions = new HashMap<>();
|
||||
|
||||
public ShaderConstants define(String def) {
|
||||
definitions.put(def, "");
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderConstants define(String def, String value) {
|
||||
definitions.put(def, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderConstants define(String def, float value) {
|
||||
definitions.put(def, Float.toString(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShaderConstants defineAll(List<String> defines) {
|
||||
for (String def : defines) {
|
||||
definitions.put(def, "");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String build() {
|
||||
final StringBuilder acc = new StringBuilder();
|
||||
writeInto(acc);
|
||||
return acc.toString();
|
||||
}
|
||||
|
||||
public void writeInto(final StringBuilder acc) {
|
||||
for (Map.Entry<String, String> e : definitions.entrySet()) {
|
||||
acc.append("#define ")
|
||||
.append(e.getKey());
|
||||
if (e.getValue().length() > 0) {
|
||||
acc.append(' ')
|
||||
.append(e.getValue());
|
||||
}
|
||||
acc.append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ShaderConstants that = (ShaderConstants) o;
|
||||
return Objects.equals(definitions, that.definitions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(definitions);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.shader;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import com.jozufozu.flywheel.core.GameStateRegistry;
|
||||
|
||||
public record StateSnapshot(BitSet ctx) {
|
||||
// TODO: is this needed?
|
||||
|
||||
public ShaderConstants getShaderConstants() {
|
||||
return GameStateRegistry.getShaderConstants(this);
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.core.shader;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
@ -29,7 +29,12 @@ public class ShaderSources implements SourceFinder {
|
|||
|
||||
public final Index index;
|
||||
|
||||
public final long loadTimeNs;
|
||||
public final long indexTimeNs;
|
||||
public final long totalTimeNs;
|
||||
|
||||
public ShaderSources(ErrorReporter errorReporter, ResourceManager manager) {
|
||||
long loadStart = System.nanoTime();
|
||||
|
||||
for (ResourceLocation location : getValidShaderFiles(manager)) {
|
||||
try (Resource resource = manager.getResource(location)) {
|
||||
|
@ -42,8 +47,15 @@ public class ShaderSources implements SourceFinder {
|
|||
//
|
||||
}
|
||||
}
|
||||
long loadEnd = System.nanoTime();
|
||||
|
||||
long indexStart = System.nanoTime();
|
||||
index = new Index(shaderSources);
|
||||
long indexEnd = System.nanoTime();
|
||||
|
||||
loadTimeNs = loadEnd - loadStart;
|
||||
indexTimeNs = indexEnd - indexStart;
|
||||
totalTimeNs = indexEnd - loadStart;
|
||||
}
|
||||
|
||||
public void postResolve() {
|
||||
|
@ -67,4 +79,8 @@ public class ShaderSources implements SourceFinder {
|
|||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public String getLoadTime() {
|
||||
return StringUtil.formatTime(totalTimeNs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import java.nio.ByteBuffer;
|
|||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -15,6 +17,20 @@ import org.lwjgl.system.MemoryUtil;
|
|||
|
||||
public class StringUtil {
|
||||
|
||||
private static final NumberFormat timeFormat = new DecimalFormat("#0.000");
|
||||
|
||||
public static String formatTime(long ns) {
|
||||
if (ns < 1000) {
|
||||
return ns + " ns";
|
||||
} else if (ns < 1000000) {
|
||||
return timeFormat.format(ns / 1000.) + " μs";
|
||||
} else if (ns < 1000000000) {
|
||||
return timeFormat.format(ns / 1000000.) + " ms";
|
||||
} else {
|
||||
return timeFormat.format(ns / 1000000000.) + " s";
|
||||
}
|
||||
}
|
||||
|
||||
public static String args(String functionName, Object... args) {
|
||||
|
||||
return functionName + '(' + Arrays.stream(args)
|
||||
|
|
|
@ -19,3 +19,16 @@ in vec4 flw_var3;
|
|||
vec4 flw_fragColor;
|
||||
ivec2 flw_fragOverlay;
|
||||
vec2 flw_fragLight;
|
||||
|
||||
/*
|
||||
* Must be implemented by materials.
|
||||
*/
|
||||
vec4 flw_fogFilter(vec4 color);
|
||||
|
||||
/*
|
||||
* May be implemented by materials.
|
||||
* If implemented, a material must define FLW_DISCARD
|
||||
*
|
||||
* Guard calls with FLW_DISCARD
|
||||
*/
|
||||
bool flw_discardPredicate(vec4 finalColor);
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
#use "flywheel:uniform/view.glsl"
|
||||
|
||||
void flw_contextVertex() {
|
||||
// TODO: remove this
|
||||
#ifdef DEBUG_NORMAL
|
||||
flw_vertexColor = vec4(flw_vertexNormal, 1.0);
|
||||
#endif
|
||||
|
||||
flw_distance = fog_distance(flw_vertexPos.xyz, flw_cameraPos.xyz, flw_fogShape);
|
||||
gl_Position = flw_viewProjection * flw_vertexPos;
|
||||
flw_vertexNormal = normalize(flw_vertexNormal);
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#use "flywheel:api/fragment.glsl"
|
||||
#use "flywheel:util/fog.glsl"
|
||||
#use "flywheel:uniform/fog.glsl"
|
||||
|
||||
uniform sampler2D flw_diffuseTex;
|
||||
|
||||
|
@ -36,17 +34,11 @@ void flw_initFragment() {
|
|||
void flw_contextFragment() {
|
||||
vec4 color = flw_fragColor;
|
||||
|
||||
#ifdef ALPHA_DISCARD
|
||||
if (color.a < ALPHA_DISCARD) {
|
||||
#ifdef FLW_DISCARD
|
||||
if (flw_discardPredicate(color)) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COLOR_FOG
|
||||
color = linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
|
||||
#elif defined(FADE_FOG)
|
||||
color = linear_fog_fade(color, flw_distance, flw_fogRange.x, flw_fogRange.y);
|
||||
#endif
|
||||
|
||||
fragColor = color;
|
||||
fragColor = flw_fogFilter(color);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#use "flywheel:api/fragment.glsl"
|
||||
#use "flywheel:util/fog.glsl"
|
||||
#use "flywheel:uniform/fog.glsl"
|
||||
|
||||
// optimize discard usage
|
||||
#ifdef ALPHA_DISCARD
|
||||
|
@ -30,17 +28,11 @@ void flw_contextFragment() {
|
|||
color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a);
|
||||
color *= lightColor;
|
||||
|
||||
#ifdef ALPHA_DISCARD
|
||||
if (color.a < ALPHA_DISCARD) {
|
||||
#ifdef FLW_DISCARD
|
||||
if (flw_discardPredicate(color)) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COLOR_FOG
|
||||
color = linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
|
||||
#elif defined(FADE_FOG)
|
||||
color = linear_fog_fade(color, flw_distance, flw_fogRange.x, flw_fogRange.y);
|
||||
#endif
|
||||
|
||||
fragColor = color;
|
||||
fragColor = flw_fogFilter(color);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#use "flywheel:api/fragment.glsl"
|
||||
#use "flywheel:util/fog.glsl"
|
||||
#use "flywheel:uniform/fog.glsl"
|
||||
|
||||
void flw_materialFragment() {
|
||||
}
|
||||
|
||||
#define FLW_DISCARD
|
||||
bool flw_discardPredicate(vec4 finalColor) {
|
||||
return finalColor.a < 0.1;
|
||||
}
|
||||
|
||||
vec4 flw_fogFilter(vec4 color) {
|
||||
return linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
|
||||
}
|
|
@ -1,4 +1,10 @@
|
|||
#use "flywheel:api/fragment.glsl"
|
||||
#use "flywheel:util/fog.glsl"
|
||||
#use "flywheel:uniform/fog.glsl"
|
||||
|
||||
void flw_materialFragment() {
|
||||
}
|
||||
|
||||
vec4 flw_fogFilter(vec4 color) {
|
||||
return linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue