Mostly untangle the loading functions, enforce triangles

This commit is contained in:
JozsefA 2021-06-04 17:55:05 -07:00
parent 9bac709dfd
commit 457fff78f3
14 changed files with 184 additions and 139 deletions

View file

@ -14,6 +14,7 @@ import org.lwjgl.opengl.GLCapabilities;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
import com.jozufozu.flywheel.backend.instancing.InstanceData; import com.jozufozu.flywheel.backend.instancing.InstanceData;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
import com.jozufozu.flywheel.core.WorldContext; import com.jozufozu.flywheel.core.WorldContext;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
@ -45,7 +46,7 @@ public class Backend {
static { static {
register(WorldContext.INSTANCE); register(WorldContext.INSTANCE);
register(WorldContext.CRUMBLING); register(InstancedRenderDispatcher.CRUMBLING);
} }
public Backend() { public Backend() {

View file

@ -1,16 +1,23 @@
package com.jozufozu.flywheel.backend; package com.jozufozu.flywheel.backend;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.collect.Lists;
import com.jozufozu.flywheel.backend.gl.GlObject;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.backend.loading.Program;
import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.Shader;
import com.jozufozu.flywheel.backend.loading.ShaderTransformer;
import com.jozufozu.flywheel.core.shader.IMultiProgram; import com.jozufozu.flywheel.core.shader.IMultiProgram;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.jozufozu.flywheel.core.shader.spec.ProgramState;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -18,57 +25,69 @@ public abstract class ShaderContext<P extends GlProgram> {
protected final Map<ResourceLocation, IMultiProgram<P>> programs = new HashMap<>(); protected final Map<ResourceLocation, IMultiProgram<P>> programs = new HashMap<>();
protected ShaderTransformer transformer = new ShaderTransformer(); protected ShaderSources sourceRepo;
public ShaderContext() {
}
// TODO: Untangle the loading functions
/** /**
* Load all programs associated with this context. This might be just one, if the context is very specialized. * Load all programs associated with this context. This might be just one, if the context is very specialized.
*/ */
public abstract void load(ShaderSources loader); public final void load(ShaderSources loader) {
this.sourceRepo = loader;
protected abstract IMultiProgram<P> loadSpecInternal(ShaderSources loader, ProgramSpec spec); load();
public void loadProgramFromSpec(ShaderSources loader, ProgramSpec programSpec) {
try {
programs.put(programSpec.name, loadSpecInternal(loader, programSpec));
Backend.log.debug("Loaded program {}", programSpec.name);
} catch (Exception e) {
Backend.log.error("Program '{}': {}", programSpec.name, e);
loader.notifyError();
}
} }
public Program loadProgram(ShaderSources loader, ProgramSpec spec, Collection<String> defines) { protected abstract void load();
Shader vertexFile = loader.source(spec.vert, ShaderType.VERTEX);
Shader fragmentFile = loader.source(spec.frag, ShaderType.FRAGMENT);
transformer.transformSource(vertexFile); public Program loadAndLink(ProgramSpec spec, @Nullable ProgramState state) {
transformer.transformSource(fragmentFile); Shader vertexFile = getSource(ShaderType.VERTEX, spec.vert);
Shader fragmentFile = getSource(ShaderType.FRAGMENT, spec.frag);
if (defines != null) { if (state != null) {
vertexFile.defineAll(defines); vertexFile.defineAll(state.getDefines());
fragmentFile.defineAll(defines); fragmentFile.defineAll(state.getDefines());
} }
Program program = loader.loadProgram(spec.name, vertexFile, fragmentFile); return link(loadProgram(spec.name, vertexFile, fragmentFile));
}
preLink(program); protected Shader getSource(ShaderType type, ResourceLocation name) {
return sourceRepo.source(name, type);
}
protected Program link(Program program) {
return program.link(); return program.link();
} }
protected void preLink(Program program) {
}
public P getProgram(ResourceLocation spec) { public P getProgram(ResourceLocation spec) {
return programs.get(spec).get(); return programs.get(spec).get();
} }
protected Program loadProgram(ResourceLocation name, Shader... shaders) {
return loadProgram(name, Lists.newArrayList(shaders));
}
/**
* Ingests the given shaders, compiling them and linking them together after applying the transformer to the source.
*
* @param name What should we call this program if something goes wrong?
* @param shaders What are the different shader stages that should be linked together?
* @return A program with all provided shaders attached
*/
protected Program loadProgram(ResourceLocation name, Collection<Shader> shaders) {
List<GlShader> compiled = new ArrayList<>(shaders.size());
try {
Program builder = new Program(name);
for (Shader shader : shaders) {
GlShader sh = new GlShader(shader);
compiled.add(sh);
builder.attachShader(shader, sh);
}
return builder;
} finally {
compiled.forEach(GlObject::delete);
}
}
} }

View file

@ -12,7 +12,6 @@ import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -26,10 +25,7 @@ import com.google.common.collect.Lists;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.jozufozu.flywheel.backend.gl.GlObject;
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.loading.Program;
import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.Shader;
import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; import com.jozufozu.flywheel.backend.loading.ShaderLoadingException;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
@ -156,43 +152,6 @@ public class ShaderSources implements ISelectiveResourceReloadListener {
return new Shader(this, type, name, getShaderSource(name)); return new Shader(this, type, name, getShaderSource(name));
} }
public Program loadProgram(ResourceLocation name, Shader... shaders) {
return loadProgram(name, Lists.newArrayList(shaders));
}
/**
* Ingests the given shaders, compiling them and linking them together after applying the transformer to the source.
*
* @param name What should we call this program if something goes wrong?
* @param shaders What are the different shader stages that should be linked together?
* @return A program with all provided shaders attached
*/
public Program loadProgram(ResourceLocation name, Collection<Shader> shaders) {
List<GlShader> compiled = new ArrayList<>(shaders.size());
try {
Program builder = new Program(name);
for (Shader shader : shaders) {
GlShader sh = new GlShader(shader);
compiled.add(sh);
builder.attachShader(shader, sh);
}
return builder;
} finally {
compiled.forEach(GlObject::delete);
}
}
private void printSource(ResourceLocation name, String source) {
Backend.log.debug("Finished processing '" + name + "':");
int i = 1;
for (String s : source.split("\n")) {
Backend.log.debug(String.format("%1$4s: ", i++) + s);
}
}
public static Stream<String> lines(String s) { public static Stream<String> lines(String s) {
return new BufferedReader(new StringReader(s)).lines(); return new BufferedReader(new StringReader(s)).lines();
} }

View file

@ -13,12 +13,10 @@ import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.RenderWork;
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.model.BufferedModel; import com.jozufozu.flywheel.backend.model.BufferedModel;
import com.jozufozu.flywheel.backend.model.IndexedModel; import com.jozufozu.flywheel.backend.model.IndexedModel;
import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.core.QuadConverter;
import com.jozufozu.flywheel.util.BufferBuilderReader; import com.jozufozu.flywheel.util.BufferBuilderReader;
import com.jozufozu.flywheel.util.RenderUtil; import com.jozufozu.flywheel.util.RenderUtil;
import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.jozufozu.flywheel.util.VirtualEmptyModelData;
@ -133,9 +131,10 @@ public class InstanceMaterial<D extends InstanceData> {
// return new BufferedModel(GlPrimitive.QUADS, format, vertices, vertexCount); // return new BufferedModel(GlPrimitive.QUADS, format, vertices, vertexCount);
return new IndexedModel(GlPrimitive.TRIANGLES, modelFormat, vertices, vertexCount, QuadConverter.getInstance().quads2Tris(vertexCount / 4)); return IndexedModel.fromSequentialQuads(modelFormat, vertices, vertexCount);
} }
// DOWN, UP, NORTH, SOUTH, WEST, EAST, null
private static final Direction[] dirs; private static final Direction[] dirs;
static { static {

View file

@ -12,8 +12,11 @@ import java.util.Vector;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.core.CrumblingInstanceManager; import com.jozufozu.flywheel.core.CrumblingInstanceManager;
import com.jozufozu.flywheel.core.CrumblingProgram;
import com.jozufozu.flywheel.core.WorldContext; import com.jozufozu.flywheel.core.WorldContext;
import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.BeginFrameEvent;
@ -35,6 +38,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.LazyValue; import net.minecraft.util.LazyValue;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
@ -44,10 +48,16 @@ import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class InstancedRenderDispatcher { public class InstancedRenderDispatcher {
private static final RenderType CRUMBLING = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); public static final ResourceLocation CRUMBLING_CONTEXT = new ResourceLocation(Flywheel.ID, "context/crumbling");
public static final WorldContext<CrumblingProgram> CRUMBLING = new WorldContext<>(CrumblingProgram::new)
.withName(CRUMBLING_CONTEXT)
.withBuiltin(ShaderType.FRAGMENT, CRUMBLING_CONTEXT, "/builtin.frag")
.withBuiltin(ShaderType.VERTEX, CRUMBLING_CONTEXT, "/builtin.vert");
private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0);
private static final WorldAttached<TileInstanceManager> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(WorldContext.INSTANCE.getMaterialManager(world))); private static final WorldAttached<TileInstanceManager> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(WorldContext.INSTANCE.getMaterialManager(world)));
public static LazyValue<Vector<CrumblingInstanceManager>> blockBreaking = new LazyValue<>(() -> { private static final LazyValue<Vector<CrumblingInstanceManager>> blockBreaking = new LazyValue<>(() -> {
Vector<CrumblingInstanceManager> renderers = new Vector<>(10); Vector<CrumblingInstanceManager> renderers = new Vector<>(10);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
renderers.add(new CrumblingInstanceManager()); renderers.add(new CrumblingInstanceManager());
@ -137,7 +147,7 @@ public class InstancedRenderDispatcher {
glActiveTexture(GL_TEXTURE4); glActiveTexture(GL_TEXTURE4);
CRUMBLING.startDrawing(); crumblingLayer.startDrawing();
bitSet.stream().forEach(i -> { bitSet.stream().forEach(i -> {
Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(i)); Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(i));
CrumblingInstanceManager renderer = renderers.get(i); CrumblingInstanceManager renderer = renderers.get(i);
@ -150,7 +160,7 @@ public class InstancedRenderDispatcher {
renderer.invalidate(); renderer.invalidate();
}); });
CRUMBLING.endDrawing(); crumblingLayer.endDrawing();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0)); Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0));

View file

@ -14,6 +14,7 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.ShaderSources;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
@ -134,6 +135,14 @@ public class Shader {
}); });
} }
public void printSource() {
Backend.log.debug("Source for shader '" + name + "':");
int i = 1;
for (String s : source.split("\n")) {
Backend.log.debug(String.format("%1$4s: ", i++) + s);
}
}
public static Stream<String> lines(String s) { public static Stream<String> lines(String s) {
return new BufferedReader(new StringReader(s)).lines(); return new BufferedReader(new StringReader(s)).lines();
} }

View file

@ -7,17 +7,27 @@ import org.lwjgl.opengl.GL20;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlPrimitive; import com.jozufozu.flywheel.backend.gl.GlPrimitive;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.core.QuadConverter;
/**
* An indexed triangle model. Just what the driver ordered.
*
* <br><em>This should be favored over a normal BufferedModel.</em>
*/
public class IndexedModel extends BufferedModel { public class IndexedModel extends BufferedModel {
protected ElementBuffer ebo; protected ElementBuffer ebo;
public IndexedModel(GlPrimitive primitiveMode, VertexFormat modelFormat, ByteBuffer buf, int vertices, ElementBuffer ebo) { public IndexedModel(VertexFormat modelFormat, ByteBuffer buf, int vertices, ElementBuffer ebo) {
super(primitiveMode, modelFormat, buf, vertices); super(GlPrimitive.TRIANGLES, modelFormat, buf, vertices);
this.ebo = ebo; this.ebo = ebo;
} }
public static IndexedModel fromSequentialQuads(VertexFormat modelFormat, ByteBuffer quads, int vertices) {
return new IndexedModel(modelFormat, quads, vertices, QuadConverter.getInstance().quads2Tris(vertices / 4));
}
@Override @Override
public void setupState() { public void setupState() {
super.setupState(); super.setupState();

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.core; package com.jozufozu.flywheel.core;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; import com.jozufozu.flywheel.backend.instancing.TileInstanceManager;
@ -7,7 +8,7 @@ import net.minecraft.util.math.BlockPos;
public class CrumblingInstanceManager extends TileInstanceManager { public class CrumblingInstanceManager extends TileInstanceManager {
public CrumblingInstanceManager() { public CrumblingInstanceManager() {
super(new MaterialManager<>(WorldContext.CRUMBLING)); super(new MaterialManager<>(InstancedRenderDispatcher.CRUMBLING));
} }
@Override @Override

View file

@ -25,7 +25,6 @@ import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram;
import com.jozufozu.flywheel.core.shader.IMultiProgram; import com.jozufozu.flywheel.core.shader.IMultiProgram;
import com.jozufozu.flywheel.core.shader.StateSensitiveMultiProgram; import com.jozufozu.flywheel.core.shader.StateSensitiveMultiProgram;
import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.WorldAttached;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -36,10 +35,14 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
private static final String declaration = "#flwbuiltins"; private static final String declaration = "#flwbuiltins";
private static final Pattern builtinPattern = Pattern.compile(declaration); private static final Pattern builtinPattern = Pattern.compile(declaration);
public static final WorldContext<WorldProgram> INSTANCE = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/world"), WorldProgram::new); public static final ResourceLocation WORLD_CONTEXT = new ResourceLocation(Flywheel.ID, "context/world");
public static final WorldContext<CrumblingProgram> CRUMBLING = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/crumbling"), CrumblingProgram::new);
protected final ResourceLocation name; public static final WorldContext<WorldProgram> INSTANCE = new WorldContext<>(WorldProgram::new)
.withName(WORLD_CONTEXT)
.withBuiltin(ShaderType.FRAGMENT, WORLD_CONTEXT, "/builtin.frag")
.withBuiltin(ShaderType.VERTEX, WORLD_CONTEXT, "/builtin.vert");
protected ResourceLocation name;
protected Supplier<Stream<ResourceLocation>> specStream; protected Supplier<Stream<ResourceLocation>> specStream;
protected TemplateFactory templateFactory; protected TemplateFactory templateFactory;
@ -50,11 +53,8 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
private final ExtensibleGlProgram.Factory<P> factory; private final ExtensibleGlProgram.Factory<P> factory;
public WorldContext(ResourceLocation root, ExtensibleGlProgram.Factory<P> factory) { public WorldContext(ExtensibleGlProgram.Factory<P> factory) {
this.factory = factory; this.factory = factory;
this.name = root;
builtins.put(ShaderType.FRAGMENT, ResourceUtil.subPath(root, "/builtin.frag"));
builtins.put(ShaderType.VERTEX, ResourceUtil.subPath(root, "/builtin.vert"));
specStream = () -> Backend.allMaterials() specStream = () -> Backend.allMaterials()
.stream() .stream()
@ -63,60 +63,88 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
templateFactory = InstancedArraysTemplate::new; templateFactory = InstancedArraysTemplate::new;
} }
public WorldContext<P> withName(ResourceLocation name) {
this.name = name;
return this;
}
public WorldContext<P> withBuiltin(ShaderType shaderType, ResourceLocation folder, String file) {
return withBuiltin(shaderType, ResourceUtil.subPath(folder, file));
}
public WorldContext<P> withBuiltin(ShaderType shaderType, ResourceLocation file) {
builtins.put(shaderType, file);
return this;
}
public MaterialManager<P> getMaterialManager(IWorld world) { public MaterialManager<P> getMaterialManager(IWorld world) {
return materialManager.get(world); return materialManager.get(world);
} }
public WorldContext<P> setSpecStream(Supplier<Stream<ResourceLocation>> specStream) { public WorldContext<P> withSpecStream(Supplier<Stream<ResourceLocation>> specStream) {
this.specStream = specStream; this.specStream = specStream;
return this; return this;
} }
public WorldContext<P> setTemplateFactory(TemplateFactory templateFactory) { public WorldContext<P> withTemplateFactory(TemplateFactory templateFactory) {
this.templateFactory = templateFactory; this.templateFactory = templateFactory;
return this; return this;
} }
@Override protected ShaderTransformer transformer;
protected IMultiProgram<P> loadSpecInternal(ShaderSources loader, ProgramSpec spec) {
return new StateSensitiveMultiProgram<>(loader, factory, this, spec);
}
protected ProgramTemplate template; protected ProgramTemplate template;
@Override @Override
public void load(ShaderSources loader) { public void load() {
programs.values().forEach(IMultiProgram::delete); programs.values().forEach(IMultiProgram::delete);
programs.clear(); programs.clear();
Backend.log.info("Loading context '{}'", name); Backend.log.info("Loading context '{}'", name);
try { try {
builtins.forEach((type, resourceLocation) -> builtinSources.put(type, loader.getShaderSource(resourceLocation))); builtins.forEach((type, resourceLocation) -> builtinSources.put(type, sourceRepo.getShaderSource(resourceLocation)));
} catch (ShaderLoadingException e) { } catch (ShaderLoadingException e) {
loader.notifyError(); sourceRepo.notifyError();
Backend.log.error(String.format("Could not find builtin: %s", e.getMessage())); Backend.log.error(String.format("Could not find builtin: %s", e.getMessage()));
return; return;
} }
template = templateFactory.create(loader); template = templateFactory.create(sourceRepo);
transformer = new ShaderTransformer() transformer = new ShaderTransformer()
.pushStage(this::injectBuiltins) .pushStage(this::injectBuiltins)
.pushStage(Shader::processIncludes) .pushStage(Shader::processIncludes)
.pushStage(Shader::parseStructs)
.pushStage(template) .pushStage(template)
.pushStage(Shader::processIncludes); .pushStage(Shader::processIncludes);
specStream.get() specStream.get()
.map(Backend::getSpec) .map(Backend::getSpec)
.forEach(spec -> loadProgramFromSpec(loader, spec)); .forEach(spec -> {
try {
programs.put(spec.name, new StateSensitiveMultiProgram<>(factory, this, spec));
Backend.log.debug("Loaded program {}", spec.name);
} catch (Exception e) {
Backend.log.error("Program '{}': {}", spec.name, e);
sourceRepo.notifyError();
}
});
} }
@Override @Override
protected void preLink(Program program) { protected Shader getSource(ShaderType type, ResourceLocation name) {
Shader source = super.getSource(type, name);
transformer.transformSource(source);
return source;
}
@Override
protected Program link(Program program) {
template.attachAttributes(program); template.attachAttributes(program);
return super.link(program);
} }
/** /**

View file

@ -1,11 +1,9 @@
package com.jozufozu.flywheel.core.shader; package com.jozufozu.flywheel.core.shader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderSources;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.backend.loading.Program;
import com.jozufozu.flywheel.core.shader.spec.IContextCondition; import com.jozufozu.flywheel.core.shader.spec.IContextCondition;
@ -18,19 +16,19 @@ public class StateSensitiveMultiProgram<P extends GlProgram> implements IMultiPr
List<Pair<IContextCondition, P>> variants; List<Pair<IContextCondition, P>> variants;
P fallback; P fallback;
public StateSensitiveMultiProgram(ShaderSources loader, ExtensibleGlProgram.Factory<P> factory, ShaderContext<P> context, ProgramSpec p) { public StateSensitiveMultiProgram(ExtensibleGlProgram.Factory<P> factory, ShaderContext<P> context, ProgramSpec p) {
variants = new ArrayList<>(p.states.size()); variants = new ArrayList<>(p.states.size());
for (ProgramState state : p.states) { for (ProgramState state : p.states) {
Program variant = context.loadProgram(loader, p, state.getDefines()); Program variant = context.loadAndLink(p, state);
Pair<IContextCondition, P> pair = Pair.of(state.getContext(), factory.create(variant, state.getExtensions())); Pair<IContextCondition, P> pair = Pair.of(state.getContext(), factory.create(variant, state.getExtensions()));
variants.add(pair); variants.add(pair);
} }
fallback = factory.create(context.loadProgram(loader, p, Collections.emptyList())); fallback = factory.create(context.loadAndLink(p, null));
} }
@Override @Override

View file

@ -2,14 +2,12 @@ package com.simibubi.create.content.contraptions.components.structureMovement.gl
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
import com.jozufozu.flywheel.backend.instancing.ITickableInstance; import com.jozufozu.flywheel.backend.instancing.ITickableInstance;
import com.jozufozu.flywheel.backend.instancing.Instancer; import com.jozufozu.flywheel.backend.instancing.Instancer;
import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.jozufozu.flywheel.backend.instancing.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
import com.jozufozu.flywheel.backend.model.BufferedModel; import com.jozufozu.flywheel.backend.model.BufferedModel;
import com.jozufozu.flywheel.backend.model.IndexedModel; import com.jozufozu.flywheel.backend.model.IndexedModel;
import com.jozufozu.flywheel.core.QuadConverter;
import com.jozufozu.flywheel.core.instancing.ConditionalInstance; import com.jozufozu.flywheel.core.instancing.ConditionalInstance;
import com.jozufozu.flywheel.core.materials.OrientedData; import com.jozufozu.flywheel.core.materials.OrientedData;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -111,6 +109,6 @@ public class GlueInstance extends EntityInstance<SuperGlueEntity> implements ITi
ByteBuffer buffer = ByteBuffer.allocate(quads.length * 4); ByteBuffer buffer = ByteBuffer.allocate(quads.length * 4);
buffer.asFloatBuffer().put(quads); buffer.asFloatBuffer().put(quads);
return new IndexedModel(GlPrimitive.TRIANGLES, AllMaterialSpecs.UNLIT_MODEL, buffer, 8, QuadConverter.getInstance().quads2Tris(2)); return IndexedModel.fromSequentialQuads(AllMaterialSpecs.UNLIT_MODEL, buffer, 8);
} }
} }

View file

@ -16,6 +16,7 @@ import java.util.stream.Stream;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.loading.ModelTemplate; import com.jozufozu.flywheel.backend.loading.ModelTemplate;
import com.jozufozu.flywheel.core.WorldContext; import com.jozufozu.flywheel.core.WorldContext;
import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.BeginFrameEvent;
@ -74,10 +75,10 @@ public class ContraptionRenderDispatcher {
public static final Compartment<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>(); public static final Compartment<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>();
private static final ResourceLocation ctxRoot = new ResourceLocation("create", "context/contraption"); private static final ResourceLocation ctxRoot = new ResourceLocation("create", "context/contraption");
public static final WorldContext<ContraptionProgram> STRUCTURE = new WorldContext<>(ctxRoot, ContraptionProgram::new) public static final WorldContext<ContraptionProgram> TILES = contraptionContext();
.setSpecStream(() -> Stream.of(AllProgramSpecs.STRUCTURE)) public static final WorldContext<ContraptionProgram> STRUCTURE = contraptionContext()
.setTemplateFactory(ModelTemplate::new); .withSpecStream(() -> Stream.of(AllProgramSpecs.STRUCTURE))
public static final WorldContext<ContraptionProgram> TILES = new WorldContext<>(ctxRoot, ContraptionProgram::new); .withTemplateFactory(ModelTemplate::new);
public static void tick() { public static void tick() {
if (Minecraft.getInstance().isGamePaused()) return; if (Minecraft.getInstance().isGamePaused()) return;
@ -341,4 +342,11 @@ public class ContraptionRenderDispatcher {
public static void removeDeadHolders() { public static void removeDeadHolders() {
WORLD_HOLDERS.values().removeIf(ContraptionWorldHolder::isDead); WORLD_HOLDERS.values().removeIf(ContraptionWorldHolder::isDead);
} }
private static WorldContext<ContraptionProgram> contraptionContext() {
return new WorldContext<>(ContraptionProgram::new)
.withName(ctxRoot)
.withBuiltin(ShaderType.FRAGMENT, ctxRoot, "/builtin.frag")
.withBuiltin(ShaderType.VERTEX, ctxRoot, "/builtin.vert");
}
} }

View file

@ -10,7 +10,6 @@ import java.util.Map;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes; import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
@ -19,7 +18,6 @@ import com.jozufozu.flywheel.backend.model.ArrayModelRenderer;
import com.jozufozu.flywheel.backend.model.BufferedModel; import com.jozufozu.flywheel.backend.model.BufferedModel;
import com.jozufozu.flywheel.backend.model.IndexedModel; import com.jozufozu.flywheel.backend.model.IndexedModel;
import com.jozufozu.flywheel.backend.model.ModelRenderer; import com.jozufozu.flywheel.backend.model.ModelRenderer;
import com.jozufozu.flywheel.core.QuadConverter;
import com.jozufozu.flywheel.light.GridAlignedBB; import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.util.BufferBuilderReader; import com.jozufozu.flywheel.util.BufferBuilderReader;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
@ -203,6 +201,6 @@ public class RenderedContraption extends ContraptionWorldHolder {
vertices.rewind(); vertices.rewind();
return new IndexedModel(GlPrimitive.TRIANGLES, format, vertices, vertexCount, QuadConverter.getInstance().quads2Tris(vertexCount / 4)); return IndexedModel.fromSequentialQuads(format, vertices, vertexCount);
} }
} }

View file

@ -1,16 +1,14 @@
package com.simibubi.create.foundation.render.effects; package com.simibubi.create.foundation.render.effects;
import java.util.Collections;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.Shader;
import com.jozufozu.flywheel.backend.loading.ShaderTransformer;
import com.jozufozu.flywheel.core.shader.IMultiProgram;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.simibubi.create.foundation.render.AllProgramSpecs; import com.simibubi.create.foundation.render.AllProgramSpecs;
import net.minecraft.util.ResourceLocation;
public class EffectsContext extends ShaderContext<SphereFilterProgram> { public class EffectsContext extends ShaderContext<SphereFilterProgram> {
public static final EffectsContext INSTANCE = new EffectsContext(); public static final EffectsContext INSTANCE = new EffectsContext();
@ -20,14 +18,23 @@ public class EffectsContext extends ShaderContext<SphereFilterProgram> {
} }
@Override @Override
protected IMultiProgram<SphereFilterProgram> loadSpecInternal(ShaderSources loader, ProgramSpec spec) { public void load() {
return new SphereFilterProgram(loadProgram(loader, spec, Collections.emptyList())); ProgramSpec programSpec = Backend.getSpec(AllProgramSpecs.CHROMATIC);
try {
programs.put(programSpec.name, new SphereFilterProgram(loadAndLink(programSpec, null)));
Backend.log.debug("Loaded program {}", programSpec.name);
} catch (Exception e) {
Backend.log.error("Program '{}': {}", programSpec.name, e);
sourceRepo.notifyError();
}
} }
@Override @Override
public void load(ShaderSources loader) { protected Shader getSource(ShaderType type, ResourceLocation name) {
transformer = new ShaderTransformer() Shader source = super.getSource(type, name);
.pushStage(Shader::processIncludes); source.processIncludes();
loadProgramFromSpec(loader, Backend.getSpec(AllProgramSpecs.CHROMATIC)); return source;
} }
} }