mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-07 12:56:31 +01:00
Things on the screen
- Specialize MeshPool for the indirect engine - Temporarily force the engine to be indirect - Fix compilation issues with test shaders - VertexAttribute supports DSA - Fix Miniball issues in dev-env - VertexList implements PointSet for use with Miniball - Meshes store their bounding spheres - Add hook/system property to load renderdoc on client launch - StructTypes provide separate StorageBufferWriter for indirect
This commit is contained in:
parent
6234df6440
commit
9d657aed40
36 changed files with 644 additions and 131 deletions
32
build.gradle
32
build.gradle
|
@ -21,6 +21,8 @@ apply plugin: 'eclipse'
|
||||||
apply plugin: 'maven-publish'
|
apply plugin: 'maven-publish'
|
||||||
apply plugin: 'org.spongepowered.mixin'
|
apply plugin: 'org.spongepowered.mixin'
|
||||||
|
|
||||||
|
jarJar.enable()
|
||||||
|
|
||||||
boolean dev = System.getenv('RELEASE') == null || System.getenv('RELEASE').equalsIgnoreCase('false');
|
boolean dev = System.getenv('RELEASE') == null || System.getenv('RELEASE').equalsIgnoreCase('false');
|
||||||
|
|
||||||
ext.buildNumber = System.getenv('BUILD_NUMBER')
|
ext.buildNumber = System.getenv('BUILD_NUMBER')
|
||||||
|
@ -31,8 +33,6 @@ version = mod_version + (dev && buildNumber != null ? "-${buildNumber}" : '')
|
||||||
|
|
||||||
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
|
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
|
||||||
|
|
||||||
jarJar.enable()
|
|
||||||
|
|
||||||
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
||||||
minecraft {
|
minecraft {
|
||||||
mappings channel: 'parchment', version: "${parchment_version}-${minecraft_version}"
|
mappings channel: 'parchment', version: "${parchment_version}-${minecraft_version}"
|
||||||
|
@ -47,6 +47,7 @@ minecraft {
|
||||||
property 'mixin.env.remapRefMap', 'true'
|
property 'mixin.env.remapRefMap', 'true'
|
||||||
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
|
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
|
||||||
property 'flw.dumpShaderSource', 'true'
|
property 'flw.dumpShaderSource', 'true'
|
||||||
|
property 'flw.loadRenderDoc', 'true'
|
||||||
|
|
||||||
arg '-mixin.config=flywheel.mixins.json'
|
arg '-mixin.config=flywheel.mixins.json'
|
||||||
|
|
||||||
|
@ -108,15 +109,31 @@ repositories {
|
||||||
includeGroup "maven.modrinth"
|
includeGroup "maven.modrinth"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix for loading non-mod libraries in dev-env, used for miniball.
|
||||||
|
// https://gist.github.com/SizableShrimp/66b22f1b24c255e1491c8d98d3f11f83
|
||||||
|
// v--------------------------------------------------------------------v
|
||||||
|
configurations {
|
||||||
|
library
|
||||||
|
implementation.extendsFrom library
|
||||||
|
}
|
||||||
|
|
||||||
|
minecraft.runs.all {
|
||||||
|
lazyToken('minecraft_classpath') {
|
||||||
|
configurations.library.copyRecursive().resolve().collect { it.absolutePath }.join(File.pathSeparator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ^--------------------------------------------------------------------^
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
|
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
|
||||||
|
|
||||||
implementation "com.dreizak:miniball:1.0.3"
|
jarJar(group: 'com.dreizak', name: 'miniball', version: "1.0.3") {
|
||||||
jarJar(group: 'com.dreizak', name: 'miniball', version: '[1.0,2.0)') {
|
jarJar.ranged(it, "[1.0,2.0)")
|
||||||
jarJar.pin(it, "[1.0,2.0)")
|
|
||||||
}
|
}
|
||||||
|
library "com.dreizak:miniball:1.0.3"
|
||||||
|
|
||||||
// switch to implementation for debugging
|
// switch to implementation for debugging
|
||||||
compileOnly fg.deobf("maven.modrinth:starlight-forge:1.0.2+1.18.2")
|
compileOnly fg.deobf("maven.modrinth:starlight-forge:1.0.2+1.18.2")
|
||||||
|
@ -139,6 +156,7 @@ mixin {
|
||||||
// Workaround for SpongePowered/MixinGradle#38
|
// Workaround for SpongePowered/MixinGradle#38
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
tasks.configureReobfTaskForReobfJar.mustRunAfter(tasks.compileJava)
|
tasks.configureReobfTaskForReobfJar.mustRunAfter(tasks.compileJava)
|
||||||
|
tasks.configureReobfTaskForReobfJarJar.mustRunAfter(tasks.compileJava)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
@ -151,6 +169,10 @@ javadoc {
|
||||||
options.addStringOption('Xdoclint:none', '-quiet')
|
options.addStringOption('Xdoclint:none', '-quiet')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
options.compilerArgs = ['-Xdiags:verbose']
|
||||||
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
manifest {
|
||||||
attributes([
|
attributes([
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.jozufozu.flywheel.api.struct;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||||
|
|
||||||
|
public interface StorageBufferWriter<T extends InstancedPart> {
|
||||||
|
|
||||||
|
void write(final long ptr, final T instance, final int batchID);
|
||||||
|
|
||||||
|
int getAlignment();
|
||||||
|
}
|
|
@ -36,6 +36,8 @@ public interface StructType<S extends InstancedPart> {
|
||||||
|
|
||||||
VertexTransformer<? extends S> getVertexTransformer();
|
VertexTransformer<? extends S> getVertexTransformer();
|
||||||
|
|
||||||
|
StorageBufferWriter<S> getStorageBufferWriter();
|
||||||
|
|
||||||
public interface VertexTransformer<S extends InstancedPart> {
|
public interface VertexTransformer<S extends InstancedPart> {
|
||||||
void transform(MutableVertexList vertexList, S struct, ClientLevel level);
|
void transform(MutableVertexList vertexList, S struct, ClientLevel level);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.jozufozu.flywheel.api.vertex;
|
package com.jozufozu.flywheel.api.vertex;
|
||||||
|
|
||||||
|
import com.dreizak.miniball.model.PointSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A read only view of a vertex buffer.
|
* A read only view of a vertex buffer.
|
||||||
*
|
*
|
||||||
|
@ -9,7 +11,7 @@ package com.jozufozu.flywheel.api.vertex;
|
||||||
* </p>
|
* </p>
|
||||||
* TODO: more flexible elements?
|
* TODO: more flexible elements?
|
||||||
*/
|
*/
|
||||||
public interface VertexList {
|
public interface VertexList extends PointSet {
|
||||||
float x(int index);
|
float x(int index);
|
||||||
|
|
||||||
float y(int index);
|
float y(int index);
|
||||||
|
@ -47,4 +49,24 @@ public interface VertexList {
|
||||||
default boolean isEmpty() {
|
default boolean isEmpty() {
|
||||||
return getVertexCount() == 0;
|
return getVertexCount() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default int size() {
|
||||||
|
return getVertexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default int dimension() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default double coord(int i, int j) {
|
||||||
|
return switch (j) {
|
||||||
|
case 0 -> x(i);
|
||||||
|
case 1 -> y(i);
|
||||||
|
case 2 -> z(i);
|
||||||
|
default -> throw new IllegalArgumentException("Invalid dimension: " + j);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,8 @@ public class Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void refresh() {
|
public static void refresh() {
|
||||||
TYPE = chooseEngine();
|
// TODO: Revert when done testing
|
||||||
|
TYPE = BackendType.INDIRECT; // chooseEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isOn() {
|
public static boolean isOn() {
|
||||||
|
|
|
@ -26,4 +26,8 @@ public enum GLSLVersion {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Integer.toString(version);
|
return Integer.toString(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getVersionLine() {
|
||||||
|
return "#version " + version + '\n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,18 @@ package com.jozufozu.flywheel.backend.gl.array;
|
||||||
public interface VertexAttribute {
|
public interface VertexAttribute {
|
||||||
int getByteWidth();
|
int getByteWidth();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this vertex attribute to the bound vertex array.
|
||||||
|
* @param offset The byte offset to the first element of the attribute.
|
||||||
|
* @param i The attribute index.
|
||||||
|
* @param stride The byte stride between consecutive elements of the attribute.
|
||||||
|
*/
|
||||||
void pointer(long offset, int i, int stride);
|
void pointer(long offset, int i, int stride);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use DSA to apply this vertex attribute to the given vertex array.
|
||||||
|
* @param vaobj The vertex array object to modify.
|
||||||
|
* @param i The attribute index.
|
||||||
|
*/
|
||||||
|
void format(int vaobj, int i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.jozufozu.flywheel.backend.gl.array;
|
package com.jozufozu.flywheel.backend.gl.array;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.opengl.GL45;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||||
|
|
||||||
|
@ -22,4 +23,9 @@ public record VertexAttributeF(GlNumericType type, int size, boolean normalized)
|
||||||
public void pointer(long offset, int i, int stride) {
|
public void pointer(long offset, int i, int stride) {
|
||||||
GL32.glVertexAttribPointer(i, size(), type().getGlEnum(), normalized(), stride, offset);
|
GL32.glVertexAttribPointer(i, size(), type().getGlEnum(), normalized(), stride, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void format(int vaobj, int i) {
|
||||||
|
GL45.glVertexArrayAttribFormat(vaobj, i, size(), type().getGlEnum(), normalized(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.jozufozu.flywheel.backend.gl.array;
|
package com.jozufozu.flywheel.backend.gl.array;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.opengl.GL45;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||||
|
|
||||||
|
@ -21,4 +22,9 @@ public record VertexAttributeI(GlNumericType type, int size) implements VertexAt
|
||||||
public void pointer(long offset, int i, int stride) {
|
public void pointer(long offset, int i, int stride) {
|
||||||
GL32.glVertexAttribIPointer(i, size(), type().getGlEnum(), stride, offset);
|
GL32.glVertexAttribIPointer(i, size(), type().getGlEnum(), stride, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void format(int vaobj, int i) {
|
||||||
|
GL45.glVertexArrayAttribIFormat(vaobj, i, size(), type().getGlEnum(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||||
import com.jozufozu.flywheel.api.instancer.Instancer;
|
import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||||
|
@ -60,6 +61,14 @@ public abstract class AbstractInstancer<D extends InstancedPart> implements Inst
|
||||||
return data.size();
|
return data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<D> getRange(int start, int end) {
|
||||||
|
return data.subList(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<D> getAll() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
protected void removeDeletedInstances() {
|
protected void removeDeletedInstances() {
|
||||||
// Figure out which elements are to be removed.
|
// Figure out which elements are to be removed.
|
||||||
final int oldSize = this.data.size();
|
final int oldSize = this.data.size();
|
||||||
|
|
|
@ -19,14 +19,6 @@ public class CPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<D> getRange(int start, int end) {
|
|
||||||
return data.subList(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<D> getAll() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyDirty() {
|
public void notifyDirty() {
|
||||||
// noop
|
// noop
|
||||||
|
|
|
@ -1,34 +1,42 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.indirect;
|
package com.jozufozu.flywheel.backend.instancing.indirect;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
import com.jozufozu.flywheel.core.compile.Memoizer;
|
import com.jozufozu.flywheel.core.compile.Memoizer;
|
||||||
import com.jozufozu.flywheel.core.compile.ProgramAssembler;
|
import com.jozufozu.flywheel.core.compile.ProgramAssembler;
|
||||||
|
import com.jozufozu.flywheel.core.compile.ShaderCompilationException;
|
||||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
|
|
||||||
public class ComputeCompiler extends Memoizer<FileResolution, GlProgram> {
|
public class ComputeCullerCompiler extends Memoizer<FileResolution, GlProgram> {
|
||||||
|
|
||||||
public static final ComputeCompiler INSTANCE = new ComputeCompiler();
|
public static final ComputeCullerCompiler INSTANCE = new ComputeCullerCompiler();
|
||||||
|
|
||||||
private ComputeCompiler() {
|
private ComputeCullerCompiler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected GlProgram _create(FileResolution file) {
|
protected GlProgram _create(FileResolution file) {
|
||||||
|
|
||||||
|
CompilationContext context = new CompilationContext();
|
||||||
|
|
||||||
|
var header = GLSLVersion.V460.getVersionLine();
|
||||||
String source = file.getFile()
|
String source = file.getFile()
|
||||||
.generateFinalSource(new CompilationContext());
|
.generateFinalSource(context);
|
||||||
|
|
||||||
var shader = new GlShader(source, ShaderType.COMPUTE, ImmutableList.of(file.getFileLoc()));
|
try {
|
||||||
|
var shader = new GlShader(header + source, ShaderType.COMPUTE, ImmutableList.of(file.getFileLoc()));
|
||||||
|
|
||||||
return new ProgramAssembler(file.getFileLoc())
|
return new ProgramAssembler(file.getFileLoc()).attachShader(shader)
|
||||||
.attachShader(shader)
|
.link()
|
||||||
.link()
|
.build(GlProgram::new);
|
||||||
.build(GlProgram::new);
|
} catch (ShaderCompilationException e) {
|
||||||
|
throw e.withErrorLog(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -1,10 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.indirect;
|
|
||||||
|
|
||||||
public class DSABuffer {
|
|
||||||
int id;
|
|
||||||
int byteSize;
|
|
||||||
|
|
||||||
public DSABuffer(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.indirect;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
|
import com.jozufozu.flywheel.core.WorldProgram;
|
||||||
|
import com.jozufozu.flywheel.core.compile.CompileUtil;
|
||||||
|
import com.jozufozu.flywheel.core.compile.Memoizer;
|
||||||
|
import com.jozufozu.flywheel.core.compile.ProgramAssembler;
|
||||||
|
import com.jozufozu.flywheel.core.compile.ShaderCompilationException;
|
||||||
|
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||||
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
|
||||||
|
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||||
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
|
|
||||||
|
public class IndirectDrawCompiler extends Memoizer<IndirectDrawCompiler.Program, GlProgram> {
|
||||||
|
public static final IndirectDrawCompiler INSTANCE = new IndirectDrawCompiler();
|
||||||
|
|
||||||
|
private IndirectDrawCompiler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GlProgram _create(IndirectDrawCompiler.Program program) {
|
||||||
|
|
||||||
|
GlShader vertexShader = compile(program.vertex.getFile(), ShaderType.VERTEX);
|
||||||
|
GlShader fragmentShader = compile(program.fragment.getFile(), ShaderType.FRAGMENT);
|
||||||
|
|
||||||
|
return new ProgramAssembler(program.vertex.getFileLoc())
|
||||||
|
.attachShader(vertexShader)
|
||||||
|
.attachShader(fragmentShader)
|
||||||
|
.link()
|
||||||
|
.build(WorldProgram::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static GlShader compile(SourceFile file, ShaderType type) {
|
||||||
|
var context = new CompilationContext();
|
||||||
|
try {
|
||||||
|
var header = CompileUtil.generateHeader(GLSLVersion.V460, type);
|
||||||
|
var source = file.generateFinalSource(context);
|
||||||
|
|
||||||
|
return new GlShader(header + source, type, ImmutableList.of(file.name));
|
||||||
|
} catch (ShaderCompilationException e) {
|
||||||
|
throw e.withErrorLog(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _destroy(GlProgram value) {
|
||||||
|
value.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void invalidateAll(ReloadRenderersEvent ignored) {
|
||||||
|
INSTANCE.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Program(FileResolution vertex, FileResolution fragment) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -149,9 +149,6 @@ public class IndirectEngine implements Engine {
|
||||||
model.init(renderLists);
|
model.init(renderLists);
|
||||||
}
|
}
|
||||||
uninitializedModels.clear();
|
uninitializedModels.clear();
|
||||||
|
|
||||||
MeshPool.getInstance()
|
|
||||||
.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shiftListeners(int cX, int cY, int cZ) {
|
private void shiftListeners(int cX, int cY, int cZ) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class IndirectInstancer<D extends InstancedPart> extends AbstractInstance
|
||||||
public final BufferLayout instanceFormat;
|
public final BufferLayout instanceFormat;
|
||||||
public final StructType<D> structType;
|
public final StructType<D> structType;
|
||||||
public final InstancedModel<D> parent;
|
public final InstancedModel<D> parent;
|
||||||
int maxInstanceCount = 0;
|
int instanceCount = 0;
|
||||||
|
|
||||||
boolean anyToUpdate;
|
boolean anyToUpdate;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ public class IndirectInstancer<D extends InstancedPart> extends AbstractInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return !anyToUpdate && !anyToRemove && maxInstanceCount == 0;
|
return !anyToUpdate && !anyToRemove && instanceCount == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
|
@ -36,7 +36,7 @@ public class IndirectInstancer<D extends InstancedPart> extends AbstractInstance
|
||||||
removeDeletedInstances();
|
removeDeletedInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
maxInstanceCount = data.size();
|
instanceCount = data.size();
|
||||||
|
|
||||||
anyToRemove = false;
|
anyToRemove = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,121 +1,244 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.indirect;
|
package com.jozufozu.flywheel.backend.instancing.indirect;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
||||||
|
import java.text.Format;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL46;
|
|
||||||
import org.lwjgl.opengl.GL46C;
|
import org.lwjgl.opengl.GL46C;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||||
|
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.backend.instancing.instancing.MeshPool;
|
|
||||||
import com.jozufozu.flywheel.core.Components;
|
import com.jozufozu.flywheel.core.Components;
|
||||||
|
import com.jozufozu.flywheel.core.Materials;
|
||||||
|
import com.jozufozu.flywheel.core.QuadConverter;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
|
import com.jozufozu.flywheel.core.uniform.UniformBuffer;
|
||||||
|
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||||
|
|
||||||
public class IndirectList<T extends InstancedPart> {
|
public class IndirectList<T extends InstancedPart> {
|
||||||
|
|
||||||
|
private static final int DRAW_COMMAND_STRIDE = 20;
|
||||||
|
|
||||||
|
final StorageBufferWriter<T> storageBufferWriter;
|
||||||
final GlProgram compute;
|
final GlProgram compute;
|
||||||
final GlProgram draw;
|
final GlProgram draw;
|
||||||
|
private final StructType<T> type;
|
||||||
|
private final long maxObjectCount;
|
||||||
|
private final long objectStride;
|
||||||
|
private final int maxBatchCount;
|
||||||
|
private final long objectClientStorage;
|
||||||
|
private final int elementBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores raw instance data per-object.
|
* Stores raw instance data per-object.
|
||||||
*/
|
*/
|
||||||
DSABuffer objectBuffer;
|
int objectBuffer;
|
||||||
|
|
||||||
|
int targetBuffer;
|
||||||
/**
|
/**
|
||||||
* Stores bounding spheres
|
* Stores bounding spheres
|
||||||
*/
|
*/
|
||||||
DSABuffer boundingSphereBuffer;
|
int boundingSphereBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores drawIndirect structs.
|
* Stores drawIndirect structs.
|
||||||
*/
|
*/
|
||||||
DSABuffer drawBuffer;
|
int drawBuffer;
|
||||||
DSABuffer targetBuffer;
|
|
||||||
|
|
||||||
final int[] buffers = new int[4];
|
final IndirectMeshPool meshPool;
|
||||||
|
|
||||||
|
int vertexArray;
|
||||||
|
|
||||||
|
final int[] shaderStorageBuffers = new int[4];
|
||||||
|
|
||||||
final List<Batch<T>> batches = new ArrayList<>();
|
final List<Batch<T>> batches = new ArrayList<>();
|
||||||
|
|
||||||
IndirectList(StructType<T> structType) {
|
IndirectList(StructType<T> structType) {
|
||||||
GL46.glCreateBuffers(buffers);
|
type = structType;
|
||||||
objectBuffer = new DSABuffer(buffers[0]);
|
storageBufferWriter = type.getStorageBufferWriter();
|
||||||
targetBuffer = new DSABuffer(buffers[1]);
|
|
||||||
boundingSphereBuffer = new DSABuffer(buffers[2]);
|
|
||||||
drawBuffer = new DSABuffer(buffers[3]);
|
|
||||||
|
|
||||||
compute = ComputeCompiler.INSTANCE.get(Components.Files.CULL_INSTANCES);
|
if (storageBufferWriter == null) {
|
||||||
draw = null;
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
glCreateBuffers(shaderStorageBuffers);
|
||||||
|
objectBuffer = shaderStorageBuffers[0];
|
||||||
|
targetBuffer = shaderStorageBuffers[1];
|
||||||
|
boundingSphereBuffer = shaderStorageBuffers[2];
|
||||||
|
drawBuffer = shaderStorageBuffers[3];
|
||||||
|
meshPool = new IndirectMeshPool(Formats.BLOCK, 1024);
|
||||||
|
|
||||||
|
// FIXME: Resizable buffers
|
||||||
|
maxObjectCount = 1024L * 100L;
|
||||||
|
maxBatchCount = 64;
|
||||||
|
|
||||||
|
// +4 for the batch id
|
||||||
|
objectStride = storageBufferWriter.getAlignment();
|
||||||
|
glNamedBufferStorage(objectBuffer, objectStride * maxObjectCount, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
glNamedBufferStorage(targetBuffer, 4 * maxObjectCount, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
glNamedBufferStorage(boundingSphereBuffer, 16 * maxBatchCount, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
glNamedBufferStorage(drawBuffer, DRAW_COMMAND_STRIDE * maxBatchCount, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
|
||||||
|
objectClientStorage = MemoryUtil.nmemAlloc(objectStride * maxObjectCount);
|
||||||
|
|
||||||
|
vertexArray = glCreateVertexArrays();
|
||||||
|
|
||||||
|
elementBuffer = QuadConverter.getInstance()
|
||||||
|
.quads2Tris(2048).buffer.handle();
|
||||||
|
setupVertexArray();
|
||||||
|
|
||||||
|
compute = ComputeCullerCompiler.INSTANCE.get(Components.Files.CULL_INSTANCES);
|
||||||
|
draw = IndirectDrawCompiler.INSTANCE.get(new IndirectDrawCompiler.Program(Components.Files.DRAW_INDIRECT_VERTEX, Components.Files.DRAW_INDIRECT_FRAGMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupVertexArray() {
|
||||||
|
glVertexArrayElementBuffer(vertexArray, elementBuffer);
|
||||||
|
|
||||||
|
var meshLayout = Formats.BLOCK.getLayout();
|
||||||
|
var meshAttribs = meshLayout.getAttributeCount();
|
||||||
|
|
||||||
|
var attributes = meshLayout.getAttributes();
|
||||||
|
|
||||||
|
long offset = 0;
|
||||||
|
for (int i = 0; i < meshAttribs; i++) {
|
||||||
|
var attribute = attributes.get(i);
|
||||||
|
glEnableVertexArrayAttrib(vertexArray, i);
|
||||||
|
glVertexArrayVertexBuffer(vertexArray, i, meshPool.vbo, offset, meshLayout.getStride());
|
||||||
|
attribute.format(vertexArray, i);
|
||||||
|
offset += attribute
|
||||||
|
.getByteWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnableVertexArrayAttrib(vertexArray, meshAttribs);
|
||||||
|
glVertexArrayVertexBuffer(vertexArray, meshAttribs, targetBuffer, 0, 4);
|
||||||
|
glVertexArrayAttribIFormat(vertexArray, meshAttribs, 1, GlNumericType.UINT.getGlEnum(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(Mesh mesh, IndirectInstancer<T> instancer) {
|
public void add(Mesh mesh, IndirectInstancer<T> instancer) {
|
||||||
var pool = MeshPool.getInstance();
|
batches.add(new Batch<>(instancer, meshPool.alloc(mesh)));
|
||||||
var buffered = pool.alloc(mesh);
|
|
||||||
|
|
||||||
batches.add(new Batch<>(instancer, buffered));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepare() {
|
void submit() {
|
||||||
|
int instanceCountThisFrame = calculateTotalInstanceCount();
|
||||||
|
|
||||||
|
if (instanceCountThisFrame == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meshPool.uploadAll();
|
||||||
|
uploadInstanceData();
|
||||||
|
uploadBoundingSpheres();
|
||||||
|
uploadIndirectCommands();
|
||||||
|
|
||||||
|
UniformBuffer.getInstance().sync();
|
||||||
|
|
||||||
|
dispatchCompute(instanceCountThisFrame);
|
||||||
|
issueMemoryBarrier();
|
||||||
|
dispatchDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dispatchDraw() {
|
||||||
|
draw.bind();
|
||||||
|
Materials.BELL.setup();
|
||||||
|
glVertexArrayElementBuffer(vertexArray, elementBuffer);
|
||||||
|
glBindVertexArray(vertexArray);
|
||||||
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawBuffer);
|
||||||
|
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, batches.size(), 0);
|
||||||
|
Materials.BELL.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void issueMemoryBarrier() {
|
||||||
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadBoundingSpheres() {
|
||||||
try (var stack = MemoryStack.stackPush()) {
|
try (var stack = MemoryStack.stackPush()) {
|
||||||
var size = batches.size() * 20;
|
final int size = batches.size() * 16;
|
||||||
|
final long basePtr = stack.nmalloc(size);
|
||||||
|
|
||||||
|
long ptr = basePtr;
|
||||||
|
for (Batch<T> batch : batches) {
|
||||||
|
var boundingSphere = batch.mesh.mesh.getBoundingSphere();
|
||||||
|
boundingSphere.getToAddress(ptr);
|
||||||
|
ptr += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL46C.nglNamedBufferSubData(boundingSphereBuffer, 0, size, basePtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dispatchCompute(int instanceCount) {
|
||||||
|
compute.bind();
|
||||||
|
glBindBuffersBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffers);
|
||||||
|
|
||||||
|
var groupCount = (instanceCount + 31) >> 5; // ceil(totalInstanceCount / 32)
|
||||||
|
glDispatchCompute(groupCount, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadInstanceData() {
|
||||||
|
long ptr = objectClientStorage;
|
||||||
|
int baseInstance = 0;
|
||||||
|
int batchID = 0;
|
||||||
|
for (var batch : batches) {
|
||||||
|
batch.baseInstance = baseInstance;
|
||||||
|
var instancer = batch.instancer;
|
||||||
|
for (T t : instancer.getAll()) {
|
||||||
|
storageBufferWriter.write(ptr, t, batchID);
|
||||||
|
ptr += objectStride;
|
||||||
|
}
|
||||||
|
baseInstance += batch.instancer.instanceCount;
|
||||||
|
batchID++;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL46C.nglNamedBufferSubData(objectBuffer, 0, ptr - objectClientStorage, objectClientStorage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadIndirectCommands() {
|
||||||
|
try (var stack = MemoryStack.stackPush()) {
|
||||||
|
var size = batches.size() * DRAW_COMMAND_STRIDE;
|
||||||
long basePtr = stack.nmalloc(size);
|
long basePtr = stack.nmalloc(size);
|
||||||
long writePtr = basePtr;
|
long writePtr = basePtr;
|
||||||
for (Batch<T> batch : batches) {
|
for (Batch<T> batch : batches) {
|
||||||
batch.writeIndirectCommand(writePtr);
|
batch.writeIndirectCommand(writePtr);
|
||||||
writePtr += 20;
|
writePtr += DRAW_COMMAND_STRIDE;
|
||||||
}
|
}
|
||||||
GL46C.nglNamedBufferData(drawBuffer.id, size, basePtr, GL46.GL_STREAM_DRAW);
|
GL46C.nglNamedBufferSubData(drawBuffer, 0, size, basePtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void submit() {
|
private int calculateTotalInstanceCount() {
|
||||||
|
int total = 0;
|
||||||
compute.bind();
|
for (Batch<T> batch : batches) {
|
||||||
GL46.glBindBuffersBase(GL46.GL_SHADER_STORAGE_BUFFER, 0, buffers);
|
batch.instancer.update();
|
||||||
|
total += batch.instancer.instanceCount;
|
||||||
var groupCount = (getTotalInstanceCount() + 31) >> 5; // ceil(totalInstanceCount / 32)
|
}
|
||||||
GL46.glDispatchCompute(groupCount, 1, 1);
|
return total;
|
||||||
|
|
||||||
draw.bind();
|
|
||||||
GL46.glMemoryBarrier(GL46.GL_SHADER_STORAGE_BARRIER_BIT);
|
|
||||||
GL46.glBindBuffer(GL46.GL_DRAW_INDIRECT_BUFFER, drawBuffer.id);
|
|
||||||
|
|
||||||
GL46.glMultiDrawElementsIndirect(GL46.GL_TRIANGLES, GL46.GL_UNSIGNED_INT, 0, batches.size(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTotalInstanceCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class Batch<T extends InstancedPart> {
|
private static final class Batch<T extends InstancedPart> {
|
||||||
final IndirectInstancer<T> instancer;
|
final IndirectInstancer<T> instancer;
|
||||||
final MeshPool.BufferedMesh mesh;
|
final IndirectMeshPool.BufferedMesh mesh;
|
||||||
|
int baseInstance;
|
||||||
|
|
||||||
private Batch(IndirectInstancer<T> instancer, MeshPool.BufferedMesh mesh) {
|
private Batch(IndirectInstancer<T> instancer, IndirectMeshPool.BufferedMesh mesh) {
|
||||||
this.instancer = instancer;
|
this.instancer = instancer;
|
||||||
this.mesh = mesh;
|
this.mesh = mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeIndirectCommand(long ptr) {
|
public void writeIndirectCommand(long ptr) {
|
||||||
// typedef struct {
|
MemoryUtil.memPutInt(ptr, mesh.getVertexCount()); // count
|
||||||
// GLuint count;
|
MemoryUtil.memPutInt(ptr + 4, 0); // instanceCount - to be incremented by the compute shader
|
||||||
// GLuint instanceCount;
|
MemoryUtil.memPutInt(ptr + 8, 0); // firstIndex - all models share the same index buffer
|
||||||
// GLuint firstIndex;
|
MemoryUtil.memPutInt(ptr + 12, mesh.getBaseVertex()); // baseVertex
|
||||||
// GLuint baseVertex;
|
MemoryUtil.memPutInt(ptr + 16, baseInstance); // baseInstance
|
||||||
// GLuint baseInstance;
|
|
||||||
//} DrawElementsIndirectCommand;
|
|
||||||
|
|
||||||
MemoryUtil.memPutInt(ptr, mesh.getVertexCount());
|
|
||||||
MemoryUtil.memPutInt(ptr + 4, 0);
|
|
||||||
MemoryUtil.memPutInt(ptr + 8, 0);
|
|
||||||
MemoryUtil.memPutInt(ptr + 12, mesh.getBaseVertex());
|
|
||||||
MemoryUtil.memPutInt(ptr + 16, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.indirect;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||||
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
|
|
||||||
|
public class IndirectMeshPool {
|
||||||
|
|
||||||
|
private final Map<Mesh, BufferedMesh> meshes = new HashMap<>();
|
||||||
|
private final List<BufferedMesh> meshList = new ArrayList<>();
|
||||||
|
|
||||||
|
final VertexType vertexType;
|
||||||
|
|
||||||
|
final int vbo;
|
||||||
|
private final ByteBuffer clientStorage;
|
||||||
|
|
||||||
|
private boolean dirty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new mesh pool.
|
||||||
|
*/
|
||||||
|
public IndirectMeshPool(VertexType type, int vertexCapacity) {
|
||||||
|
vertexType = type;
|
||||||
|
vbo = glCreateBuffers();
|
||||||
|
var byteCapacity = type.byteOffset(vertexCapacity);
|
||||||
|
glNamedBufferStorage(vbo, byteCapacity, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
clientStorage = MemoryUtil.memAlloc(byteCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a model in the arena.
|
||||||
|
*
|
||||||
|
* @param mesh The model to allocate.
|
||||||
|
* @return A handle to the allocated model.
|
||||||
|
*/
|
||||||
|
public BufferedMesh alloc(Mesh mesh) {
|
||||||
|
return meshes.computeIfAbsent(mesh, m -> {
|
||||||
|
BufferedMesh bufferedModel = new BufferedMesh(m);
|
||||||
|
meshList.add(bufferedModel);
|
||||||
|
|
||||||
|
dirty = true;
|
||||||
|
return bufferedModel;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BufferedMesh get(Mesh mesh) {
|
||||||
|
return meshes.get(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uploadAll() {
|
||||||
|
if (!dirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dirty = false;
|
||||||
|
|
||||||
|
int byteIndex = 0;
|
||||||
|
int baseVertex = 0;
|
||||||
|
for (BufferedMesh model : meshList) {
|
||||||
|
model.byteIndex = byteIndex;
|
||||||
|
model.baseVertex = baseVertex;
|
||||||
|
|
||||||
|
model.buffer(clientStorage);
|
||||||
|
|
||||||
|
byteIndex += model.getByteSize();
|
||||||
|
baseVertex += model.mesh.getVertexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
glNamedBufferSubData(vbo, 0, clientStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() {
|
||||||
|
glDeleteBuffers(vbo);
|
||||||
|
meshes.clear();
|
||||||
|
meshList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BufferedMesh {
|
||||||
|
|
||||||
|
public final Mesh mesh;
|
||||||
|
private long byteIndex;
|
||||||
|
private int baseVertex;
|
||||||
|
|
||||||
|
public BufferedMesh(Mesh mesh) {
|
||||||
|
this.mesh = mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buffer(ByteBuffer buffer) {
|
||||||
|
var writer = IndirectMeshPool.this.vertexType.createWriter(buffer);
|
||||||
|
writer.seek(this.byteIndex);
|
||||||
|
writer.writeVertexList(this.mesh.getReader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getByteSize() {
|
||||||
|
return IndirectMeshPool.this.vertexType.getLayout().getStride() * this.mesh.getVertexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBaseVertex() {
|
||||||
|
return baseVertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVertexCount() {
|
||||||
|
return this.mesh.getVertexCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,13 +1,7 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.indirect;
|
package com.jozufozu.flywheel.backend.instancing.indirect;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.RenderStage;
|
|
||||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
|
||||||
import com.jozufozu.flywheel.core.model.Model;
|
import com.jozufozu.flywheel.core.model.Model;
|
||||||
|
|
||||||
public class InstancedModel<D extends InstancedPart> {
|
public class InstancedModel<D extends InstancedPart> {
|
||||||
|
@ -42,7 +36,7 @@ public class InstancedModel<D extends InstancedPart> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVertexCount() {
|
public int getVertexCount() {
|
||||||
return model.getVertexCount() * instancer.maxInstanceCount;
|
return model.getVertexCount() * instancer.instanceCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class MeshPool {
|
||||||
|
|
||||||
private static MeshPool allocator;
|
private static MeshPool allocator;
|
||||||
|
|
||||||
public static MeshPool getInstance() {
|
static MeshPool getInstance() {
|
||||||
if (allocator == null) {
|
if (allocator == null) {
|
||||||
allocator = new MeshPool();
|
allocator = new MeshPool();
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ public class MeshPool {
|
||||||
public class BufferedMesh {
|
public class BufferedMesh {
|
||||||
|
|
||||||
private final ElementBuffer ebo;
|
private final ElementBuffer ebo;
|
||||||
private final Mesh mesh;
|
public final Mesh mesh;
|
||||||
private final VertexType type;
|
private final VertexType type;
|
||||||
private long byteIndex;
|
private long byteIndex;
|
||||||
private int baseVertex;
|
private int baseVertex;
|
||||||
|
|
|
@ -49,6 +49,8 @@ public class Components {
|
||||||
public static final FileResolution CRUMBLING_VERTEX = contextVertex(ResourceUtil.subPath(Names.CRUMBLING, ".vert"));
|
public static final FileResolution CRUMBLING_VERTEX = contextVertex(ResourceUtil.subPath(Names.CRUMBLING, ".vert"));
|
||||||
public static final FileResolution CRUMBLING_FRAGMENT = contextFragment(ResourceUtil.subPath(Names.CRUMBLING, ".frag"));
|
public static final FileResolution CRUMBLING_FRAGMENT = contextFragment(ResourceUtil.subPath(Names.CRUMBLING, ".frag"));
|
||||||
public static final FileResolution CULL_INSTANCES = compute(Flywheel.rl("compute/cull_instances.glsl"));
|
public static final FileResolution CULL_INSTANCES = compute(Flywheel.rl("compute/cull_instances.glsl"));
|
||||||
|
public static final FileResolution DRAW_INDIRECT_VERTEX = FileResolution.get(ResourceUtil.subPath(Names.DRAW_INDIRECT, ".vert"));
|
||||||
|
public static final FileResolution DRAW_INDIRECT_FRAGMENT = FileResolution.get(ResourceUtil.subPath(Names.DRAW_INDIRECT, ".frag"));
|
||||||
|
|
||||||
private static FileResolution compute(ResourceLocation rl) {
|
private static FileResolution compute(ResourceLocation rl) {
|
||||||
return FileResolution.get(rl);
|
return FileResolution.get(rl);
|
||||||
|
@ -115,5 +117,6 @@ public class Components {
|
||||||
public static final ResourceLocation SHADED = Flywheel.rl("material/shaded");
|
public static final ResourceLocation SHADED = Flywheel.rl("material/shaded");
|
||||||
public static final ResourceLocation WORLD = Flywheel.rl("context/world");
|
public static final ResourceLocation WORLD = Flywheel.rl("context/world");
|
||||||
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling");
|
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling");
|
||||||
|
public static final ResourceLocation DRAW_INDIRECT = Flywheel.rl("compute/draw_instances");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,24 @@ package com.jozufozu.flywheel.core.hardcoded;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
|
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex;
|
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex;
|
||||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
||||||
|
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||||
|
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||||
|
|
||||||
public class ModelPart implements Mesh {
|
public class ModelPart implements Mesh {
|
||||||
|
|
||||||
private final int vertices;
|
private final int vertices;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final VertexList reader;
|
private final VertexList reader;
|
||||||
|
private final @NotNull Vector4f boundingSphere;
|
||||||
|
|
||||||
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) {
|
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -35,6 +40,8 @@ public class ModelPart implements Mesh {
|
||||||
|
|
||||||
reader = writer.intoReader(this.vertices);
|
reader = writer.intoReader(this.vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boundingSphere = ModelUtil.computeBoundingSphere(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PartBuilder builder(String name, int sizeU, int sizeV) {
|
public static PartBuilder builder(String name, int sizeU, int sizeV) {
|
||||||
|
@ -60,4 +67,9 @@ public class ModelPart implements Mesh {
|
||||||
public PosTexNormalVertex getVertexType() {
|
public PosTexNormalVertex getVertexType() {
|
||||||
return Formats.POS_TEX_NORMAL;
|
return Formats.POS_TEX_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector4fc getBoundingSphere() {
|
||||||
|
return boundingSphere;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class BufferLayout {
|
||||||
this.stride = calculateStride(this.attributes) + padding;
|
this.stride = calculateStride(this.attributes) + padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<VertexAttribute> getAttributes() {
|
public List<VertexAttribute> getAttributes() {
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexWriter;
|
import com.jozufozu.flywheel.api.vertex.VertexWriter;
|
||||||
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.core.QuadConverter;
|
import com.jozufozu.flywheel.core.QuadConverter;
|
||||||
|
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mesh that can be rendered by flywheel.
|
* A mesh that can be rendered by flywheel.
|
||||||
|
@ -39,6 +40,8 @@ public interface Mesh {
|
||||||
|
|
||||||
VertexList getReader();
|
VertexList getReader();
|
||||||
|
|
||||||
|
Vector4fc getBoundingSphere();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The number of vertices the model has.
|
* @return The number of vertices the model has.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.jozufozu.flywheel.core.model;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.dreizak.miniball.highdim.Miniball;
|
import com.dreizak.miniball.highdim.Miniball;
|
||||||
|
@ -11,6 +12,7 @@ import com.jozufozu.flywheel.api.material.Material;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.jozufozu.flywheel.core.Materials;
|
import com.jozufozu.flywheel.core.Materials;
|
||||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||||
|
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
@ -74,4 +76,12 @@ public class ModelUtil {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Vector4f computeBoundingSphere(VertexList reader) {
|
||||||
|
var miniball = new Miniball(reader);
|
||||||
|
double[] center = miniball.center();
|
||||||
|
double radius = miniball.radius();
|
||||||
|
return new Vector4f((float) center[0], (float) center[1], (float) center[2], (float) radius);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,21 @@ package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||||
|
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||||
|
|
||||||
public class SimpleMesh implements Mesh {
|
public class SimpleMesh implements Mesh {
|
||||||
private final VertexList reader;
|
private final VertexList reader;
|
||||||
private final VertexType vertexType;
|
private final VertexType vertexType;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private final Vector4f boundingSphere;
|
||||||
|
|
||||||
public SimpleMesh(VertexList reader, VertexType vertexType, String name) {
|
public SimpleMesh(VertexList reader, VertexType vertexType, String name) {
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
this.vertexType = vertexType;
|
this.vertexType = vertexType;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
|
boundingSphere = ModelUtil.computeBoundingSphere(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,6 +34,11 @@ public class SimpleMesh implements Mesh {
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector4fc getBoundingSphere() {
|
||||||
|
return boundingSphere;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SimpleMesh{" + "name='" + name + "',vertexType='" + vertexType + "}";
|
return "SimpleMesh{" + "name='" + name + "',vertexType='" + vertexType + "}";
|
||||||
|
|
|
@ -184,24 +184,24 @@ public class SourceFile {
|
||||||
return "#use " + '"' + name + '"';
|
return "#use " + '"' + name + '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateFinalSource(CompilationContext env) {
|
public String generateFinalSource(CompilationContext context) {
|
||||||
return generateFinalSource(env, Collections.emptyList());
|
return generateFinalSource(context, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateFinalSource(CompilationContext env, List<Pair<Span, String>> replacements) {
|
public String generateFinalSource(CompilationContext context, List<Pair<Span, String>> replacements) {
|
||||||
var out = new StringBuilder();
|
var out = new StringBuilder();
|
||||||
for (Import include : flattenedImports) {
|
for (Import include : flattenedImports) {
|
||||||
SourceFile file = include.getFile();
|
SourceFile file = include.getFile();
|
||||||
|
|
||||||
if (file == null || env.contains(file)) {
|
if (file == null || context.contains(file)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.append(file.generateLineHeader(env))
|
out.append(file.generateLineHeader(context))
|
||||||
.append(file.replaceAndElide(replacements));
|
.append(file.replaceAndElide(replacements));
|
||||||
}
|
}
|
||||||
|
|
||||||
out.append(this.generateLineHeader(env))
|
out.append(this.generateLineHeader(context))
|
||||||
.append(this.replaceAndElide(replacements));
|
.append(this.replaceAndElide(replacements));
|
||||||
|
|
||||||
return out.toString();
|
return out.toString();
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.jozufozu.flywheel.core.structs.model;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||||
import com.jozufozu.flywheel.core.Components;
|
import com.jozufozu.flywheel.core.Components;
|
||||||
|
@ -33,6 +34,11 @@ public class TransformedType implements StructType<TransformedPart> {
|
||||||
return new TransformedWriterUnsafe(this, backing);
|
return new TransformedWriterUnsafe(this, backing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StorageBufferWriter<TransformedPart> getStorageBufferWriter() {
|
||||||
|
return null; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileResolution getInstanceShader() {
|
public FileResolution getInstanceShader() {
|
||||||
return Components.Files.TRANSFORMED;
|
return Components.Files.TRANSFORMED;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.jozufozu.flywheel.core.structs.oriented;
|
||||||
|
|
||||||
|
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
|
||||||
|
|
||||||
|
public class OrientedStorageWriter implements StorageBufferWriter<OrientedPart> {
|
||||||
|
|
||||||
|
public static final OrientedStorageWriter INSTANCE = new OrientedStorageWriter();
|
||||||
|
|
||||||
|
private OrientedStorageWriter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(final long ptr, OrientedPart d, final int batchID) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, d.qX);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, d.qY);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 8, d.qZ);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 12, d.qW);
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr + 16, d.posX);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 20, d.posY);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 24, d.posZ);
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr + 28, d.pivotX);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 32, d.pivotY);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 36, d.pivotZ);
|
||||||
|
|
||||||
|
MemoryUtil.memPutShort(ptr + 40, d.blockLight);
|
||||||
|
MemoryUtil.memPutShort(ptr + 42, d.skyLight);
|
||||||
|
|
||||||
|
MemoryUtil.memPutByte(ptr + 44, d.r);
|
||||||
|
MemoryUtil.memPutByte(ptr + 45, d.g);
|
||||||
|
MemoryUtil.memPutByte(ptr + 46, d.b);
|
||||||
|
MemoryUtil.memPutByte(ptr + 47, d.a);
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr + 48, batchID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAlignment() {
|
||||||
|
return 52;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package com.jozufozu.flywheel.core.structs.oriented;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||||
import com.jozufozu.flywheel.core.Components;
|
import com.jozufozu.flywheel.core.Components;
|
||||||
|
@ -36,6 +37,11 @@ public class OrientedType implements StructType<OrientedPart> {
|
||||||
return new OrientedWriterUnsafe(this, backing);
|
return new OrientedWriterUnsafe(this, backing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OrientedStorageWriter getStorageBufferWriter() {
|
||||||
|
return OrientedStorageWriter.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileResolution getInstanceShader() {
|
public FileResolution getInstanceShader() {
|
||||||
return Components.Files.ORIENTED;
|
return Components.Files.ORIENTED;
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.jozufozu.flywheel.mixin;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import net.minecraft.client.main.Main;
|
||||||
|
|
||||||
|
@Mixin(Main.class)
|
||||||
|
public class ClientMainMixin {
|
||||||
|
@Inject(method = "main", at = @At("HEAD"))
|
||||||
|
private static void injectRenderDoc(CallbackInfo ci) {
|
||||||
|
// Only try to load RenderDoc if a system property is set.
|
||||||
|
if (System.getProperty("flw.loadRenderDoc") == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
System.loadLibrary("renderdoc");
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
// Oh well, we tried.
|
||||||
|
// On Windows, RenderDoc installs to "C:\Program Files\RenderDoc\"
|
||||||
|
System.err.println("Is RenderDoc in your PATH?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
#version 450
|
|
||||||
#define FLW_SUBGROUP_SIZE 32
|
#define FLW_SUBGROUP_SIZE 32
|
||||||
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
layout(local_size_x = FLW_SUBGROUP_SIZE) in;
|
||||||
#use "flywheel:compute/objects.glsl"
|
#use "flywheel:compute/objects.glsl"
|
||||||
#use "flywheel:util/quaternion.glsl"
|
#use "flywheel:util/quaternion.glsl"
|
||||||
|
|
||||||
layout(std130, binding = 3) uniform FrameData {
|
layout(std140, binding = 3) uniform FrameData {
|
||||||
vec4 a1; // vec4(nx.x, px.x, ny.x, py.x)
|
vec4 a1; // vec4(nx.x, px.x, ny.x, py.x)
|
||||||
vec4 a2; // vec4(nx.y, px.y, ny.y, py.y)
|
vec4 a2; // vec4(nx.y, px.y, ny.y, py.y)
|
||||||
vec4 a3; // vec4(nx.z, px.z, ny.z, py.z)
|
vec4 a3; // vec4(nx.z, px.z, ny.z, py.z)
|
||||||
|
@ -13,23 +12,22 @@ layout(std130, binding = 3) uniform FrameData {
|
||||||
vec2 b2; // vec2(nz.y, pz.y)
|
vec2 b2; // vec2(nz.y, pz.y)
|
||||||
vec2 b3; // vec2(nz.z, pz.z)
|
vec2 b3; // vec2(nz.z, pz.z)
|
||||||
vec2 b4; // vec2(nz.w, pz.w)
|
vec2 b4; // vec2(nz.w, pz.w)
|
||||||
uint drawCount;
|
|
||||||
} frustum;
|
} frustum;
|
||||||
|
|
||||||
// populated by instancers
|
// populated by instancers
|
||||||
layout(binding = 0) readonly buffer ObjectBuffer {
|
layout(std430, binding = 0) readonly buffer ObjectBuffer {
|
||||||
Instance objects[];
|
Instance objects[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 1) writeonly buffer TargetBuffer {
|
layout(std430, binding = 1) writeonly buffer TargetBuffer {
|
||||||
uint objectIDs[];
|
uint objectIDs[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 2) readonly buffer BoundingSpheres {
|
layout(std430, binding = 2) readonly buffer BoundingSpheres {
|
||||||
vec4 boundingSpheres[];
|
vec4 boundingSpheres[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 3) buffer DrawCommands {
|
layout(std430, binding = 3) buffer DrawCommands {
|
||||||
MeshDrawCommand drawCommands[];
|
MeshDrawCommand drawCommands[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,16 +42,16 @@ bool isVisible(uint objectID, uint batchID) {
|
||||||
vec4 sphere = boundingSpheres[batchID];
|
vec4 sphere = boundingSpheres[batchID];
|
||||||
|
|
||||||
vec3 pivot = objects[objectID].pivot;
|
vec3 pivot = objects[objectID].pivot;
|
||||||
vec3 center = rotateQuat(sphere.xyz - pivot, objects[objectID].orientation) + pivot + objects[objectID].position;
|
vec3 center = rotateVertexByQuat(sphere.xyz - pivot, objects[objectID].rotation) + pivot + objects[objectID].pos;
|
||||||
float radius = sphere.r;
|
float radius = sphere.r;
|
||||||
|
|
||||||
return testSphere(center, radius);
|
return true; //testSphere(center, radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
uint objectID = gl_GlobalInvocationID.x;
|
uint objectID = gl_GlobalInvocationID.x;
|
||||||
|
|
||||||
if (objectID >= frustum.drawCount) {
|
if (objectID >= objects.length()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
#use "flywheel:api/fragment.glsl"
|
||||||
|
#use "flywheel:context/world.frag"
|
||||||
|
#use "flywheel:material/default.frag"
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
flw_initFragment();
|
||||||
|
flw_materialFragment();
|
||||||
|
flw_contextFragment();
|
||||||
|
}
|
|
@ -1,22 +1,23 @@
|
||||||
#use "flywheel:api/vertex.glsl"
|
#use "flywheel:api/vertex.glsl"
|
||||||
#use "flywheel:compute/objects.glsl"
|
#use "flywheel:compute/objects.glsl"
|
||||||
#use "flywheel:pos_tex_normal.glsl"
|
#use "flywheel:layout/block.vert"
|
||||||
#use "flywheel:context/world.vert"
|
#use "flywheel:context/world.vert"
|
||||||
|
#use "flywheel:util/quaternion.glsl"
|
||||||
|
|
||||||
// populated by instancers
|
// populated by instancers
|
||||||
layout(binding = 0) readonly buffer ObjectBuffer {
|
layout(std430, binding = 0) readonly buffer ObjectBuffer {
|
||||||
Instance objects[];
|
Instance objects[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 1) readonly buffer TargetBuffer {
|
layout(std430, binding = 1) readonly buffer TargetBuffer {
|
||||||
uint objectIDs[];
|
uint objectIDs[];
|
||||||
};
|
};
|
||||||
|
|
||||||
void flw_instanceVertex(Instance i) {
|
void flw_instanceVertex(Instance i) {
|
||||||
flw_vertexPos = vec4(rotateVertexByQuat(flw_vertexPos.xyz - i.pivot, i.rotation) + i.pivot + i.pos, 1.0);
|
flw_vertexPos = vec4(rotateVertexByQuat(flw_vertexPos.xyz - i.pivot, i.rotation) + i.pivot + i.pos, 1.0);
|
||||||
flw_vertexNormal = rotateVertexByQuat(flw_vertexNormal, i.rotation);
|
flw_vertexNormal = rotateVertexByQuat(flw_vertexNormal, i.rotation);
|
||||||
flw_vertexColor = i.color;
|
flw_vertexColor = unpackUnorm4x8(i.color);
|
||||||
flw_vertexLight = i.light / 15.0;
|
flw_vertexLight = unpackUnorm2x16(i.light) / 15.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
|
|
||||||
struct Instance {
|
struct Instance {
|
||||||
ivec2 light;
|
vec4 rotation;
|
||||||
vec4 color;
|
|
||||||
vec3 pos;
|
vec3 pos;
|
||||||
vec3 pivot;
|
vec3 pivot;
|
||||||
vec4 rotation;
|
uint light;
|
||||||
|
uint color;
|
||||||
uint batchID;
|
uint batchID;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MeshDrawCommands {
|
struct MeshDrawCommand {
|
||||||
uint indexCount;
|
uint indexCount;
|
||||||
uint instanceCount;
|
uint instanceCount;
|
||||||
uint firstIndex;
|
uint firstIndex;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"BufferUploaderMixin",
|
"BufferUploaderMixin",
|
||||||
"ChunkRebuildHooksMixin",
|
"ChunkRebuildHooksMixin",
|
||||||
"ClientLevelMixin",
|
"ClientLevelMixin",
|
||||||
|
"ClientMainMixin",
|
||||||
"EntityTypeMixin",
|
"EntityTypeMixin",
|
||||||
"FixFabulousDepthMixin",
|
"FixFabulousDepthMixin",
|
||||||
"FogUpdateMixin",
|
"FogUpdateMixin",
|
||||||
|
|
Loading…
Reference in a new issue