mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-08 13:26:39 +01:00
Structless instances
- Instance shaders define their own input variables - Input locations are transformed during compilation based on vertex type
This commit is contained in:
parent
0e37a0586f
commit
5657e8669e
8 changed files with 159 additions and 110 deletions
|
@ -1,5 +1,7 @@
|
||||||
package com.jozufozu.flywheel.core.compile;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||||
|
@ -8,9 +10,12 @@ import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||||
import com.jozufozu.flywheel.core.source.FileIndex;
|
import com.jozufozu.flywheel.core.source.FileIndex;
|
||||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
import com.jozufozu.flywheel.core.source.ShaderField;
|
||||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||||
import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
|
import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
|
||||||
import com.jozufozu.flywheel.core.source.parse.StructField;
|
import com.jozufozu.flywheel.core.source.parse.StructField;
|
||||||
|
import com.jozufozu.flywheel.core.source.span.Span;
|
||||||
|
import com.jozufozu.flywheel.util.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles compilation and deletion of vertex shaders.
|
* Handles compilation and deletion of vertex shaders.
|
||||||
|
@ -43,8 +48,21 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
|
|
||||||
|
int attributeBaseIndex = key.vertexType.getLayout()
|
||||||
|
.getAttributeCount();
|
||||||
|
|
||||||
var instanceShader = key.instanceShader;
|
var instanceShader = key.instanceShader;
|
||||||
instanceShader.generateFinalSource(index, finalSource);
|
var replacements = new ArrayList<Pair<Span, String>>();
|
||||||
|
for (ShaderField field : instanceShader.fields.values()) {
|
||||||
|
if (field.decoration != ShaderField.Decoration.IN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int location = Integer.parseInt(field.location.get());
|
||||||
|
int newLocation = location + attributeBaseIndex;
|
||||||
|
replacements.add(Pair.of(field.location, Integer.toString(newLocation)));
|
||||||
|
}
|
||||||
|
instanceShader.generateFinalSource(index, finalSource, replacements);
|
||||||
|
|
||||||
// MATERIAL
|
// MATERIAL
|
||||||
|
|
||||||
|
@ -58,11 +76,17 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
||||||
|
|
||||||
// MAIN
|
// MAIN
|
||||||
|
|
||||||
var instanceStruct = instanceShader.findFunction("flw_instanceVertex")
|
finalSource.append("""
|
||||||
.flatMap(f -> f.getParameterType(0)
|
void main() {
|
||||||
.findStruct())
|
flw_layoutVertex();
|
||||||
.orElseThrow();
|
|
||||||
finalSource.append(generateFooter(key.vertexType, instanceStruct));
|
flw_instanceVertex();
|
||||||
|
|
||||||
|
flw_materialVertex();
|
||||||
|
|
||||||
|
flw_contextVertex();
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new GlShader(finalSource.toString(), ShaderType.VERTEX, ImmutableList.of(layoutShader.name, instanceShader.name, materialShader.name, contextShaderSource.name), shaderConstants);
|
return new GlShader(finalSource.toString(), ShaderType.VERTEX, ImmutableList.of(layoutShader.name, instanceShader.name, materialShader.name, contextShaderSource.name), shaderConstants);
|
||||||
|
@ -71,65 +95,6 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateFooter(VertexType vertexType, ShaderStruct instance) {
|
|
||||||
ImmutableList<StructField> fields = instance.getFields();
|
|
||||||
|
|
||||||
int attributeBinding = vertexType.getLayout()
|
|
||||||
.getAttributeCount();
|
|
||||||
|
|
||||||
StringBuilder footer = new StringBuilder();
|
|
||||||
|
|
||||||
for (StructField field : fields) {
|
|
||||||
footer.append("layout(location = ")
|
|
||||||
.append(attributeBinding)
|
|
||||||
.append(") in")
|
|
||||||
.append(' ')
|
|
||||||
.append(field.type)
|
|
||||||
.append(' ')
|
|
||||||
.append("_flw_a_i_")
|
|
||||||
.append(field.name)
|
|
||||||
.append(";\n");
|
|
||||||
attributeBinding += CompileUtil.getAttributeCount(field.type);
|
|
||||||
}
|
|
||||||
footer.append('\n');
|
|
||||||
|
|
||||||
footer.append(String.format("""
|
|
||||||
void main() {
|
|
||||||
flw_layoutVertex();
|
|
||||||
|
|
||||||
%s instance;
|
|
||||||
%s
|
|
||||||
flw_instanceVertex(instance);
|
|
||||||
|
|
||||||
flw_materialVertex();
|
|
||||||
|
|
||||||
flw_contextVertex();
|
|
||||||
}
|
|
||||||
""",
|
|
||||||
instance.name,
|
|
||||||
assignFields(instance, "instance.", "_flw_a_i_")
|
|
||||||
));
|
|
||||||
|
|
||||||
return footer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static StringBuilder assignFields(ShaderStruct struct, String prefix1, String prefix2) {
|
|
||||||
ImmutableList<StructField> fields = struct.getFields();
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
for (StructField field : fields) {
|
|
||||||
builder.append(prefix1)
|
|
||||||
.append(field.name)
|
|
||||||
.append(" = ")
|
|
||||||
.append(prefix2)
|
|
||||||
.append(field.name)
|
|
||||||
.append(";\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void _destroy(GlShader value) {
|
protected void _destroy(GlShader value) {
|
||||||
value.delete();
|
value.delete();
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.jozufozu.flywheel.core.source;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.core.source.parse.AbstractShaderElement;
|
||||||
|
import com.jozufozu.flywheel.core.source.span.Span;
|
||||||
|
|
||||||
|
public class ShaderField extends AbstractShaderElement {
|
||||||
|
public static final Pattern PATTERN = Pattern.compile("layout\\s+\\(location\\s+=\\s+(\\d+)\\)\\s+(in|out)\\s+([\\w\\d]+)\\s+" + "([\\w\\d]+)");
|
||||||
|
|
||||||
|
public final Span location;
|
||||||
|
public final @Nullable Decoration decoration;
|
||||||
|
public final Span type;
|
||||||
|
public final Span name;
|
||||||
|
|
||||||
|
public ShaderField(Span self, Span location, Span inOut, Span type, Span name) {
|
||||||
|
super(self);
|
||||||
|
|
||||||
|
this.location = location;
|
||||||
|
this.decoration = Decoration.fromSpan(inOut);
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Decoration {
|
||||||
|
IN,
|
||||||
|
OUT,
|
||||||
|
FLAT,
|
||||||
|
;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Decoration fromSpan(Span span) {
|
||||||
|
return switch (span.toString()) {
|
||||||
|
case "in" -> IN;
|
||||||
|
case "out" -> OUT;
|
||||||
|
case "flat" -> FLAT;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package com.jozufozu.flywheel.core.source;
|
package com.jozufozu.flywheel.core.source;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -18,6 +20,7 @@ import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
|
||||||
import com.jozufozu.flywheel.core.source.span.ErrorSpan;
|
import com.jozufozu.flywheel.core.source.span.ErrorSpan;
|
||||||
import com.jozufozu.flywheel.core.source.span.Span;
|
import com.jozufozu.flywheel.core.source.span.Span;
|
||||||
import com.jozufozu.flywheel.core.source.span.StringSpan;
|
import com.jozufozu.flywheel.core.source.span.StringSpan;
|
||||||
|
import com.jozufozu.flywheel.util.Pair;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
@ -34,10 +37,6 @@ public class SourceFile {
|
||||||
|
|
||||||
public final ShaderSources parent;
|
public final ShaderSources parent;
|
||||||
public final String source;
|
public final String source;
|
||||||
/**
|
|
||||||
* Sections of the source that must be trimmed for compilation. Currently, it only contains the spans of imports.
|
|
||||||
*/
|
|
||||||
public final String elided;
|
|
||||||
|
|
||||||
public final SourceLines lines;
|
public final SourceLines lines;
|
||||||
|
|
||||||
|
@ -55,6 +54,8 @@ public class SourceFile {
|
||||||
* Includes ordered as defined in the source.
|
* Includes ordered as defined in the source.
|
||||||
*/
|
*/
|
||||||
public final ImmutableList<Import> imports;
|
public final ImmutableList<Import> imports;
|
||||||
|
public final ImmutableMap<String, ShaderField> fields;
|
||||||
|
private final List<Span> elisions;
|
||||||
|
|
||||||
public SourceFile(ErrorReporter errorReporter, ShaderSources parent, ResourceLocation name, String source) {
|
public SourceFile(ErrorReporter errorReporter, ShaderSources parent, ResourceLocation name, String source) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
@ -63,13 +64,12 @@ public class SourceFile {
|
||||||
|
|
||||||
this.lines = new SourceLines(source);
|
this.lines = new SourceLines(source);
|
||||||
|
|
||||||
List<Span> elisions = new ArrayList<>();
|
this.elisions = new ArrayList<>();
|
||||||
|
|
||||||
this.imports = parseImports(errorReporter, elisions);
|
this.imports = parseImports(errorReporter);
|
||||||
this.functions = parseFunctions();
|
this.functions = parseFunctions();
|
||||||
this.structs = parseStructs();
|
this.structs = parseStructs();
|
||||||
|
this.fields = parseFields();
|
||||||
this.elided = elideSource(source, elisions).toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span getLineSpan(int line) {
|
public Span getLineSpan(int line) {
|
||||||
|
@ -136,11 +136,15 @@ public class SourceFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateFinalSource(FileIndex env, StringBuilder source) {
|
public void generateFinalSource(FileIndex env, StringBuilder source) {
|
||||||
|
generateFinalSource(env, source, Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateFinalSource(FileIndex env, StringBuilder source, List<Pair<Span, String>> replacements) {
|
||||||
for (Import include : imports) {
|
for (Import include : imports) {
|
||||||
SourceFile file = include.getFile();
|
SourceFile file = include.getFile();
|
||||||
|
|
||||||
if (file != null && !env.exists(file)) {
|
if (file != null && !env.exists(file)) {
|
||||||
file.generateFinalSource(env, source);
|
file.generateFinalSource(env, source, replacements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +155,13 @@ public class SourceFile {
|
||||||
.append(" // ")
|
.append(" // ")
|
||||||
.append(name)
|
.append(name)
|
||||||
.append('\n');
|
.append('\n');
|
||||||
source.append(elided);
|
|
||||||
|
var replacementsAndElisions = new ArrayList<>(replacements);
|
||||||
|
for (Span elision : elisions) {
|
||||||
|
replacementsAndElisions.add(Pair.of(elision, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
source.append(this.replace(replacementsAndElisions));
|
||||||
source.append('\n');
|
source.append('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,18 +169,27 @@ public class SourceFile {
|
||||||
return "Source for shader '" + name + "':\n" + lines.printLinesWithNumbers();
|
return "Source for shader '" + name + "':\n" + lines.printLinesWithNumbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CharSequence elideSource(String source, List<Span> elisions) {
|
private CharSequence replace(List<Pair<Span, String>> replacements) {
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
|
|
||||||
int lastEnd = 0;
|
int lastEnd = 0;
|
||||||
|
|
||||||
for (Span elision : elisions) {
|
replacements.sort(Comparator.comparing(Pair::first));
|
||||||
out.append(source, lastEnd, elision.getStartPos());
|
|
||||||
|
|
||||||
lastEnd = elision.getEndPos();
|
for (var replacement : replacements) {
|
||||||
|
var loc = replacement.first();
|
||||||
|
|
||||||
|
if (loc.getSourceFile() != this) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.append(this.source, lastEnd, loc.getStartPos());
|
||||||
|
out.append(replacement.second());
|
||||||
|
|
||||||
|
lastEnd = loc.getEndPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
out.append(source, lastEnd, source.length());
|
out.append(this.source, lastEnd, this.source.length());
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -179,7 +198,7 @@ public class SourceFile {
|
||||||
* Scan the source for function definitions and "parse" them into objects that contain properties of the function.
|
* Scan the source for function definitions and "parse" them into objects that contain properties of the function.
|
||||||
*/
|
*/
|
||||||
private ImmutableMap<String, ShaderFunction> parseFunctions() {
|
private ImmutableMap<String, ShaderFunction> parseFunctions() {
|
||||||
Matcher matcher = ShaderFunction.functionDeclaration.matcher(source);
|
Matcher matcher = ShaderFunction.PATTERN.matcher(source);
|
||||||
|
|
||||||
Map<String, ShaderFunction> functions = new HashMap<>();
|
Map<String, ShaderFunction> functions = new HashMap<>();
|
||||||
|
|
||||||
|
@ -229,12 +248,31 @@ public class SourceFile {
|
||||||
return structs.build();
|
return structs.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan the source for function definitions and "parse" them into objects that contain properties of the function.
|
||||||
|
*/
|
||||||
|
private ImmutableMap<String, ShaderField> parseFields() {
|
||||||
|
Matcher matcher = ShaderField.PATTERN.matcher(source);
|
||||||
|
|
||||||
|
ImmutableMap.Builder<String, ShaderField> fields = ImmutableMap.builder();
|
||||||
|
while (matcher.find()) {
|
||||||
|
Span self = Span.fromMatcher(this, matcher);
|
||||||
|
Span location = Span.fromMatcher(this, matcher, 1);
|
||||||
|
Span decoration = Span.fromMatcher(this, matcher, 2);
|
||||||
|
Span type = Span.fromMatcher(this, matcher, 3);
|
||||||
|
Span name = Span.fromMatcher(this, matcher, 4);
|
||||||
|
|
||||||
|
fields.put(location.get(), new ShaderField(self, location, decoration, type, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields.build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan the source for {@code #use "..."} directives.
|
* Scan the source for {@code #use "..."} directives.
|
||||||
* Records the contents of the directive into an {@link Import} object, and marks the directive for elision.
|
* Records the contents of the directive into an {@link Import} object, and marks the directive for elision.
|
||||||
* @param elisions
|
|
||||||
*/
|
*/
|
||||||
private ImmutableList<Import> parseImports(ErrorReporter errorReporter, List<Span> elisions) {
|
private ImmutableList<Import> parseImports(ErrorReporter errorReporter) {
|
||||||
Matcher uses = Import.PATTERN.matcher(source);
|
Matcher uses = Import.PATTERN.matcher(source);
|
||||||
|
|
||||||
Set<String> importedFiles = new HashSet<>();
|
Set<String> importedFiles = new HashSet<>();
|
||||||
|
@ -253,7 +291,7 @@ public class SourceFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elisions.add(use); // we have to trim that later
|
this.elisions.add(use); // we have to trim that later
|
||||||
}
|
}
|
||||||
|
|
||||||
return ImmutableList.copyOf(imports);
|
return ImmutableList.copyOf(imports);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import com.jozufozu.flywheel.core.source.span.Span;
|
||||||
public class ShaderFunction extends AbstractShaderElement {
|
public class ShaderFunction extends AbstractShaderElement {
|
||||||
|
|
||||||
// https://regexr.com/60n3d
|
// https://regexr.com/60n3d
|
||||||
public static final Pattern functionDeclaration = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{");
|
public static final Pattern PATTERN = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{");
|
||||||
|
|
||||||
public static final Pattern argument = Pattern.compile("(?:(inout|in|out) )?(\\w+)\\s+(\\w+)");
|
public static final Pattern argument = Pattern.compile("(?:(inout|in|out) )?(\\w+)\\s+(\\w+)");
|
||||||
public static final Pattern assignment = Pattern.compile("(\\w+)\\s*=");
|
public static final Pattern assignment = Pattern.compile("(\\w+)\\s*=");
|
||||||
|
|
|
@ -3,6 +3,8 @@ package com.jozufozu.flywheel.core.source.span;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||||
import com.jozufozu.flywheel.core.source.parse.ShaderFunction;
|
import com.jozufozu.flywheel.core.source.parse.ShaderFunction;
|
||||||
import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
|
import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
|
||||||
|
@ -14,7 +16,7 @@ import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
|
||||||
* Spans are used for pretty-printing errors.
|
* Spans are used for pretty-printing errors.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public abstract class Span implements CharSequence {
|
public abstract class Span implements CharSequence, Comparable<Span> {
|
||||||
|
|
||||||
protected final SourceFile in;
|
protected final SourceFile in;
|
||||||
protected final CharPos start;
|
protected final CharPos start;
|
||||||
|
@ -138,4 +140,9 @@ public abstract class Span implements CharSequence {
|
||||||
}
|
}
|
||||||
return in.findFunction(this);
|
return in.findFunction(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull Span o) {
|
||||||
|
return Integer.compareUnsigned(getStartPos(), o.getStartPos());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import com.jozufozu.flywheel.util.ResourceUtil;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class InstanceShaders {
|
public class InstanceShaders {
|
||||||
public static final BiConsumer<ErrorReporter, SourceFile> CHECK = SourceChecks.checkFunctionParameterTypeExists("flw_instanceVertex", 1, 0);
|
public static final BiConsumer<ErrorReporter, SourceFile> CHECK = SourceChecks.checkFunctionArity("flw_instanceVertex", 0);
|
||||||
|
|
||||||
public static final FileResolution TRANSFORMED = create(ResourceUtil.subPath(Names.TRANSFORMED, ".vert"));
|
public static final FileResolution TRANSFORMED = create(ResourceUtil.subPath(Names.TRANSFORMED, ".vert"));
|
||||||
public static final FileResolution ORIENTED = create(ResourceUtil.subPath(Names.ORIENTED, ".vert"));
|
public static final FileResolution ORIENTED = create(ResourceUtil.subPath(Names.ORIENTED, ".vert"));
|
||||||
|
|
|
@ -2,17 +2,15 @@
|
||||||
#use "flywheel:util/light.glsl"
|
#use "flywheel:util/light.glsl"
|
||||||
#use "flywheel:util/quaternion.glsl"
|
#use "flywheel:util/quaternion.glsl"
|
||||||
|
|
||||||
struct Oriented {
|
layout (location = 0) in vec2 oriented_light;
|
||||||
vec2 light;
|
layout (location = 1) in vec4 oriented_color;
|
||||||
vec4 color;
|
layout (location = 2) in vec3 oriented_pos;
|
||||||
vec3 pos;
|
layout (location = 3) in vec3 oriented_pivot;
|
||||||
vec3 pivot;
|
layout (location = 4) in vec4 oriented_rotation;
|
||||||
vec4 rotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
void flw_instanceVertex(Oriented oriented) {
|
void flw_instanceVertex() {
|
||||||
flw_vertexPos = vec4(rotateVertexByQuat(flw_vertexPos.xyz - oriented.pivot, oriented.rotation) + oriented.pivot + oriented.pos, 1.0);
|
flw_vertexPos = vec4(rotateVertexByQuat(flw_vertexPos.xyz - oriented_pivot, oriented_rotation) + oriented_pivot + oriented_pos, 1.0);
|
||||||
flw_vertexNormal = rotateVertexByQuat(flw_vertexNormal, oriented.rotation);
|
flw_vertexNormal = rotateVertexByQuat(flw_vertexNormal, oriented_rotation);
|
||||||
flw_vertexColor = oriented.color;
|
flw_vertexColor = oriented_color;
|
||||||
flw_vertexLight = shiftLight(oriented.light);
|
flw_vertexLight = shiftLight(oriented_light);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
#use "flywheel:api/vertex.glsl"
|
#use "flywheel:api/vertex.glsl"
|
||||||
#use "flywheel:util/light.glsl"
|
#use "flywheel:util/light.glsl"
|
||||||
|
|
||||||
struct Instance {
|
layout (location = 0) in vec2 transformed_light;
|
||||||
vec2 light;
|
layout (location = 1) in vec4 transformed_color;
|
||||||
vec4 color;
|
layout (location = 2) in mat4 transformed_pose;
|
||||||
mat4 transform;
|
layout (location = 6) in mat3 transformed_normal;
|
||||||
mat3 normalMat;
|
|
||||||
};
|
|
||||||
|
|
||||||
void flw_instanceVertex(Instance instance) {
|
void flw_instanceVertex() {
|
||||||
flw_vertexPos = instance.transform * flw_vertexPos;
|
flw_vertexPos = transformed_pose * flw_vertexPos;
|
||||||
flw_vertexNormal = instance.normalMat * flw_vertexNormal;
|
flw_vertexNormal = transformed_normal * flw_vertexNormal;
|
||||||
flw_vertexColor = instance.color;
|
flw_vertexColor = transformed_color;
|
||||||
flw_vertexLight = shiftLight(instance.light);
|
flw_vertexLight = shiftLight(transformed_light);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue