Move to the template system and overhaul instance attributes

- All material shaders now use the template system.
 - Because of the template system, we can know what attributes a material has, along with how they're formatted.
 - All of the *Attribute enums are effectively inlined, as the context they used to provide is no longer needed.
This commit is contained in:
JozsefA 2021-05-18 14:05:52 -07:00
parent 695fe98d28
commit 55703d8838
67 changed files with 739 additions and 1123 deletions

View file

@ -6,9 +6,11 @@ import static org.lwjgl.opengl.GL20.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL20.glActiveTexture; import static org.lwjgl.opengl.GL20.glActiveTexture;
import static org.lwjgl.opengl.GL20.glBindTexture; import static org.lwjgl.opengl.GL20.glBindTexture;
import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
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.SortedSet; import java.util.SortedSet;
import java.util.Vector; import java.util.Vector;
@ -76,7 +78,7 @@ public class Backend {
private static boolean enabled; private static boolean enabled;
static final Map<ResourceLocation, MaterialSpec<?>> materialRegistry = new HashMap<>(); static final Map<ResourceLocation, MaterialSpec<?>> materialRegistry = new HashMap<>();
static final Map<ResourceLocation, ShaderContext<?>> contexts = new HashMap<>(); static final List<ShaderContext<?>> contexts = new ArrayList<>();
static final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>(); static final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>();
static { static {
@ -119,11 +121,7 @@ public class Backend {
* Register a shader context. * Register a shader context.
*/ */
public static <P extends GlProgram> ShaderContext<P> register(ShaderContext<P> spec) { public static <P extends GlProgram> ShaderContext<P> register(ShaderContext<P> spec) {
ResourceLocation name = spec.getRoot(); contexts.add(spec);
if (contexts.containsKey(name)) {
throw new IllegalStateException("Program spec '" + name + "' already registered.");
}
contexts.put(name, spec);
return spec; return spec;
} }

View file

@ -6,9 +6,12 @@ import java.util.Map;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.backend.gl.shader.IMultiProgram; import com.jozufozu.flywheel.backend.gl.shader.IMultiProgram;
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec; import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
import com.jozufozu.flywheel.backend.gl.shader.ShaderConstants;
import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader; import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader;
import com.jozufozu.flywheel.backend.loading.ProcessingStage; 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.ShaderTransformer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -17,27 +20,49 @@ public abstract class ShaderContext<P extends GlProgram> {
public final Map<ProgramSpec, IMultiProgram<P>> programs = new HashMap<>(); public final Map<ProgramSpec, IMultiProgram<P>> programs = new HashMap<>();
public final ResourceLocation root; public final ResourceLocation root;
protected final ShaderSpecLoader<P> specLoader;
protected ShaderTransformer transformer = new ShaderTransformer();
public ShaderContext(ResourceLocation root) { public ShaderContext(ResourceLocation root, ShaderSpecLoader<P> specLoader) {
this.root = root; this.root = root;
this.specLoader = specLoader;
} }
public abstract ShaderSpecLoader<P> getLoader(); // TODO: Untangle the loading functions
/**
* Load all programs associated with this context. This might be just one, if the context is very specialized.
*/
public abstract void load(ShaderLoader loader); public abstract void load(ShaderLoader loader);
public void loadProgramFromSpec(ShaderLoader loader, ProgramSpec programSpec) { public void loadProgramFromSpec(ShaderLoader loader, ProgramSpec programSpec) {
programs.put(programSpec, getLoader().create(loader, this, programSpec)); programs.put(programSpec, specLoader.create(loader, this, programSpec));
Backend.log.debug("Loaded program {}", programSpec.name); Backend.log.debug("Loaded program {}", programSpec.name);
} }
public void preProcess(ShaderLoader loader, Shader shader) { public Program loadProgram(ProgramSpec spec, ShaderConstants defines, ShaderLoader loader) {
if (defines != null)
transformer.pushStage(defines);
Shader vertexFile = loader.source(spec.vert, ShaderType.VERTEX);
Shader fragmentFile = loader.source(spec.frag, ShaderType.FRAGMENT);
transformer.transformSource(vertexFile);
transformer.transformSource(fragmentFile);
Program program = loader.loadProgram(spec.name, vertexFile, fragmentFile);
if (defines != null)
transformer.popStage();
preLink(program);
return program.link();
} }
public ProcessingStage loadingStage(ShaderLoader loader) { protected void preLink(Program program) {
return shader -> this.preProcess(loader, shader);
} }
public P getProgram(ProgramSpec spec) { public P getProgram(ProgramSpec spec) {

View file

@ -27,11 +27,10 @@ import org.lwjgl.system.MemoryUtil;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.GlObject;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.backend.gl.shader.GlShader; 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.ShaderTransformer;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.resources.IResource; import net.minecraft.resources.IResource;
@ -59,26 +58,7 @@ public class ShaderLoader {
shaderSource.clear(); shaderSource.clear();
loadShaderSources(manager); loadShaderSources(manager);
// InstancedArraysTemplate template = new InstancedArraysTemplate(this); for (ShaderContext<?> context : Backend.contexts) {
//
// ResourceLocation name = new ResourceLocation("create", "test");
// ResourceLocation vert = new ResourceLocation("create", "model_new.vert");
// ResourceLocation frag = new ResourceLocation("create", "block_new.frag");
//
// ShaderTransformer transformer = new ShaderTransformer()
// .pushStage(WorldContext.INSTANCE.loadingStage(this))
// .pushStage(this::processIncludes)
// .pushStage(template)
// .pushStage(this::processIncludes);
//
// Shader vertexFile = this.source(vert, ShaderType.VERTEX);
// Shader fragmentFile = this.source(frag, ShaderType.FRAGMENT);
//
// GlProgram.Builder builder = loadProgram(name, transformer, vertexFile, fragmentFile);
//
// BasicProgram program = new BasicProgram(builder, GlFogMode.NONE.getFogFactory());
for (ShaderContext<?> context : Backend.contexts.values()) {
context.load(this); context.load(this);
} }
@ -122,32 +102,30 @@ public class ShaderLoader {
return new Shader(type, name, getShaderSource(name)); return new Shader(type, name, getShaderSource(name));
} }
public GlProgram.Builder loadProgram(ResourceLocation name, ShaderTransformer transformer, Shader... shaders) { public Program loadProgram(ResourceLocation name, Shader... shaders) {
return loadProgram(name, transformer, Lists.newArrayList(shaders)); return loadProgram(name, Lists.newArrayList(shaders));
} }
/** /**
* Ingests the given shaders, compiling them and linking them together after applying the transformer to the source. * 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 name What should we call this program if something goes wrong?
* @param transformer What should we do to the sources before compilation?
* @param shaders What are the different shader stages that should be linked together? * @param shaders What are the different shader stages that should be linked together?
* @return A linked program builder. * @return A program with all provided shaders attached
*/ */
public GlProgram.Builder loadProgram(ResourceLocation name, ShaderTransformer transformer, Collection<Shader> shaders) { public Program loadProgram(ResourceLocation name, Collection<Shader> shaders) {
List<GlShader> compiled = new ArrayList<>(shaders.size()); List<GlShader> compiled = new ArrayList<>(shaders.size());
try { try {
GlProgram.Builder builder = GlProgram.builder(name); Program builder = new Program(name);
for (Shader shader : shaders) { for (Shader shader : shaders) {
transformer.transformSource(shader);
GlShader sh = new GlShader(shader); GlShader sh = new GlShader(shader);
compiled.add(sh); compiled.add(sh);
builder.attachShader(sh); builder.attachShader(shader, sh);
} }
return builder.link(); return builder;
} finally { } finally {
compiled.forEach(GlObject::delete); compiled.forEach(GlObject::delete);
} }
@ -180,7 +158,7 @@ public class ShaderLoader {
ResourceLocation include = new ResourceLocation(includeName); ResourceLocation include = new ResourceLocation(includeName);
if (seen.add(include)) { if (seen.add(include)) {
String includeSource = shaderSource.get(include); String includeSource = getShaderSource(include);
if (includeSource != null) { if (includeSource != null) {
return includeRecursive(includeSource, seen); return includeRecursive(includeSource, seen);

View file

@ -5,6 +5,7 @@ import static org.lwjgl.opengl.GL20.glUniform3f;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.backend.gl.shader.ProgramFogMode; import com.jozufozu.flywheel.backend.gl.shader.ProgramFogMode;
import com.jozufozu.flywheel.backend.loading.Program;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -20,7 +21,7 @@ public class BasicProgram extends GlProgram {
protected int uBlockAtlas; protected int uBlockAtlas;
protected int uLightMap; protected int uLightMap;
public BasicProgram(GlProgram.Builder builder, ProgramFogMode.Factory fogFactory) { public BasicProgram(Program builder, ProgramFogMode.Factory fogFactory) {
this(builder.name, builder.program, fogFactory); this(builder.name, builder.program, fogFactory);
} }

View file

@ -2,8 +2,10 @@ package com.jozufozu.flywheel.backend.core;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Stream;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.ResourceUtil; import com.jozufozu.flywheel.backend.ResourceUtil;
@ -11,10 +13,15 @@ import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderLoader; import com.jozufozu.flywheel.backend.ShaderLoader;
import com.jozufozu.flywheel.backend.gl.shader.FogSensitiveProgram; import com.jozufozu.flywheel.backend.gl.shader.FogSensitiveProgram;
import com.jozufozu.flywheel.backend.gl.shader.IMultiProgram; import com.jozufozu.flywheel.backend.gl.shader.IMultiProgram;
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader; import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate;
import com.jozufozu.flywheel.backend.loading.Program;
import com.jozufozu.flywheel.backend.loading.ProgramTemplate;
import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.Shader;
import com.jozufozu.flywheel.backend.loading.ShaderTransformer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -23,20 +30,30 @@ public class WorldContext<P extends BasicProgram> 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<BasicProgram> INSTANCE = new WorldContext<>(new ResourceLocation("create", "context/std"), new FogSensitiveProgram.SpecLoader<>(BasicProgram::new)); public static final WorldContext<BasicProgram> INSTANCE = new WorldContext<>(new ResourceLocation("create", "context/world"), new FogSensitiveProgram.SpecLoader<>(BasicProgram::new));
public static final WorldContext<CrumblingProgram> CRUMBLING = new WorldContext<>(new ResourceLocation("create", "context/crumbling"), new FogSensitiveProgram.SpecLoader<>(CrumblingProgram::new)); public static final WorldContext<CrumblingProgram> CRUMBLING = new WorldContext<>(new ResourceLocation("create", "context/crumbling"), new FogSensitiveProgram.SpecLoader<>(CrumblingProgram::new));
private final ShaderSpecLoader<P> loader;
final Map<ShaderType, ResourceLocation> builtins; final Map<ShaderType, ResourceLocation> builtins;
final Map<ShaderType, String> builtinSources;
protected ProgramTemplate template;
protected final Supplier<Stream<ProgramSpec>> specStream;
protected final TemplateFactory templateFactory;
public WorldContext(ResourceLocation root, ShaderSpecLoader<P> loader) { public WorldContext(ResourceLocation root, ShaderSpecLoader<P> loader) {
super(root); this(root, loader, () -> Backend.allMaterials()
.stream()
.map(MaterialSpec::getProgramSpec), InstancedArraysTemplate::new);
}
public WorldContext(ResourceLocation root, ShaderSpecLoader<P> loader, Supplier<Stream<ProgramSpec>> specStream, TemplateFactory templateFactory) {
super(root, loader);
this.specStream = specStream;
this.templateFactory = templateFactory;
builtins = new EnumMap<>(ShaderType.class); builtins = new EnumMap<>(ShaderType.class);
builtinSources = new EnumMap<>(ShaderType.class);
builtins.put(ShaderType.FRAGMENT, ResourceUtil.subPath(root, "/builtin.frag")); builtins.put(ShaderType.FRAGMENT, ResourceUtil.subPath(root, "/builtin.frag"));
builtins.put(ShaderType.VERTEX, ResourceUtil.subPath(root, "/builtin.vert")); builtins.put(ShaderType.VERTEX, ResourceUtil.subPath(root, "/builtin.vert"));
this.loader = loader;
} }
@Override @Override
@ -44,26 +61,37 @@ public class WorldContext<P extends BasicProgram> extends ShaderContext<P> {
programs.values().forEach(IMultiProgram::delete); programs.values().forEach(IMultiProgram::delete);
programs.clear(); programs.clear();
Backend.allMaterials() builtins.forEach((type, resourceLocation) -> builtinSources.put(type, loader.getShaderSource(resourceLocation)));
.stream()
.map(MaterialSpec::getProgramSpec) template = templateFactory.create(loader);
.forEach(spec -> loadProgramFromSpec(loader, spec)); transformer = new ShaderTransformer()
.pushStage(this::injectBuiltins)
.pushStage(loader::processIncludes)
.pushStage(Shader::parseStructs)
.pushStage(template)
.pushStage(loader::processIncludes);
specStream.get().forEach(spec -> loadProgramFromSpec(loader, spec));
} }
@Override @Override
public void preProcess(ShaderLoader loader, Shader shader) { protected void preLink(Program program) {
String builtinSrc = loader.getShaderSource(builtins.get(shader.type)); template.attachAttributes(program);
}
/**
* Replace #flwbuiltins with whatever expansion this context provides for the given shader.
*/
public void injectBuiltins(Shader shader) {
Matcher matcher = builtinPattern.matcher(shader.getSource()); Matcher matcher = builtinPattern.matcher(shader.getSource());
if (matcher.find()) if (matcher.find())
shader.setSource(matcher.replaceFirst(builtinSrc)); shader.setSource(matcher.replaceFirst(builtinSources.get(shader.type)));
else else
throw new RuntimeException(String.format("%s shader '%s' is missing %s, cannot use in World Context", shader.type.name, shader.name, declaration)); throw new RuntimeException(String.format("%s shader '%s' is missing %s, cannot use in World Context", shader.type.name, shader.name, declaration));
} }
@Override public interface TemplateFactory {
public ShaderSpecLoader<P> getLoader() { ProgramTemplate create(ShaderLoader loader);
return loader;
} }
} }

View file

@ -1,39 +0,0 @@
package com.jozufozu.flywheel.backend.core.materials;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
public enum BasicAttributes implements IVertexAttrib {
LIGHT("aLight", CommonAttributes.LIGHT),
COLOR("aColor", CommonAttributes.RGBA),
;
private final String name;
private final IAttribSpec spec;
BasicAttributes(String name, IAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 0;
}
@Override
public int getBufferIndex() {
return 0;
}
}

View file

@ -1,41 +0,0 @@
package com.jozufozu.flywheel.backend.core.materials;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.gl.attrib.VertexAttribSpec;
public enum ModelAttributes implements IVertexAttrib {
VERTEX_POSITION("aPos", CommonAttributes.VEC3),
NORMAL("aNormal", CommonAttributes.NORMAL),
TEXTURE("aTexCoords", CommonAttributes.UV),
;
private final String name;
private final VertexAttribSpec spec;
ModelAttributes(String name, VertexAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 0;
}
@Override
public int getBufferIndex() {
return 0;
}
}

View file

@ -1,40 +0,0 @@
package com.jozufozu.flywheel.backend.core.materials;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
public enum OrientedAttributes implements IVertexAttrib {
INSTANCE_POS("aInstancePos", CommonAttributes.VEC3),
PIVOT("aPivot", CommonAttributes.VEC3),
ROTATION("aRotation", CommonAttributes.QUATERNION),
;
private final String name;
private final IAttribSpec spec;
OrientedAttributes(String name, IAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 0;
}
@Override
public int getBufferIndex() {
return 0;
}
}

View file

@ -1,39 +0,0 @@
package com.jozufozu.flywheel.backend.core.materials;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.gl.attrib.MatrixAttributes;
public enum TransformAttributes implements IVertexAttrib {
TRANSFORM("aTransform", MatrixAttributes.MAT4),
NORMAL_MAT("aNormalMat", MatrixAttributes.MAT3),
;
private final String name;
private final IAttribSpec spec;
TransformAttributes(String name, IAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 0;
}
@Override
public int getBufferIndex() {
return 0;
}
}

View file

@ -1,5 +1,12 @@
package com.jozufozu.flywheel.backend.gl; package com.jozufozu.flywheel.backend.gl;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
@ -15,6 +22,10 @@ public enum GlPrimitiveType {
UINT(4, "uint", GL11.GL_UNSIGNED_INT), UINT(4, "uint", GL11.GL_UNSIGNED_INT),
INT(4, "int", GL11.GL_INT); INT(4, "int", GL11.GL_INT);
private static final GlPrimitiveType[] VALUES = values();
private static final Map<String, GlPrimitiveType> NAME_LOOKUP = Arrays.stream(VALUES)
.collect(Collectors.toMap(GlPrimitiveType::getDisplayName, type -> type));
private final int size; private final int size;
private final String displayName; private final String displayName;
private final int glConstant; private final int glConstant;
@ -36,4 +47,9 @@ public enum GlPrimitiveType {
public int getGlConstant() { public int getGlConstant() {
return this.glConstant; return this.glConstant;
} }
@Nullable
public static GlPrimitiveType byName(String name) {
return name == null ? null : NAME_LOOKUP.get(name.toLowerCase(Locale.ROOT));
}
} }

View file

@ -1,12 +0,0 @@
package com.jozufozu.flywheel.backend.gl.attrib;
public interface IVertexAttrib {
String attribName();
IAttribSpec attribSpec();
int getDivisor();
int getBufferIndex();
}

View file

@ -1,21 +1,20 @@
package com.jozufozu.flywheel.backend.gl.attrib; package com.jozufozu.flywheel.backend.gl.attrib;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Collections;
public class VertexFormat { public class VertexFormat {
private final ArrayList<IVertexAttrib> allAttributes; private final ArrayList<IAttribSpec> allAttributes;
private final int numAttributes; private final int numAttributes;
private final int stride; private final int stride;
public VertexFormat(ArrayList<IVertexAttrib> allAttributes) { public VertexFormat(ArrayList<IAttribSpec> allAttributes) {
this.allAttributes = allAttributes; this.allAttributes = allAttributes;
int numAttributes = 0, stride = 0; int numAttributes = 0, stride = 0;
for (IVertexAttrib attrib : allAttributes) { for (IAttribSpec spec : allAttributes) {
IAttribSpec spec = attrib.attribSpec();
numAttributes += spec.getAttributeCount(); numAttributes += spec.getAttributeCount();
stride += spec.getSize(); stride += spec.getSize();
} }
@ -33,8 +32,7 @@ public class VertexFormat {
public void vertexAttribPointers(int index) { public void vertexAttribPointers(int index) {
int offset = 0; int offset = 0;
for (IVertexAttrib attrib : this.allAttributes) { for (IAttribSpec spec : this.allAttributes) {
IAttribSpec spec = attrib.attribSpec();
spec.vertexAttribPointer(stride, index, offset); spec.vertexAttribPointer(stride, index, offset);
index += spec.getAttributeCount(); index += spec.getAttributeCount();
offset += spec.getSize(); offset += spec.getSize();
@ -45,16 +43,14 @@ public class VertexFormat {
return new Builder(); return new Builder();
} }
public static class Builder { public static class Builder {
private final ArrayList<IVertexAttrib> allAttributes; private final ArrayList<IAttribSpec> allAttributes = new ArrayList<>();
public Builder() { public Builder() {
allAttributes = new ArrayList<>();
} }
public <A extends Enum<A> & IVertexAttrib> Builder addAttributes(Class<A> attribEnum) { public Builder addAttributes(IAttribSpec... attributes) {
allAttributes.addAll(Arrays.asList(attribEnum.getEnumConstants())); Collections.addAll(allAttributes, attributes);
return this; return this;
} }

View file

@ -38,8 +38,12 @@ public abstract class MappedBuffer implements AutoCloseable {
public MappedBuffer putFloatArray(float[] floats) { public MappedBuffer putFloatArray(float[] floats) {
checkAndMap(); checkAndMap();
internal.asFloatBuffer().put(floats);
internal.position(internal.position() + floats.length * 4); for (float f : floats) {
internal.putFloat(f);
}
// internal.asFloatBuffer().put(floats);
// internal.position(internal.position() + floats.length * 4);
return this; return this;
} }

View file

@ -7,6 +7,7 @@ import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderLoader; import com.jozufozu.flywheel.backend.ShaderLoader;
import com.jozufozu.flywheel.backend.gl.GlFog; import com.jozufozu.flywheel.backend.gl.GlFog;
import com.jozufozu.flywheel.backend.gl.GlFogMode; import com.jozufozu.flywheel.backend.gl.GlFogMode;
import com.jozufozu.flywheel.backend.loading.Program;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -45,7 +46,7 @@ public class FogSensitiveProgram<P extends GlProgram> implements IMultiProgram<P
defines.defineAll(fogMode.getDefines()); defines.defineAll(fogMode.getDefines());
GlProgram.Builder builder = spec.loadProgram(ctx, defines, loader); Program builder = ctx.loadProgram(spec, defines, loader);
programs.put(fogMode, fogProgramLoader.create(builder.name, builder.program, fogMode.getFogFactory())); programs.put(fogMode, fogProgramLoader.create(builder.name, builder.program, fogMode.getFogFactory()));
} }

View file

@ -1,24 +1,13 @@
package com.jozufozu.flywheel.backend.gl.shader; package com.jozufozu.flywheel.backend.gl.shader;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_TRUE;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glBindAttribLocation;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glDeleteProgram; import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetUniformLocation; import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.glUniform1i; import static org.lwjgl.opengl.GL20.glUniform1i;
import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; import static org.lwjgl.opengl.GL20.glUniformMatrix4fv;
import static org.lwjgl.opengl.GL20.glUseProgram; import static org.lwjgl.opengl.GL20.glUseProgram;
import java.util.Collection;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.GlObject;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.util.RenderUtil; import com.jozufozu.flywheel.util.RenderUtil;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -33,10 +22,6 @@ public abstract class GlProgram extends GlObject {
this.name = name; this.name = name;
} }
public static Builder builder(ResourceLocation name) {
return new Builder(name);
}
public void bind() { public void bind() {
glUseProgram(handle()); glUseProgram(handle());
} }
@ -88,53 +73,4 @@ public abstract class GlProgram extends GlObject {
glDeleteProgram(handle); glDeleteProgram(handle);
} }
public static class Builder {
public final ResourceLocation name;
public final int program;
private int attributeIndex;
public Builder(ResourceLocation name) {
this.name = name;
this.program = glCreateProgram();
}
public Builder attachShader(GlShader shader) {
glAttachShader(this.program, shader.handle());
return this;
}
public <A extends IVertexAttrib> Builder addAttributes(Collection<A> attributes) {
attributes.forEach(this::addAttribute);
return this;
}
public <A extends IVertexAttrib> Builder addAttribute(A attrib) {
glBindAttribLocation(this.program, attributeIndex, attrib.attribName());
attributeIndex += attrib.attribSpec().getAttributeCount();
return this;
}
/**
* Links the attached shaders to this program.
*/
public Builder link() {
glLinkProgram(this.program);
String log = glGetProgramInfoLog(this.program);
if (!log.isEmpty()) {
Backend.log.debug("Program link log for " + this.name + ": " + log);
}
int result = glGetProgrami(this.program, GL_LINK_STATUS);
if (result != GL_TRUE) {
throw new RuntimeException("Shader program linking failed, see log for details");
}
return this;
}
}
} }

View file

@ -1,15 +1,5 @@
package com.jozufozu.flywheel.backend.gl.shader; package com.jozufozu.flywheel.backend.gl.shader;
import java.util.ArrayList;
import java.util.Arrays;
import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderLoader;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate;
import com.jozufozu.flywheel.backend.loading.Shader;
import com.jozufozu.flywheel.backend.loading.ShaderTransformer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
public class ProgramSpec { public class ProgramSpec {
@ -20,37 +10,15 @@ public class ProgramSpec {
public final ShaderConstants defines; public final ShaderConstants defines;
public final ArrayList<IVertexAttrib> attributes;
public static Builder builder(ResourceLocation name) { public static Builder builder(ResourceLocation name) {
return new Builder(name); return new Builder(name);
} }
public ProgramSpec(ResourceLocation name, ResourceLocation vert, ResourceLocation frag, ShaderConstants defines, ArrayList<IVertexAttrib> attributes) { public ProgramSpec(ResourceLocation name, ResourceLocation vert, ResourceLocation frag, ShaderConstants defines) {
this.name = name; this.name = name;
this.vert = vert; this.vert = vert;
this.frag = frag; this.frag = frag;
this.defines = defines; this.defines = defines;
this.attributes = attributes;
}
public GlProgram.Builder loadProgram(ShaderContext<?> ctx, ShaderConstants defines, ShaderLoader loader) {
InstancedArraysTemplate template = new InstancedArraysTemplate(loader);
ShaderTransformer transformer = new ShaderTransformer()
.pushStage(ctx.loadingStage(loader))
// .pushStage(loader::processIncludes)
// .pushStage(template)
.pushStage(loader::processIncludes);
if (defines != null)
transformer.pushStage(defines);
Shader vertexFile = loader.source(vert, ShaderType.VERTEX);
Shader fragmentFile = loader.source(frag, ShaderType.FRAGMENT);
return loader.loadProgram(name, transformer, vertexFile, fragmentFile)
.addAttributes(attributes);
} }
public static class Builder { public static class Builder {
@ -59,11 +27,9 @@ public class ProgramSpec {
private ShaderConstants defines = ShaderConstants.EMPTY; private ShaderConstants defines = ShaderConstants.EMPTY;
private final ResourceLocation name; private final ResourceLocation name;
private final ArrayList<IVertexAttrib> attributes;
public Builder(ResourceLocation name) { public Builder(ResourceLocation name) {
this.name = name; this.name = name;
attributes = new ArrayList<>();
} }
public Builder setVert(ResourceLocation vert) { public Builder setVert(ResourceLocation vert) {
@ -81,13 +47,8 @@ public class ProgramSpec {
return this; return this;
} }
public <A extends Enum<A> & IVertexAttrib> Builder addAttributes(Class<A> attributeEnum) { public ProgramSpec build() {
attributes.addAll(Arrays.asList(attributeEnum.getEnumConstants())); return new ProgramSpec(name, vert, frag, defines);
return this;
}
public ProgramSpec createProgramSpec() {
return new ProgramSpec(name, vert, frag, defines, attributes);
} }
} }

View file

@ -4,5 +4,12 @@ import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderLoader; import com.jozufozu.flywheel.backend.ShaderLoader;
public interface ShaderSpecLoader<P extends GlProgram> { public interface ShaderSpecLoader<P extends GlProgram> {
/**
* @param loader
* @param ctx
* @param spec
* @return
*/
IMultiProgram<P> create(ShaderLoader loader, ShaderContext<P> ctx, ProgramSpec spec); IMultiProgram<P> create(ShaderLoader loader, ShaderContext<P> ctx, ProgramSpec spec);
} }

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.gl.shader;
import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderLoader; import com.jozufozu.flywheel.backend.ShaderLoader;
import com.jozufozu.flywheel.backend.loading.Program;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -31,7 +32,7 @@ public class SingleProgram<P extends GlProgram> implements IMultiProgram<P> {
@Override @Override
public IMultiProgram<P> create(ShaderLoader loader, ShaderContext<P> ctx, ProgramSpec spec) { public IMultiProgram<P> create(ShaderLoader loader, ShaderContext<P> ctx, ProgramSpec spec) {
GlProgram.Builder builder = spec.loadProgram(ctx, spec.defines, loader); Program builder = ctx.loadProgram(spec, spec.defines, loader);
return new SingleProgram<>(factory.create(builder.name, builder.program)); return new SingleProgram<>(factory.create(builder.name, builder.program));
} }

View file

@ -6,8 +6,17 @@ import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
public class InstancedArraysTemplate extends ProgramTemplate { public class InstancedArraysTemplate extends ProgramTemplate {
public static final String[] requiredVert = {"FLWInstanceData", "FLWVertexData", "FLWFragment"};
public static final String[] requiredFrag = {"FLWFragment"}; public static final String vertexData = "VertexData";
public static final String instanceData = "InstanceData";
public static final String fragment = "Fragment";
public static final String vertexPrefix = "a_v_";
public static final String instancePrefix = "a_i_";
public static final String[] requiredVert = new String[]{instanceData, vertexData, fragment};
public static final String[] requiredFrag = {fragment};
public static final ResourceLocation vert = new ResourceLocation("create", "template/instanced/instanced.vert"); public static final ResourceLocation vert = new ResourceLocation("create", "template/instanced/instanced.vert");
public static final ResourceLocation frag = new ResourceLocation("create", "template/instanced/instanced.frag"); public static final ResourceLocation frag = new ResourceLocation("create", "template/instanced/instanced.frag");
@ -18,4 +27,12 @@ public class InstancedArraysTemplate extends ProgramTemplate {
templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert))); templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert)));
templates.put(ShaderType.FRAGMENT, new ShaderTemplate(requiredFrag, loader.getShaderSource(frag))); templates.put(ShaderType.FRAGMENT, new ShaderTemplate(requiredFrag, loader.getShaderSource(frag)));
} }
@Override
public void attachAttributes(Program builder) {
Shader shader = builder.attached.get(ShaderType.VERTEX);
shader.getTag(vertexData).addPrefixedAttributes(builder, vertexPrefix);
shader.getTag(instanceData).addPrefixedAttributes(builder, instancePrefix);
}
} }

View file

@ -0,0 +1,19 @@
package com.jozufozu.flywheel.backend.loading;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.jozufozu.flywheel.backend.gl.GlPrimitiveType;
public class LayoutTag {
public static final Pattern pattern = Pattern.compile("Layout\\((\\w+)(?:\\s*,\\s*(\\w*))?\\)");
final GlPrimitiveType type;
final boolean normalized;
public LayoutTag(Matcher matcher) {
type = GlPrimitiveType.byName(matcher.group(1));
normalized = Boolean.parseBoolean(matcher.group(2));
}
}

View file

@ -0,0 +1,34 @@
package com.jozufozu.flywheel.backend.loading;
import com.jozufozu.flywheel.backend.ShaderLoader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import net.minecraft.util.ResourceLocation;
public class ModelTemplate extends ProgramTemplate {
public static final String vertexData = "VertexData";
public static final String fragment = "Fragment";
public static final String vertexPrefix = "a_v_";
public static final String[] requiredVert = new String[]{vertexData, fragment};
public static final String[] requiredFrag = {fragment};
public static final ResourceLocation vert = new ResourceLocation("create", "template/model/model.vert");
public static final ResourceLocation frag = new ResourceLocation("create", "template/model/model.frag");
public ModelTemplate(ShaderLoader loader) {
super(loader);
templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert)));
templates.put(ShaderType.FRAGMENT, new ShaderTemplate(requiredFrag, loader.getShaderSource(frag)));
}
@Override
public void attachAttributes(Program builder) {
Shader shader = builder.attached.get(ShaderType.VERTEX);
shader.getTag(vertexData).addPrefixedAttributes(builder, vertexPrefix);
}
}

View file

@ -1,45 +0,0 @@
package com.jozufozu.flywheel.backend.loading;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.minecraft.util.ResourceLocation;
public class ParsedShader {
private static final Pattern decorator = Pattern.compile("#\\[([\\w_]*)]");
private static final Pattern taggedStruct = Pattern.compile("#\\[([\\w_]*)]\\s*struct\\s+([\\w\\d_]*)\\s*\\{(\\s*(?:.*;\\s*\\n)+\\s*)}\\s*;");
final ResourceLocation loc;
final String src;
final Map<String, TaggedStruct> tag2Struct = new HashMap<>();
final Map<String, TaggedStruct> name2Struct = new HashMap<>();
public ParsedShader(ResourceLocation loc, String src) {
this.loc = loc;
Matcher structs = taggedStruct.matcher(src);
StringBuffer strippedSrc = new StringBuffer();
while (structs.find()) {
TaggedStruct struct = new TaggedStruct(structs);
structs.appendReplacement(strippedSrc, decorator.matcher(struct.source).replaceFirst(""));
tag2Struct.put(struct.tag, struct);
name2Struct.put(struct.name, struct);
}
structs.appendTail(strippedSrc);
this.src = strippedSrc.toString();
}
public TaggedStruct getTag(String tag) {
return tag2Struct.get(tag);
}
public TaggedStruct getStruct(String name) {
return name2Struct.get(name);
}
}

View file

@ -0,0 +1,69 @@
package com.jozufozu.flywheel.backend.loading;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_TRUE;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glBindAttribLocation;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import java.util.EnumMap;
import java.util.Map;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import net.minecraft.util.ResourceLocation;
public class Program {
public final ResourceLocation name;
public final int program;
private int attributeIndex;
public final Map<ShaderType, Shader> attached;
public Program(ResourceLocation name) {
this.name = name;
this.program = glCreateProgram();
attached = new EnumMap<>(ShaderType.class);
}
public Program attachShader(Shader shader, GlShader glShader) {
glAttachShader(this.program, glShader.handle());
attached.put(shader.type, shader);
return this;
}
public Program addAttribute(String name, int attributeCount) {
glBindAttribLocation(this.program, attributeIndex, name);
attributeIndex += attributeCount;
return this;
}
/**
* Links the attached shaders to this program.
*/
public Program link() {
glLinkProgram(this.program);
String log = glGetProgramInfoLog(this.program);
if (!log.isEmpty()) {
Backend.log.debug("Program link log for " + this.name + ": " + log);
}
int result = glGetProgrami(this.program, GL_LINK_STATUS);
if (result != GL_TRUE) {
throw new RuntimeException("Shader program linking failed, see log for details");
}
return this;
}
}

View file

@ -6,7 +6,7 @@ import java.util.Map;
import com.jozufozu.flywheel.backend.ShaderLoader; import com.jozufozu.flywheel.backend.ShaderLoader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
public class ProgramTemplate implements ProcessingStage { public abstract class ProgramTemplate implements ProcessingStage {
protected final ShaderLoader loader; protected final ShaderLoader loader;
protected Map<ShaderType, ShaderTemplate> templates = new EnumMap<>(ShaderType.class); protected Map<ShaderType, ShaderTemplate> templates = new EnumMap<>(ShaderType.class);
@ -21,8 +21,10 @@ public class ProgramTemplate implements ProcessingStage {
if (template == null) return; if (template == null) return;
ParsedShader parsedShader = new ParsedShader(shader.name, shader.getSource()); shader.setSource(template.apply(shader));
}
public void attachAttributes(Program builder) {
shader.setSource(template.apply(parsedShader));
} }
} }

View file

@ -1,26 +1,32 @@
package com.jozufozu.flywheel.backend.loading; package com.jozufozu.flywheel.backend.loading;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
public class Shader { public class Shader {
private static final Pattern decorator = Pattern.compile("#\\[([\\w_]*)]");
public final ResourceLocation name;
public ShaderType type; public ShaderType type;
public ResourceLocation name;
private String source; private String source;
private boolean parsed = false;
final List<TaggedStruct> structs = new ArrayList<>(3);
final Map<String, TaggedStruct> tag2Struct = new HashMap<>();
final Map<String, TaggedStruct> name2Struct = new HashMap<>();
public Shader(ShaderType type, ResourceLocation name, String source) { public Shader(ShaderType type, ResourceLocation name, String source) {
this.type = type; this.type = type;
this.name = name; this.name = name;
this.setSource(source); this.source = source;
}
public static Shader vert(ResourceLocation fileLoc, String source) {
return new Shader(ShaderType.VERTEX, fileLoc, source);
}
public static Shader frag(ResourceLocation fileLoc, String source) {
return new Shader(ShaderType.FRAGMENT, fileLoc, source);
} }
public String getSource() { public String getSource() {
@ -30,4 +36,41 @@ public class Shader {
public void setSource(String source) { public void setSource(String source) {
this.source = source; this.source = source;
} }
public TaggedStruct getTag(String tag) {
checkAndParse();
return tag2Struct.get(tag);
}
public TaggedStruct getStruct(String name) {
checkAndParse();
return name2Struct.get(name);
}
private void checkAndParse() {
if (!parsed) {
parsed = true;
parseStructs();
}
}
public void parseStructs() {
Matcher structMatcher = TaggedStruct.taggedStruct.matcher(source);
StringBuffer strippedSrc = new StringBuffer();
while (structMatcher.find()) {
TaggedStruct struct = new TaggedStruct(structMatcher);
structs.add(struct);
structMatcher.appendReplacement(strippedSrc, decorator.matcher(struct.source).replaceFirst(""));
tag2Struct.put(struct.tag, struct);
name2Struct.put(struct.name, struct);
}
structMatcher.appendTail(strippedSrc);
this.source = strippedSrc.toString();
}
} }

View file

@ -2,7 +2,6 @@ package com.jozufozu.flywheel.backend.loading;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -32,14 +31,14 @@ public class ShaderTemplate {
} }
public String apply(ParsedShader shader) { public String apply(Shader shader) {
return header + return header +
shader.src + shader.getSource() +
processBody(shader); processBody(shader);
} }
public String processBody(ParsedShader shader) { public String processBody(Shader shader) {
String s = body; String s = body;
List<String> missing = new ArrayList<>(); List<String> missing = new ArrayList<>();
@ -55,7 +54,7 @@ public class ShaderTemplate {
} }
if (!missing.isEmpty()) { if (!missing.isEmpty()) {
String err = shader.loc + " is missing: " + String.join(", ", missing); String err = shader.name + " is missing: " + String.join(", ", missing);
throw new RuntimeException(err); throw new RuntimeException(err);
} }
@ -65,7 +64,7 @@ public class ShaderTemplate {
return s; return s;
} }
private String fillPrefixes(ParsedShader shader, String s) { private String fillPrefixes(Shader shader, String s) {
Matcher prefixMatches = prefixer.matcher(s); Matcher prefixMatches = prefixer.matcher(s);
StringBuffer out = new StringBuffer(); StringBuffer out = new StringBuffer();
@ -77,13 +76,13 @@ public class ShaderTemplate {
TaggedStruct struct = shader.getStruct(structName); TaggedStruct struct = shader.getStruct(structName);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (Map.Entry<String, String> field : struct.fields.entrySet()) { for (TaggedField field : struct.fields) {
builder.append(modifier); builder.append(modifier);
builder.append(' '); builder.append(' ');
builder.append(field.getValue()); builder.append(field.getType());
builder.append(' '); builder.append(' ');
builder.append(prefix); builder.append(prefix);
builder.append(field.getKey()); builder.append(field.getName());
builder.append(";\n"); builder.append(";\n");
} }
@ -93,7 +92,7 @@ public class ShaderTemplate {
return out.toString(); return out.toString();
} }
private String fillAssigns(ParsedShader shader, String s) { private String fillAssigns(Shader shader, String s) {
Matcher assignMatches = assigner.matcher(s); Matcher assignMatches = assigner.matcher(s);
StringBuffer out = new StringBuffer(); StringBuffer out = new StringBuffer();
@ -105,12 +104,12 @@ public class ShaderTemplate {
TaggedStruct struct = shader.getStruct(structName); TaggedStruct struct = shader.getStruct(structName);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (String field : struct.fields.keySet()) { for (TaggedField field : struct.fields) {
builder.append(lhs); builder.append(lhs);
builder.append(field); builder.append(field.getName());
builder.append(" = "); builder.append(" = ");
builder.append(rhs); builder.append(rhs);
builder.append(field); builder.append(field.getName());
builder.append(";\n"); builder.append(";\n");
} }

View file

@ -16,6 +16,11 @@ public class ShaderTransformer {
return this; return this;
} }
public ShaderTransformer popStage() {
stages.removeLast();
return this;
}
public ShaderTransformer prependStage(ProcessingStage stage) { public ShaderTransformer prependStage(ProcessingStage stage) {
if (stage != null) { if (stage != null) {
stages.addFirst(stage); stages.addFirst(stage);

View file

@ -0,0 +1,48 @@
package com.jozufozu.flywheel.backend.loading;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TaggedField {
public static final Pattern fieldPattern = Pattern.compile("(?:#\\[([^\\n]*)]\\s*)?(\\S+)\\s*(\\S+);");
public String annotation;
public String name;
public String type;
public LayoutTag layout;
public TaggedField(Matcher fieldMatcher) {
annotation = fieldMatcher.group(1);
type = fieldMatcher.group(2);
name = fieldMatcher.group(3);
if (annotation != null) {
Matcher matcher = LayoutTag.pattern.matcher(annotation);
if (matcher.find()) {
layout = new LayoutTag(matcher);
}
}
}
public String getAnnotation() {
return annotation;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
@Override
public String toString() {
return "TaggedField{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
'}';
}
}

View file

@ -1,13 +1,16 @@
package com.jozufozu.flywheel.backend.loading; package com.jozufozu.flywheel.backend.loading;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class TaggedStruct { public class TaggedStruct {
public static final Pattern fieldPattern = Pattern.compile("(\\S+)\\s*(\\S+);"); // https://regexr.com/5t207
static final Pattern taggedStruct = Pattern.compile("#\\[(\\w*)]\\s*struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d \\t#\\[\\](),;\\n]*)}\\s*;");
int srcStart, srcEnd; int srcStart, srcEnd;
String source; String source;
@ -15,7 +18,8 @@ public class TaggedStruct {
String name; String name;
String body; String body;
Map<String, String> fields = new HashMap<>(); List<TaggedField> fields = new ArrayList<>(4);
Map<String, String> fields2Types = new HashMap<>();
public TaggedStruct(Matcher foundMatcher) { public TaggedStruct(Matcher foundMatcher) {
this.source = foundMatcher.group(); this.source = foundMatcher.group();
@ -27,10 +31,19 @@ public class TaggedStruct {
name = foundMatcher.group(2); name = foundMatcher.group(2);
body = foundMatcher.group(3); body = foundMatcher.group(3);
Matcher fielder = fieldPattern.matcher(body); Matcher fielder = TaggedField.fieldPattern.matcher(body);
while (fielder.find()) { while (fielder.find()) {
fields.put(fielder.group(2), fielder.group(1)); fields.add(new TaggedField(fielder));
fields2Types.put(fielder.group(2), fielder.group(1));
}
}
public void addPrefixedAttributes(Program builder, String prefix) {
for (TaggedField field : fields) {
int attributeCount = TypeHelper.getAttributeCount(field.type);
builder.addAttribute(prefix + field.name, attributeCount);
} }
} }
} }

View file

@ -0,0 +1,37 @@
package com.jozufozu.flywheel.backend.loading;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TypeHelper {
public static final Pattern vecType = Pattern.compile("^[biud]?vec([234])$");
public static final Pattern matType = Pattern.compile("^mat([234])(?:x([234]))?$");
public static int getElementCount(String type) {
Matcher vec = vecType.matcher(type);
if (vec.find()) return Integer.parseInt(vec.group(1));
Matcher mat = matType.matcher(type);
if (mat.find()) {
int n = Integer.parseInt(mat.group(1));
String m = mat.group(2);
if (m != null) return Integer.parseInt(m) * n;
return n;
}
return 1;
}
public static int getAttributeCount(String type) {
Matcher mat = matType.matcher(type);
if (mat.find()) {
return Integer.parseInt(mat.group(1));
}
return 1;
}
}

View file

@ -1,41 +0,0 @@
package com.simibubi.create.content.contraptions.base;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.gl.attrib.VertexAttribSpec;
public enum KineticAttributes implements IVertexAttrib {
INSTANCE_POSITION("aInstancePos", CommonAttributes.VEC3),
SPEED("aSpeed", CommonAttributes.FLOAT),
OFFSET("aOffset", CommonAttributes.FLOAT),
;
private final String name;
private final VertexAttribSpec spec;
KineticAttributes(String name, VertexAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 1;
}
@Override
public int getBufferIndex() {
return 1;
}
}

View file

@ -1,39 +0,0 @@
package com.simibubi.create.content.contraptions.base;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.gl.attrib.VertexAttribSpec;
public enum RotatingAttributes implements IVertexAttrib {
AXIS("aAxis", CommonAttributes.NORMAL),
;
private final String name;
private final VertexAttribSpec spec;
RotatingAttributes(String name, VertexAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 1;
}
@Override
public int getBufferIndex() {
return 1;
}
}

View file

@ -1,45 +0,0 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.gl.attrib.VertexAttribSpec;
public enum ActorVertexAttributes implements IVertexAttrib {
INSTANCE_POSITION("aInstancePos", CommonAttributes.VEC3),
LIGHT("aModelLight", CommonAttributes.LIGHT),
OFFSET("aOffset", CommonAttributes.FLOAT),
AXIS("aAxis", CommonAttributes.NORMAL),
INSTANCE_ROTATION("aInstanceRot", CommonAttributes.QUATERNION),
ROTATION_CENTER("aRotationCenter", CommonAttributes.NORMAL),
SPEED("aSpeed", CommonAttributes.FLOAT),
;
private final String name;
private final VertexAttribSpec spec;
ActorVertexAttributes(String name, VertexAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 1;
}
@Override
public int getBufferIndex() {
return 1;
}
}

View file

@ -1,43 +0,0 @@
package com.simibubi.create.content.contraptions.components.structureMovement.render;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.gl.attrib.VertexAttribSpec;
public enum ContraptionAttributes implements IVertexAttrib {
VERTEX_POSITION("aPos", CommonAttributes.VEC3),
NORMAL("aNormal", CommonAttributes.NORMAL),
TEXTURE("aTexCoords", CommonAttributes.UV),
COLOR("aColor", CommonAttributes.RGBA),
MODEL_LIGHT("aModelLight", CommonAttributes.LIGHT),
;
private final String name;
private final VertexAttribSpec spec;
ContraptionAttributes(String name, VertexAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 0;
}
@Override
public int getBufferIndex() {
return 0;
}
}

View file

@ -1,24 +0,0 @@
package com.simibubi.create.content.contraptions.components.structureMovement.render;
import com.jozufozu.flywheel.backend.ShaderLoader;
import com.jozufozu.flywheel.backend.core.WorldContext;
import com.jozufozu.flywheel.backend.gl.shader.FogSensitiveProgram;
import com.simibubi.create.foundation.render.AllProgramSpecs;
import net.minecraft.util.ResourceLocation;
public class ContraptionContext extends WorldContext<ContraptionProgram> {
public static final ContraptionContext INSTANCE = new ContraptionContext();
public ContraptionContext() {
super(new ResourceLocation("create", "context/contraption"), new FogSensitiveProgram.SpecLoader<>(ContraptionProgram::new));
}
@Override
public void load(ShaderLoader loader) {
super.load(loader);
loadProgramFromSpec(loader, AllProgramSpecs.STRUCTURE);
}
}

View file

@ -26,7 +26,7 @@ public class ContraptionKineticRenderer extends InstancedTileRenderer<Contraptio
private final WeakReference<RenderedContraption> contraption; private final WeakReference<RenderedContraption> contraption;
ContraptionKineticRenderer(RenderedContraption contraption) { ContraptionKineticRenderer(RenderedContraption contraption) {
super(ContraptionContext.INSTANCE); super(ContraptionRenderDispatcher.TILES);
this.contraption = new WeakReference<>(contraption); this.contraption = new WeakReference<>(contraption);
} }

View file

@ -10,10 +10,14 @@ import static org.lwjgl.opengl.GL13.glEnable;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
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.core.WorldContext;
import com.jozufozu.flywheel.backend.gl.shader.FogSensitiveProgram;
import com.jozufozu.flywheel.backend.loading.ModelTemplate;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.CreateClient; import com.simibubi.create.CreateClient;
@ -48,6 +52,7 @@ import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
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.LightType; import net.minecraft.world.LightType;
@ -59,6 +64,9 @@ import net.minecraftforge.client.model.data.EmptyModelData;
public class ContraptionRenderDispatcher { public class ContraptionRenderDispatcher {
public static final Int2ObjectMap<RenderedContraption> renderers = new Int2ObjectOpenHashMap<>(); public static final Int2ObjectMap<RenderedContraption> renderers = new Int2ObjectOpenHashMap<>();
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");
public static final WorldContext<ContraptionProgram> STRUCTURE = new WorldContext<>(ctxRoot, new FogSensitiveProgram.SpecLoader<>(ContraptionProgram::new), () -> Stream.of(AllProgramSpecs.STRUCTURE), ModelTemplate::new);
public static final WorldContext<ContraptionProgram> TILES = new WorldContext<>(ctxRoot, new FogSensitiveProgram.SpecLoader<>(ContraptionProgram::new));
protected static PlacementSimulationWorld renderWorld; protected static PlacementSimulationWorld renderWorld;
public static void tick() { public static void tick() {
@ -90,7 +98,7 @@ public class ContraptionRenderDispatcher {
glActiveTexture(GL_TEXTURE4); // the shaders expect light volumes to be in texture 4 glActiveTexture(GL_TEXTURE4); // the shaders expect light volumes to be in texture 4
if (Backend.canUseVBOs()) { if (Backend.canUseVBOs()) {
ContraptionProgram structureShader = ContraptionContext.INSTANCE.getProgram(AllProgramSpecs.STRUCTURE); ContraptionProgram structureShader = STRUCTURE.getProgram(AllProgramSpecs.STRUCTURE);
structureShader.bind(); structureShader.bind();
structureShader.uploadViewProjection(viewProjection); structureShader.uploadViewProjection(viewProjection);

View file

@ -14,6 +14,7 @@ import org.lwjgl.opengl.GL11;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.core.IndexedModel; import com.jozufozu.flywheel.backend.core.IndexedModel;
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;
import com.jozufozu.flywheel.backend.light.GridAlignedBB; import com.jozufozu.flywheel.backend.light.GridAlignedBB;
@ -49,7 +50,11 @@ import net.minecraftforge.client.model.data.EmptyModelData;
public class RenderedContraption { public class RenderedContraption {
public static final VertexFormat FORMAT = VertexFormat.builder() public static final VertexFormat FORMAT = VertexFormat.builder()
.addAttributes(ContraptionAttributes.class) .addAttributes(CommonAttributes.VEC3,
CommonAttributes.NORMAL,
CommonAttributes.UV,
CommonAttributes.RGBA,
CommonAttributes.LIGHT)
.build(); .build();
private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors()); private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors());

View file

@ -1,42 +0,0 @@
package com.simibubi.create.content.contraptions.relays.belt;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.gl.attrib.VertexAttribSpec;
public enum BeltAttributes implements IVertexAttrib {
INSTANCE_ROTATION("aInstanceRot", CommonAttributes.QUATERNION),
SOURCE_TEX("aSourceTexture", CommonAttributes.UV),
SCROLL_TEX("aScrollTexture", CommonAttributes.VEC4),
SCROLL_MULT("aScrollMult", CommonAttributes.NORMALIZED_BYTE),
;
private final String name;
private final VertexAttribSpec spec;
BeltAttributes(String name, VertexAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 1;
}
@Override
public int getBufferIndex() {
return 1;
}
}

View file

@ -1,46 +0,0 @@
package com.simibubi.create.content.logistics.block;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
import com.jozufozu.flywheel.backend.gl.attrib.VertexAttribSpec;
public enum FlapAttributes implements IVertexAttrib {
INSTANCE_POSITION("aInstancePos",CommonAttributes.VEC3),
LIGHT("aLight", CommonAttributes.LIGHT),
SEGMENT_OFFSET("aSegmentOffset", CommonAttributes.VEC3),
PIVOT("aPivot", CommonAttributes.VEC3),
HORIZONTAL_ANGLE("aHorizontalAngle", CommonAttributes.FLOAT),
INTENSITY("aIntensity", CommonAttributes.FLOAT),
FLAP_SCALE("aFlapScale", CommonAttributes.FLOAT),
FLAPNESS("aFlapness", CommonAttributes.FLOAT),
;
private final String name;
private final VertexAttribSpec spec;
FlapAttributes(String name, VertexAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 1;
}
@Override
public int getBufferIndex() {
return 1;
}
}

View file

@ -1,39 +1,47 @@
package com.simibubi.create.foundation.render; package com.simibubi.create.foundation.render;
import com.jozufozu.flywheel.backend.core.materials.BasicAttributes; import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.core.materials.OrientedAttributes; import com.jozufozu.flywheel.backend.gl.attrib.MatrixAttributes;
import com.jozufozu.flywheel.backend.core.materials.TransformAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.simibubi.create.content.contraptions.base.KineticAttributes;
import com.simibubi.create.content.contraptions.base.RotatingAttributes;
import com.simibubi.create.content.contraptions.components.actors.ActorVertexAttributes;
import com.simibubi.create.content.contraptions.relays.belt.BeltAttributes;
import com.simibubi.create.content.logistics.block.FlapAttributes;
public class AllInstanceFormats { public class AllInstanceFormats {
public static final VertexFormat MODEL = VertexFormat.builder() public static final VertexFormat MODEL = litInstance()
.addAttributes(BasicAttributes.class) .addAttributes(MatrixAttributes.MAT4,
.addAttributes(TransformAttributes.class) MatrixAttributes.MAT3)
.build(); .build();
public static final VertexFormat ORIENTED = VertexFormat.builder()
.addAttributes(BasicAttributes.class) public static final VertexFormat ORIENTED = litInstance()
.addAttributes(OrientedAttributes.class) .addAttributes(CommonAttributes.VEC3, CommonAttributes.VEC3, CommonAttributes.QUATERNION)
.build(); .build();
public static VertexFormat ROTATING = VertexFormat.builder()
.addAttributes(BasicAttributes.class) public static VertexFormat ROTATING = kineticInstance()
.addAttributes(KineticAttributes.class) .addAttributes(CommonAttributes.NORMAL)
.addAttributes(RotatingAttributes.class)
.build(); .build();
public static VertexFormat BELT = kineticInstance()
.addAttributes(CommonAttributes.QUATERNION, CommonAttributes.UV, CommonAttributes.VEC4,
CommonAttributes.NORMALIZED_BYTE)
.build();
public static VertexFormat ACTOR = VertexFormat.builder() public static VertexFormat ACTOR = VertexFormat.builder()
.addAttributes(ActorVertexAttributes.class) .addAttributes(CommonAttributes.VEC3, CommonAttributes.LIGHT, CommonAttributes.FLOAT,
.build(); CommonAttributes.NORMAL, CommonAttributes.QUATERNION, CommonAttributes.NORMAL,
public static VertexFormat BELT = VertexFormat.builder() CommonAttributes.FLOAT)
.addAttributes(BasicAttributes.class)
.addAttributes(KineticAttributes.class)
.addAttributes(BeltAttributes.class)
.build(); .build();
public static VertexFormat FLAP = VertexFormat.builder() public static VertexFormat FLAP = VertexFormat.builder()
.addAttributes(FlapAttributes.class) .addAttributes(CommonAttributes.VEC3, CommonAttributes.LIGHT, CommonAttributes.VEC3, CommonAttributes.VEC3,
CommonAttributes.FLOAT, CommonAttributes.FLOAT, CommonAttributes.FLOAT, CommonAttributes.FLOAT)
.build(); .build();
private static VertexFormat.Builder litInstance() {
return VertexFormat.builder()
.addAttributes(CommonAttributes.LIGHT, CommonAttributes.RGBA);
}
private static VertexFormat.Builder kineticInstance() {
return litInstance()
.addAttributes(CommonAttributes.VEC3, CommonAttributes.FLOAT, CommonAttributes.FLOAT);
}
} }

View file

@ -2,9 +2,9 @@ package com.simibubi.create.foundation.render;
import static com.jozufozu.flywheel.backend.Backend.register; import static com.jozufozu.flywheel.backend.Backend.register;
import com.jozufozu.flywheel.backend.core.materials.ModelAttributes;
import com.jozufozu.flywheel.backend.core.materials.ModelData; import com.jozufozu.flywheel.backend.core.materials.ModelData;
import com.jozufozu.flywheel.backend.core.materials.OrientedData; import com.jozufozu.flywheel.backend.core.materials.OrientedData;
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.MaterialSpec; import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
import com.simibubi.create.Create; import com.simibubi.create.Create;
@ -20,7 +20,9 @@ public class AllMaterialSpecs {
// noop, make sure the static field are loaded. // noop, make sure the static field are loaded.
} }
public static final VertexFormat UNLIT_MODEL = VertexFormat.builder().addAttributes(ModelAttributes.class).build(); public static final VertexFormat UNLIT_MODEL = VertexFormat.builder()
.addAttributes(CommonAttributes.VEC3, CommonAttributes.NORMAL, CommonAttributes.UV)
.build();
public static final MaterialSpec<ModelData> TRANSFORMED = register(new MaterialSpec<>(Locations.MODEL, AllProgramSpecs.MODEL, UNLIT_MODEL, AllInstanceFormats.MODEL, ModelData::new)); public static final MaterialSpec<ModelData> TRANSFORMED = register(new MaterialSpec<>(Locations.MODEL, AllProgramSpecs.MODEL, UNLIT_MODEL, AllInstanceFormats.MODEL, ModelData::new));
public static final MaterialSpec<OrientedData> ORIENTED = register(new MaterialSpec<>(Locations.ORIENTED, AllProgramSpecs.ORIENTED, UNLIT_MODEL, AllInstanceFormats.ORIENTED, OrientedData::new)); public static final MaterialSpec<OrientedData> ORIENTED = register(new MaterialSpec<>(Locations.ORIENTED, AllProgramSpecs.ORIENTED, UNLIT_MODEL, AllInstanceFormats.ORIENTED, OrientedData::new));

View file

@ -2,19 +2,9 @@ package com.simibubi.create.foundation.render;
import static com.jozufozu.flywheel.backend.Backend.register; import static com.jozufozu.flywheel.backend.Backend.register;
import com.jozufozu.flywheel.backend.core.materials.BasicAttributes;
import com.jozufozu.flywheel.backend.core.materials.ModelAttributes;
import com.jozufozu.flywheel.backend.core.materials.OrientedAttributes;
import com.jozufozu.flywheel.backend.core.materials.TransformAttributes;
import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec; import com.jozufozu.flywheel.backend.gl.shader.ProgramSpec;
import com.jozufozu.flywheel.backend.gl.shader.ShaderConstants; import com.jozufozu.flywheel.backend.gl.shader.ShaderConstants;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.KineticAttributes;
import com.simibubi.create.content.contraptions.base.RotatingAttributes;
import com.simibubi.create.content.contraptions.components.actors.ActorVertexAttributes;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionAttributes;
import com.simibubi.create.content.contraptions.relays.belt.BeltAttributes;
import com.simibubi.create.content.logistics.block.FlapAttributes;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -24,66 +14,44 @@ public class AllProgramSpecs {
} }
public static final ProgramSpec CHROMATIC = register(builder("chromatic") public static final ProgramSpec CHROMATIC = register(builder("chromatic")
.addAttributes(ModelAttributes.class)
.addAttributes(BasicAttributes.class)
.addAttributes(TransformAttributes.class)
.setVert(Locations.EFFECT_VERT) .setVert(Locations.EFFECT_VERT)
.setFrag(Locations.EFFECT_FRAG) .setFrag(Locations.EFFECT_FRAG)
.createProgramSpec()); .build());
public static final ProgramSpec MODEL = register(builder("model") public static final ProgramSpec MODEL = register(builder("model")
.addAttributes(ModelAttributes.class)
.addAttributes(BasicAttributes.class)
.addAttributes(TransformAttributes.class)
.setVert(Locations.MODEL_VERT) .setVert(Locations.MODEL_VERT)
.setFrag(Locations.BLOCK) .setFrag(Locations.BLOCK)
.createProgramSpec()); .build());
public static final ProgramSpec ORIENTED = register(builder("oriented") public static final ProgramSpec ORIENTED = register(builder("oriented")
.addAttributes(ModelAttributes.class)
.addAttributes(BasicAttributes.class)
.addAttributes(OrientedAttributes.class)
.setVert(Locations.ORIENTED) .setVert(Locations.ORIENTED)
.setFrag(Locations.BLOCK) .setFrag(Locations.BLOCK)
.createProgramSpec()); .build());
public static final ProgramSpec ROTATING = register(builder("rotating") public static final ProgramSpec ROTATING = register(builder("rotating")
.addAttributes(ModelAttributes.class)
.addAttributes(BasicAttributes.class)
.addAttributes(KineticAttributes.class)
.addAttributes(RotatingAttributes.class)
.setVert(Locations.ROTATING) .setVert(Locations.ROTATING)
.setFrag(Locations.BLOCK) .setFrag(Locations.BLOCK)
.createProgramSpec()); .build());
public static final ProgramSpec BELT = register(builder("belt") public static final ProgramSpec BELT = register(builder("belt")
.addAttributes(ModelAttributes.class)
.addAttributes(BasicAttributes.class)
.addAttributes(KineticAttributes.class)
.addAttributes(BeltAttributes.class)
.setVert(Locations.BELT) .setVert(Locations.BELT)
.setFrag(Locations.BLOCK) .setFrag(Locations.BLOCK)
.createProgramSpec()); .build());
public static final ProgramSpec FLAPS = register(builder("flap") public static final ProgramSpec FLAPS = register(builder("flap")
.addAttributes(ModelAttributes.class)
.addAttributes(FlapAttributes.class)
.setVert(Locations.FLAP) .setVert(Locations.FLAP)
.setFrag(Locations.BLOCK) .setFrag(Locations.BLOCK)
.createProgramSpec()); .build());
public static final ProgramSpec STRUCTURE = register(builder("contraption_structure") public static final ProgramSpec STRUCTURE = register(builder("contraption_structure")
.addAttributes(ContraptionAttributes.class)
.setVert(Locations.CONTRAPTION_STRUCTURE) .setVert(Locations.CONTRAPTION_STRUCTURE)
.setFrag(Locations.BLOCK) .setFrag(Locations.BLOCK)
.setDefines(ShaderConstants.define("CONTRAPTION")) .setDefines(ShaderConstants.define("CONTRAPTION"))
.createProgramSpec()); .build());
public static final ProgramSpec ACTOR = register(builder("contraption_actor") public static final ProgramSpec ACTOR = register(builder("contraption_actor")
.addAttributes(ModelAttributes.class)
.addAttributes(ActorVertexAttributes.class)
.setVert(Locations.CONTRAPTION_ACTOR) .setVert(Locations.CONTRAPTION_ACTOR)
.setFrag(Locations.BLOCK) .setFrag(Locations.BLOCK)
.setDefines(ShaderConstants.define("CONTRAPTION")) .setDefines(ShaderConstants.define("CONTRAPTION"))
.createProgramSpec()); .build());
public static ProgramSpec.Builder builder(String name) { public static ProgramSpec.Builder builder(String name) {
return ProgramSpec.builder(new ResourceLocation(Create.ID, name)); return ProgramSpec.builder(new ResourceLocation(Create.ID, name));

View file

@ -1,14 +1,14 @@
package com.simibubi.create.foundation.render; package com.simibubi.create.foundation.render;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionContext;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
import com.simibubi.create.foundation.fluid.FluidRenderer; import com.simibubi.create.foundation.fluid.FluidRenderer;
import com.simibubi.create.foundation.render.effects.EffectsContext; import com.simibubi.create.foundation.render.effects.EffectsContext;
public class CreateFlywheelHandler { public class CreateFlywheelHandler {
public static void init() { public static void init() {
Backend.register(ContraptionContext.INSTANCE); Backend.register(ContraptionRenderDispatcher.TILES);
Backend.register(ContraptionRenderDispatcher.STRUCTURE);
Backend.register(EffectsContext.INSTANCE); Backend.register(EffectsContext.INSTANCE);
Backend.listeners.renderLayerListener(ContraptionRenderDispatcher::renderLayer); Backend.listeners.renderLayerListener(ContraptionRenderDispatcher::renderLayer);
Backend.listeners.renderLayerListener(FluidRenderer::renderLayer); Backend.listeners.renderLayerListener(FluidRenderer::renderLayer);

View file

@ -2,8 +2,8 @@ package com.simibubi.create.foundation.render.effects;
import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.ShaderLoader; import com.jozufozu.flywheel.backend.ShaderLoader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader;
import com.jozufozu.flywheel.backend.gl.shader.SingleProgram; import com.jozufozu.flywheel.backend.gl.shader.SingleProgram;
import com.jozufozu.flywheel.backend.loading.ShaderTransformer;
import com.simibubi.create.foundation.render.AllProgramSpecs; import com.simibubi.create.foundation.render.AllProgramSpecs;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -12,20 +12,14 @@ public class EffectsContext extends ShaderContext<SphereFilterProgram> {
public static final EffectsContext INSTANCE = new EffectsContext(); public static final EffectsContext INSTANCE = new EffectsContext();
private final SingleProgram.SpecLoader<SphereFilterProgram> loader;
public EffectsContext() { public EffectsContext() {
super(new ResourceLocation("create", "effects")); super(new ResourceLocation("create", "effects"), new SingleProgram.SpecLoader<>(SphereFilterProgram::new));
loader = new SingleProgram.SpecLoader<>(SphereFilterProgram::new);
} }
@Override @Override
public void load(ShaderLoader loader) { public void load(ShaderLoader loader) {
transformer = new ShaderTransformer()
.pushStage(loader::processIncludes);
loadProgramFromSpec(loader, AllProgramSpecs.CHROMATIC); loadProgramFromSpec(loader, AllProgramSpecs.CHROMATIC);
} }
@Override
public ShaderSpecLoader<SphereFilterProgram> getLoader() {
return loader;
}
} }

View file

@ -1,38 +0,0 @@
package com.simibubi.create.foundation.render.effects;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
import com.jozufozu.flywheel.backend.gl.attrib.IAttribSpec;
import com.jozufozu.flywheel.backend.gl.attrib.IVertexAttrib;
public enum ScreenQuadAttributes implements IVertexAttrib {
INSTANCE_POS("aVertex", CommonAttributes.VEC4),
;
private final String name;
private final IAttribSpec spec;
ScreenQuadAttributes(String name, IAttribSpec spec) {
this.name = name;
this.spec = spec;
}
@Override
public String attribName() {
return name;
}
@Override
public IAttribSpec attribSpec() {
return spec;
}
@Override
public int getDivisor() {
return 0;
}
@Override
public int getBufferIndex() {
return 0;
}
}

View file

@ -1,4 +1,3 @@
#version 110
#define PI 3.1415926538 #define PI 3.1415926538
#flwbuiltins #flwbuiltins
@ -6,55 +5,45 @@
#flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/matutils.glsl">
#flwinclude <"create:core/diffuse.glsl"> #flwinclude <"create:core/diffuse.glsl">
attribute vec3 aPos; #[InstanceData]
attribute vec3 aNormal; struct Belt {
attribute vec2 aTexCoords; vec2 light;
vec4 color;
vec3 pos;
float speed;
float offset;
vec4 rotation;
vec2 sourceTexture;
vec4 scrollTexture;
float scrollMult;
};
attribute vec2 aLight; #flwinclude <"create:data/modelvertex.glsl">
attribute vec4 aColor; #flwinclude <"create:data/blockfragment.glsl">
attribute vec3 aInstancePos;
attribute float aSpeed;
attribute float aOffset;
attribute vec4 aInstanceRot;
attribute vec2 aSourceTexture;
attribute vec4 aScrollTexture;
attribute float aScrollMult;
varying vec2 TexCoords; BlockFrag FLWMain(Vertex v, Belt instance) {
varying vec4 Color; vec3 rotated = rotateVertexByQuat(v.pos - .5, instance.rotation) + instance.pos + .5;
varying float Diffuse;
varying vec2 Light;
void main() {
vec3 rotated = rotateVertexByQuat(aPos - .5, aInstanceRot) + aInstancePos + .5;
vec4 worldPos = vec4(rotated, 1.); vec4 worldPos = vec4(rotated, 1.);
vec3 norm = rotateVertexByQuat(aNormal, aInstanceRot); vec3 norm = rotateVertexByQuat(v.normal, instance.rotation);
FLWFinalizeWorldPos(worldPos); FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm); FLWFinalizeNormal(norm);
float scrollSize = aScrollTexture.w - aScrollTexture.y; float scrollSize = instance.scrollTexture.w - instance.scrollTexture.y;
float scroll = fract(aSpeed * uTime / (31.5 * 16.) + aOffset) * scrollSize * aScrollMult; float scroll = fract(instance.speed * uTime / (31.5 * 16.) + instance.offset) * scrollSize * instance.scrollMult;
Diffuse = diffuse(norm); BlockFrag b;
TexCoords = aTexCoords - aSourceTexture + aScrollTexture.xy + vec2(0, scroll); b.diffuse = diffuse(norm);
Light = aLight; b.texCoords = v.texCoords - instance.sourceTexture + instance.scrollTexture.xy + vec2(0, scroll);
b.light = instance.light;
#ifdef CONTRAPTION #if defined(RAINBOW_DEBUG)
if (uDebug == 2) { b.color = instance.color;
Color = vec4(norm, 1.);
} else {
Color = vec4(1.);
}
#else #else
if (uDebug == 1) { b.color = vec4(1.);
Color = aColor;
} else if (uDebug == 2) {
Color = vec4(norm, 1.);
} else {
Color = vec4(1.);
}
#endif #endif
return b;
} }

View file

@ -1,16 +1,11 @@
#version 110
#flwbuiltins #flwbuiltins
varying vec2 TexCoords; #flwinclude <"create:data/blockfragment.glsl">
varying vec2 Light;
varying float Diffuse;
varying vec4 Color;
void main() { void FLWMain(BlockFrag r) {
vec4 tex = FLWBlockTexture(TexCoords); vec4 tex = FLWBlockTexture(r.texCoords);
vec4 color = vec4(tex.rgb * FLWLight(Light).rgb * Diffuse, tex.a) * Color; vec4 color = vec4(tex.rgb * FLWLight(r.light).rgb * r.diffuse, tex.a) * r.color;
FLWFinalizeColor(color); FLWFinalizeColor(color);
} }

View file

@ -1,17 +0,0 @@
#flwbuiltins
#[Fragment]
struct Raster {
vec2 texCoords;
vec4 color;
float diffuse;
vec2 light;
};
void FLWMain(Raster r) {
vec4 tex = FLWBlockTexture(r.texCoords);
vec4 color = vec4(tex.rgb * FLWLight(r.light).rgb * r.diffuse, tex.a) * r.color;
FLWFinalizeColor(color);
}

View file

@ -1,4 +1,4 @@
#flwinclude <"create:context/std/fog.glsl"> #flwinclude <"create:context/world/fog.glsl">
#flwinclude <"create:core/lightutil.glsl"> #flwinclude <"create:core/lightutil.glsl">
varying vec3 BoxCoord; varying vec3 BoxCoord;

View file

@ -10,7 +10,6 @@ uniform mat4 uModel;
uniform float uTime; uniform float uTime;
uniform mat4 uViewProjection; uniform mat4 uViewProjection;
uniform int uDebug;
uniform vec3 uCameraPos; uniform vec3 uCameraPos;
void FLWFinalizeWorldPos(inout vec4 worldPos) { void FLWFinalizeWorldPos(inout vec4 worldPos) {

View file

@ -1,4 +1,4 @@
#flwinclude <"create:context/std/fog.glsl"> #flwinclude <"create:context/world/fog.glsl">
uniform vec2 uTextureScale; uniform vec2 uTextureScale;
uniform sampler2D uBlockAtlas; uniform sampler2D uBlockAtlas;

View file

@ -1 +1 @@
#flwinclude <"create:context/std/builtin.vert"> #flwinclude <"create:context/world/builtin.vert">

View file

@ -1,4 +1,4 @@
#flwinclude <"create:context/std/fog.glsl"> #flwinclude <"create:context/world/fog.glsl">
#flwinclude <"create:core/lightutil.glsl"> #flwinclude <"create:core/lightutil.glsl">
uniform sampler2D uBlockAtlas; uniform sampler2D uBlockAtlas;

View file

@ -1,6 +1,5 @@
uniform float uTime; uniform float uTime;
uniform mat4 uViewProjection; uniform mat4 uViewProjection;
uniform int uDebug;
uniform vec3 uCameraPos; uniform vec3 uCameraPos;
#if defined(USE_FOG) #if defined(USE_FOG)

View file

@ -1,4 +1,3 @@
#version 110
#define PI 3.1415926538 #define PI 3.1415926538
#flwbuiltins #flwbuiltins
@ -6,45 +5,38 @@
#flwinclude <"create:core/quaternion.glsl"> #flwinclude <"create:core/quaternion.glsl">
#flwinclude <"create:core/diffuse.glsl"> #flwinclude <"create:core/diffuse.glsl">
// model data #[InstanceData]
attribute vec3 aPos; struct Actor {
attribute vec3 aNormal; vec3 pos;
attribute vec2 aTexCoords; vec2 light;
float offset;
vec3 axis;
vec4 rotation;
vec3 rotationCenter;
float speed;
};
// instance data #flwinclude <"create:data/modelvertex.glsl">
attribute vec3 aInstancePos; #flwinclude <"create:data/blockfragment.glsl">
attribute vec2 aModelLight;
attribute float aOffset;
attribute vec3 aAxis;
attribute vec4 aInstanceRot;
attribute vec3 aRotationCenter;
attribute float aSpeed;
varying float Diffuse; BlockFrag FLWMain(Vertex v, Actor instance) {
varying vec2 TexCoords; float degrees = instance.offset + uTime * instance.speed / 20.;
varying vec4 Color;
varying vec2 Light;
void main() {
float degrees = aOffset + uTime * aSpeed / 20.;
//float angle = fract(degrees / 360.) * PI * 2.; //float angle = fract(degrees / 360.) * PI * 2.;
vec4 kineticRot = quat(aAxis, degrees); vec4 kineticRot = quat(instance.axis, degrees);
vec3 rotated = rotateVertexByQuat(aPos - aRotationCenter, kineticRot) + aRotationCenter; vec3 rotated = rotateVertexByQuat(v.pos - instance.rotationCenter, kineticRot) + instance.rotationCenter;
vec4 worldPos = vec4(rotateVertexByQuat(rotated - .5, aInstanceRot) + aInstancePos + .5, 1.); vec4 worldPos = vec4(rotateVertexByQuat(rotated - .5, instance.rotation) + instance.pos + .5, 1.);
vec3 norm = rotateVertexByQuat(rotateVertexByQuat(aNormal, kineticRot), aInstanceRot); vec3 norm = rotateVertexByQuat(rotateVertexByQuat(v.normal, kineticRot), instance.rotation);
FLWFinalizeWorldPos(worldPos); FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm); FLWFinalizeNormal(norm);
Diffuse = diffuse(norm); BlockFrag b;
TexCoords = aTexCoords; b.diffuse = diffuse(norm);
Light = aModelLight; b.texCoords = v.texCoords;
b.light = instance.light;
b.color = vec4(1.);
if (uDebug == 2) { return b;
Color = vec4(norm, 1.);
} else {
Color = vec4(1.);
}
} }

View file

@ -1,34 +1,32 @@
#version 110
#define PI 3.1415926538 #define PI 3.1415926538
#flwbuiltins #flwbuiltins
#flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/matutils.glsl">
#flwinclude <"create:core/diffuse.glsl"> #flwinclude <"create:core/diffuse.glsl">
attribute vec3 aPos; #[VertexData]
attribute vec3 aNormal; struct Vertex {
attribute vec2 aTexCoords; vec3 pos;
attribute vec4 aColor; vec3 normal;
attribute vec2 aModelLight; vec2 texCoords;
vec4 color;
vec2 modelLight;
};
varying float Diffuse; #flwinclude <"create:data/blockfragment.glsl">
varying vec2 TexCoords;
varying vec4 Color;
varying vec2 Light;
void main() { BlockFrag FLWMain(Vertex v) {
vec4 worldPos = vec4(aPos, 1.); vec4 worldPos = vec4(v.pos, 1.);
vec3 norm = aNormal; vec3 norm = v.normal;
FLWFinalizeWorldPos(worldPos); FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm); FLWFinalizeNormal(norm);
Diffuse = diffuse(norm); BlockFrag b;
if (uDebug == 2) { b.diffuse = diffuse(norm);
Color = vec4(norm, 1.); b.color = v.color / diffuse(v.normal);
} else { b.texCoords = v.texCoords;
Color = aColor / diffuse(aNormal); b.light = v.modelLight;
}
TexCoords = aTexCoords; return b;
Light = aModelLight;
} }

View file

@ -0,0 +1,7 @@
#[Fragment]
struct BlockFrag {
vec2 texCoords;
vec4 color;
float diffuse;
vec2 light;
};

View file

@ -0,0 +1,6 @@
#[VertexData]
struct Vertex {
vec3 pos;
vec3 normal;
vec2 texCoords;
};

View file

@ -1,4 +1,3 @@
#version 110
#define PI 3.1415926538 #define PI 3.1415926538
#flwbuiltins #flwbuiltins
@ -6,62 +5,58 @@
#flwinclude <"create:core/quaternion.glsl"> #flwinclude <"create:core/quaternion.glsl">
#flwinclude <"create:core/diffuse.glsl"> #flwinclude <"create:core/diffuse.glsl">
attribute vec3 aPos; #[InstanceData]
attribute vec3 aNormal; struct Flap {
attribute vec2 aTexCoords; vec3 instancePos;
vec2 light;
vec3 segmentOffset;
vec3 pivot;
float horizontalAngle;
float intensity;
float flapScale;
float flapness;
};
attribute vec3 aInstancePos; #flwinclude <"create:data/modelvertex.glsl">
attribute vec2 aLight; #flwinclude <"create:data/blockfragment.glsl">
attribute vec3 aSegmentOffset;
attribute vec3 aPivot;
attribute float aHorizontalAngle;
attribute float aIntensity;
attribute float aFlapScale;
attribute float aFlapness;
// outputs
varying vec2 TexCoords;
varying vec4 Color;
varying float Diffuse;
varying vec2 Light;
float toRad(float degrees) { float toRad(float degrees) {
return fract(degrees / 360.) * PI * 2.; return fract(degrees / 360.) * PI * 2.;
} }
float getFlapAngle() { float getFlapAngle(float flapness, float intensity, float scale) {
float absFlap = abs(aFlapness); float absFlap = abs(flapness);
float angle = sin((1. - absFlap) * PI * aIntensity) * 30. * aFlapness * aFlapScale; float angle = sin((1. - absFlap) * PI * intensity) * 30. * flapness * scale;
float halfAngle = angle * 0.5; float halfAngle = angle * 0.5;
float which = step(0., aFlapness); float which = step(0., flapness);// 0 if negative, 1 if positive
float degrees = which * halfAngle + (1. - which) * angle;// branchless conditional multiply float degrees = which * halfAngle + (1. - which) * angle;// branchless conditional multiply
return degrees; return degrees;
} }
void main() { BlockFrag FLWMain(Vertex v, Flap flap) {
float flapAngle = getFlapAngle(); float flapAngle = getFlapAngle(flap.flapness, flap.intensity, flap.flapScale);
vec4 orientation = quat(vec3(0., 1., 0.), -aHorizontalAngle); vec4 orientation = quat(vec3(0., 1., 0.), -flap.horizontalAngle);
vec4 flapRotation = quat(vec3(1., 0., 0.), flapAngle); vec4 flapRotation = quat(vec3(1., 0., 0.), flapAngle);
vec3 rotated = rotateVertexByQuat(aPos - aPivot, flapRotation) + aPivot + aSegmentOffset; vec3 rotated = rotateVertexByQuat(v.pos - flap.pivot, flapRotation) + flap.pivot + flap.segmentOffset;
rotated = rotateVertexByQuat(rotated - .5, orientation) + aInstancePos + .5; rotated = rotateVertexByQuat(rotated - .5, orientation) + flap.instancePos + .5;
vec4 worldPos = vec4(rotated, 1.); vec4 worldPos = vec4(rotated, 1.);
vec3 norm = rotateVertexByQuat(rotateVertexByQuat(aNormal, flapRotation), orientation); vec3 norm = rotateVertexByQuat(rotateVertexByQuat(v.normal, flapRotation), orientation);
FLWFinalizeWorldPos(worldPos); FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm); FLWFinalizeNormal(norm);
Diffuse = diffuse(norm); BlockFrag b;
TexCoords = aTexCoords; b.diffuse = diffuse(norm);
Light = aLight; b.texCoords = v.texCoords;
b.light = flap.light;
Color = vec4(1.); b.color = vec4(1.);
return b;
} }

View file

@ -1,35 +1,31 @@
#version 110
#flwbuiltins #flwbuiltins
#flwinclude <"create:core/diffuse.glsl"> #flwinclude <"create:core/diffuse.glsl">
attribute vec3 aPos; #[InstanceData]
attribute vec3 aNormal; struct Instance {
attribute vec2 aTexCoords; vec2 light;
vec4 color;
mat4 transform;
mat3 normalMat;
};
attribute vec2 aLight; #flwinclude <"create:data/modelvertex.glsl">
attribute vec4 aColor; #flwinclude <"create:data/blockfragment.glsl">
attribute mat4 aTransform;
attribute mat3 aNormalMat;
varying vec2 TexCoords; BlockFrag FLWMain(Vertex v, Instance i) {
varying vec4 Color; vec4 worldPos = i.transform * vec4(v.pos, 1.);
varying float Diffuse;
varying vec2 Light;
void main() { vec3 norm = i.normalMat * v.normal;
vec4 worldPos = aTransform * vec4(aPos, 1.);
vec3 norm = aNormalMat * aNormal;
FLWFinalizeWorldPos(worldPos); FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm); FLWFinalizeNormal(norm);
norm = normalize(norm); norm = normalize(norm);
Diffuse = diffuse(norm); BlockFrag b;
TexCoords = aTexCoords; b.diffuse = diffuse(norm);
Light = aLight; b.texCoords = v.texCoords;
b.light = i.light;
Color = aColor; b.color = i.color;
return b;
} }

View file

@ -1,46 +0,0 @@
#flwbuiltins
#flwinclude <"create:core/diffuse.glsl">
#[VertexData]
struct Vertex {
#[Layout(float)]
vec3 pos;
vec3 normal;
vec2 texCoords;
};
#[InstanceData]
struct Instance {
#[Normalized(ushort)]
vec2 light;
#[Normalized(ubyte)]
vec4 color;
mat4 transform;
mat3 normalMat;
};
#[Fragment]
struct Raster {
vec2 texCoords;
vec4 color;
float diffuse;
vec2 light;
};
Raster FLWMain(Vertex v, Instance i) {
vec4 worldPos = i.transform * vec4(v.pos, 1.);
vec3 norm = i.normalMat * v.normal;
norm = normalize(norm);
FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm);
Raster r;
r.diffuse = diffuse(norm);
r.texCoords = v.texCoords;
r.light = i.light;
r.color = i.color;
return r;
}

View file

@ -1,36 +1,32 @@
#version 110
#flwbuiltins #flwbuiltins
#flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/matutils.glsl">
#flwinclude <"create:core/quaternion.glsl"> #flwinclude <"create:core/quaternion.glsl">
#flwinclude <"create:core/diffuse.glsl"> #flwinclude <"create:core/diffuse.glsl">
attribute vec3 aPos; #[InstanceData]
attribute vec3 aNormal; struct Oriented {
attribute vec2 aTexCoords; vec2 light;
vec4 color;
vec3 pos;
vec3 pivot;
vec4 rotation;
};
attribute vec2 aLight; #flwinclude <"create:data/modelvertex.glsl">
attribute vec4 aColor; #flwinclude <"create:data/blockfragment.glsl">
attribute vec3 aInstancePos;
attribute vec3 aPivot;
attribute vec4 aRotation;
varying vec2 TexCoords; BlockFrag FLWMain(Vertex v, Oriented o) {
varying vec4 Color; vec4 worldPos = vec4(rotateVertexByQuat(v.pos - o.pivot, o.rotation) + o.pivot + o.pos, 1.);
varying float Diffuse;
varying vec2 Light;
void main() { vec3 norm = rotateVertexByQuat(v.normal, o.rotation);
vec4 worldPos = vec4(rotateVertexByQuat(aPos - aPivot, aRotation) + aPivot + aInstancePos, 1.);
vec3 norm = rotateVertexByQuat(aNormal, aRotation);
FLWFinalizeWorldPos(worldPos); FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm); FLWFinalizeNormal(norm);
Diffuse = diffuse(norm); BlockFrag b;
TexCoords = aTexCoords; b.diffuse = diffuse(norm);
Light = aLight; b.texCoords = v.texCoords;
b.light = o.light;
Color = aColor; b.color = o.color;
return b;
} }

View file

@ -1,60 +1,51 @@
#version 110
#define PI 3.1415926538 #define PI 3.1415926538
#flwbuiltins #flwbuiltins
#flwinclude <"create:core/quaternion.glsl">
#flwinclude <"create:core/matutils.glsl"> #flwinclude <"create:core/matutils.glsl">
#flwinclude <"create:core/diffuse.glsl"> #flwinclude <"create:core/diffuse.glsl">
attribute vec3 aPos; #[InstanceData]
attribute vec3 aNormal; struct Rotating {
attribute vec2 aTexCoords; vec2 light;
vec4 color;
vec3 pos;
float speed;
float offset;
vec3 axis;
};
attribute vec2 aLight; #flwinclude <"create:data/modelvertex.glsl">
attribute vec4 aColor; #flwinclude <"create:data/blockfragment.glsl">
attribute vec3 aInstancePos;
attribute float aSpeed;
attribute float aOffset;
attribute vec3 aAxis;
varying vec2 TexCoords; mat4 kineticRotation(float offset, float speed, vec3 axis) {
varying vec4 Color; float degrees = offset + uTime * speed * 3./10.;
varying float Diffuse;
varying vec2 Light;
mat4 kineticRotation() {
float degrees = aOffset + uTime * aSpeed * 3./10.;
float angle = fract(degrees / 360.) * PI * 2.; float angle = fract(degrees / 360.) * PI * 2.;
return rotate(aAxis, angle); return rotate(axis, angle);
} }
void main() { BlockFrag FLWMain(Vertex v, Rotating instance) {
mat4 kineticRotation = kineticRotation(); mat4 kineticRotation = kineticRotation(instance.offset, instance.speed, instance.axis);
vec4 worldPos = kineticRotation * vec4(aPos - .5, 1.) + vec4(aInstancePos + .5, 0.);
vec3 norm = modelToNormal(kineticRotation) * aNormal; vec4 worldPos = vec4(v.pos - .5, 1.);
worldPos *= kineticRotation;
worldPos += vec4(instance.pos + .5, 0.);
vec3 norm = modelToNormal(kineticRotation) * v.normal;
FLWFinalizeWorldPos(worldPos); FLWFinalizeWorldPos(worldPos);
FLWFinalizeNormal(norm); FLWFinalizeNormal(norm);
Diffuse = diffuse(norm); BlockFrag b;
TexCoords = aTexCoords; b.diffuse = diffuse(norm);
Light = aLight; b.texCoords = v.texCoords;
b.light = instance.light;
#ifdef CONTRAPTION #if defined(RAINBOW_DEBUG)
if (uDebug == 2) { b.color = instance.color;
Color = vec4(norm, 1.);
} else {
Color = vec4(1.);
}
#else #else
if (uDebug == 1) { b.color = vec4(1.);
Color = aColor;
} else if (uDebug == 2) {
Color = vec4(norm, 1.);
} else {
Color = vec4(1.);
}
#endif #endif
return b;
} }

View file

@ -0,0 +1,12 @@
#version 110
#flwbeginbody
#FLWPrefixFields(Fragment, varying, v2f_)
void main() {
Fragment f;
#FLWAssignFields(Fragment, f., v2f_)
FLWMain(f);
}

View file

@ -0,0 +1,15 @@
#version 110
#flwbeginbody
#FLWPrefixFields(VertexData, attribute, a_v_)
#FLWPrefixFields(Fragment, varying, v2f_)
void main() {
VertexData v;
#FLWAssignFields(VertexData, v., a_v_)
Fragment o = FLWMain(v);
#FLWAssignFields(Fragment, v2f_, o.)
}