Merge remote-tracking branch 'origin/1.18/dev' into 1.18/fabric/dev

Conflicts:
	build.gradle
	gradle.properties
	src/main/java/com/jozufozu/flywheel/core/model/BakedModelBuilder.java
	src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java
	src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java
	src/main/java/com/jozufozu/flywheel/core/model/WorldModelBuilder.java
	src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java
This commit is contained in:
PepperCode1 2023-07-07 11:46:29 -06:00
commit 95cf9dbe78
30 changed files with 290 additions and 362 deletions

View file

@ -17,7 +17,7 @@ targetCompatibility = JavaVersion.VERSION_17
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
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'))
repositories {
maven {
@ -52,19 +52,24 @@ repositories {
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${minecraft_version}"
mappings loom.layered() {
officialMojangMappings()
parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip")
if (Boolean.parseBoolean(project.use_parchment)) {
mappings loom.layered() {
officialMojangMappings()
parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip")
}
} else {
mappings loom.officialMojangMappings()
}
modImplementation "net.fabricmc:fabric-loader:${loader_version}"
// Fabric API
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
modCompileOnly 'curse.maven:starlight-521783:3667443'
// switch to implementation for debugging
modCompileOnly 'maven.modrinth:starlight:1.0.2+1.18.2'
modCompileOnly 'maven.modrinth:iris:1.18.x-v1.2.5'
modCompileOnly 'maven.modrinth:sodium:mc1.18.2-0.4.1'
modCompileOnly 'maven.modrinth:iris:1.6.4+1.18.2'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
modCompileOnly 'maven.modrinth:indium:1.0.6+mc1.18.2'

View file

@ -2,18 +2,20 @@ org.gradle.jvmargs = -Xmx3G
org.gradle.daemon = false
# mod version info
mod_version = 0.6.8.a
mod_version = 0.6.9
artifact_minecraft_version = 1.18.2
minecraft_version = 1.18.2
loader_version = 0.14.9
fabric_version = 0.66.0+1.18.2
loader_version = 0.14.21
fabric_version = 0.76.0+1.18.2
# build dependency versions
loom_version = 1.0-SNAPSHOT
loom_version = 1.1-SNAPSHOT
cursegradle_version = 1.4.0
parchment_version = 2022.11.06
use_parchment = true
# curseforge info
projectId = 486392
curse_type = release

Binary file not shown.

View file

@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

18
gradlew vendored
View file

@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -80,10 +80,10 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@ -143,12 +143,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -205,6 +209,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.

15
gradlew.bat vendored
View file

@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal

View file

@ -25,11 +25,11 @@ public interface Material<D extends InstanceData> {
Instancer<D> model(Object key, Supplier<Model> modelSupplier);
default Instancer<D> getModel(PartialModel partial, BlockState referenceState) {
return model(partial, () -> new BlockModel(partial.get(), referenceState));
return model(partial, () -> BlockModel.of(partial.get(), referenceState));
}
default Instancer<D> getModel(PartialModel partial) {
return model(partial, () -> new BlockModel(partial.get(), Blocks.AIR.defaultBlockState()));
return model(partial, () -> BlockModel.of(partial.get(), Blocks.AIR.defaultBlockState()));
}
default Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir) {
@ -37,10 +37,10 @@ public interface Material<D extends InstanceData> {
}
default Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<PoseStack> modelTransform) {
return model(Pair.of(dir, partial), () -> new BlockModel(partial.get(), referenceState, modelTransform.get()));
return model(Pair.of(dir, partial), () -> BlockModel.of(partial.get(), referenceState, modelTransform.get()));
}
default Instancer<D> getModel(BlockState toRender) {
return model(toRender, () -> new BlockModel(toRender));
return model(toRender, () -> BlockModel.of(toRender));
}
}

View file

@ -41,4 +41,7 @@ public interface VertexList {
default boolean isEmpty() {
return getVertexCount() == 0;
}
default void delete() {
}
}

View file

@ -3,10 +3,10 @@ package com.jozufozu.flywheel.backend.instancing;
import java.nio.ByteBuffer;
import org.jetbrains.annotations.ApiStatus;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
import com.mojang.blaze3d.platform.MemoryTracker;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.RenderType;
@ -48,10 +48,10 @@ public class DrawBuffer {
int byteSize = format.getVertexSize() * (vertexCount + 1);
if (backingBuffer == null) {
backingBuffer = MemoryTracker.create(byteSize);
backingBuffer = MemoryUtil.memAlloc(byteSize);
}
if (byteSize > backingBuffer.capacity()) {
backingBuffer = MemoryTracker.resize(backingBuffer, byteSize);
backingBuffer = MemoryUtil.memRealloc(backingBuffer, byteSize);
}
return new DirectVertexConsumer(backingBuffer, format, vertexCount);

View file

@ -2,7 +2,6 @@ package com.jozufozu.flywheel.core;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
import com.jozufozu.flywheel.core.shader.NormalDebugStateProvider;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.core.source.FileResolution;
@ -15,7 +14,7 @@ import net.minecraft.resources.ResourceLocation;
public class Contexts {
public static ProgramCompiler<WorldProgram> WORLD;
public static ProgramCompiler<CrumblingProgram> CRUMBLING;
public static ProgramCompiler<WorldProgram> CRUMBLING;
public static void flwInit(GatherContextEvent event) {
GameStateRegistry.register(NormalDebugStateProvider.INSTANCE);
@ -24,7 +23,7 @@ public class Contexts {
FileResolution crumblingBuiltins = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".glsl"));
WORLD = ProgramCompiler.create(Templates.INSTANCING, WorldProgram::new, worldBuiltins);
CRUMBLING = ProgramCompiler.create(Templates.INSTANCING, CrumblingProgram::new, crumblingBuiltins);
CRUMBLING = ProgramCompiler.create(Templates.INSTANCING, WorldProgram::new, crumblingBuiltins);
}
public static class Names {

View file

@ -1,48 +0,0 @@
package com.jozufozu.flywheel.core.crumbling;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.mixin.atlas.SheetDataAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.resources.ResourceLocation;
/**
* Track width and height of all created texture atlases.
*
* @see com.jozufozu.flywheel.mixin.atlas.AtlasDataMixin
*/
public class AtlasInfo {
private static final Map<ResourceLocation, SheetSize> sheetData = new HashMap<>();
@Nullable
public static TextureAtlas getAtlas(ResourceLocation name) {
AbstractTexture texture = Minecraft.getInstance().getTextureManager().getTexture(name);
if (texture instanceof TextureAtlas atlas)
return atlas;
else
return null;
}
@Nullable
public static SheetSize getSheetSize(@Nullable ResourceLocation loc) {
return sheetData.get(loc);
}
/**
* FOR USE IN MIXIN
*/
public static void _setAtlasData(ResourceLocation atlas, SheetDataAccessor accessor) {
sheetData.put(atlas, new SheetSize(accessor.flywheel$getWidth(), accessor.flywheel$getHeight()));
}
public record SheetSize(int width, int height) {
}
}

View file

@ -3,16 +3,13 @@ package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.backend.RenderLayer;
import com.jozufozu.flywheel.backend.instancing.instancing.InstancedMaterialGroup;
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.util.Textures;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.math.Matrix4f;
import net.minecraft.client.renderer.RenderType;
public class CrumblingGroup<P extends CrumblingProgram> extends InstancedMaterialGroup<P> {
private int width;
private int height;
public class CrumblingGroup<P extends WorldProgram> extends InstancedMaterialGroup<P> {
public CrumblingGroup(InstancingEngine<P> owner, RenderType type) {
super(owner, type);
@ -21,41 +18,9 @@ public class CrumblingGroup<P extends CrumblingProgram> extends InstancedMateria
// XXX See notes of overriden method
@Override
public void render(Matrix4f viewProjection, double camX, double camY, double camZ, RenderLayer layer) {
type.setupRenderState();
int renderTex = RenderSystem.getShaderTexture(0);
updateAtlasSize();
type.clearRenderState();
CrumblingRenderer._currentLayer.setupRenderState();
int breakingTex = RenderSystem.getShaderTexture(0);
RenderSystem.setShaderTexture(0, renderTex);
RenderSystem.setShaderTexture(4, breakingTex);
Textures.bindActiveTextures();
renderAll(viewProjection, camX, camY, camZ, layer);
CrumblingRenderer._currentLayer.clearRenderState();
}
private void updateAtlasSize() {
AtlasInfo.SheetSize sheetSize = AtlasInfo.getSheetSize(Textures.getShaderTexture(0));
if (sheetSize != null) {
width = sheetSize.width();
height = sheetSize.height();
} else {
width = height = 256;
}
}
@Override
protected void setup(P p) {
p.setAtlasSize(width, height);
}
}

View file

@ -1,42 +0,0 @@
package com.jozufozu.flywheel.core.crumbling;
import static org.lwjgl.opengl.GL20.glUniform2f;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;
public class CrumblingProgram extends WorldProgram {
protected final int uTextureScale;
protected int uCrumbling;
public CrumblingProgram(ResourceLocation name, int handle) {
super(name, handle);
uTextureScale = getUniformLocation("uTextureScale");
}
@Override
protected void registerSamplers() {
super.registerSamplers();
uCrumbling = setSamplerBinding("uCrumbling", 4);
}
public void setTextureScale(float x, float y) {
glUniform2f(uTextureScale, x, y);
}
public void setAtlasSize(int width, int height) {
TextureAtlas blockAtlas = AtlasInfo.getAtlas(InventoryMenu.BLOCK_ATLAS);
if (blockAtlas == null) return;
TextureAtlasSprite sprite = blockAtlas.getSprite(ModelBakery.BREAKING_LOCATIONS.get(0));
setTextureScale(width / (float) sprite.getWidth(), height / (float) sprite.getHeight());
}
}

View file

@ -6,17 +6,16 @@ import java.util.SortedSet;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine;
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.event.RenderLayerEvent;
import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
import com.jozufozu.flywheel.util.Lazy;
import com.jozufozu.flywheel.util.Pair;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
@ -26,8 +25,6 @@ import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.BlockDestructionProgress;
@ -61,17 +58,14 @@ public class CrumblingRenderer {
// XXX Restore state
GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
CrumblingRenderer.renderBreaking(activeStages, new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z));
renderCrumbling(activeStages, camera, new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z));
restoreState.restore();
}
private static void renderBreaking(Int2ObjectMap<List<BlockEntity>> activeStages, RenderLayerEvent event) {
private static void renderCrumbling(Int2ObjectMap<List<BlockEntity>> activeStages, Camera camera, RenderLayerEvent event) {
State state = STATE.get();
InstanceManager<BlockEntity> instanceManager = state.instanceManager;
InstancingEngine<CrumblingProgram> materials = state.materialManager;
TextureManager textureManager = Minecraft.getInstance().getTextureManager();
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
InstancingEngine<WorldProgram> materials = state.materialManager;
for (Int2ObjectMap.Entry<List<BlockEntity>> stage : activeStages.int2ObjectEntrySet()) {
_currentLayer = ModelBakery.DESTROY_TYPES.get(stage.getIntKey());
@ -80,22 +74,14 @@ public class CrumblingRenderer {
if (_currentLayer != null) {
stage.getValue().forEach(instanceManager::add);
instanceManager.beginFrame(SerialTaskEngine.INSTANCE, info);
instanceManager.beginFrame(SerialTaskEngine.INSTANCE, camera);
// XXX Each call applies another restore state even though we are already inside of a restore state
materials.render(SerialTaskEngine.INSTANCE, event);
instanceManager.invalidate();
}
}
// XXX Inconsistent GL state cleanup
// If texture binding and active unit need to be restored, store them in variables before GL state is changed
// instead of guessing that unit 0 and crumbling tex 0 are correct
GlTextureUnit.T0.makeActive();
AbstractTexture breaking = textureManager.getTexture(ModelBakery.BREAKING_LOCATIONS.get(0));
if (breaking != null) RenderSystem.bindTexture(breaking.getId());
}
/**
@ -138,7 +124,7 @@ public class CrumblingRenderer {
}
private static class State {
private final InstancingEngine<CrumblingProgram> materialManager;
private final InstancingEngine<WorldProgram> materialManager;
private final InstanceManager<BlockEntity> instanceManager;
private State() {

View file

@ -10,7 +10,6 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
import com.mojang.blaze3d.platform.MemoryTracker;
public class ModelPart implements Model {
@ -29,7 +28,7 @@ public class ModelPart implements Model {
this.vertices = vertices;
}
ByteBuffer buffer = MemoryTracker.create(size());
ByteBuffer buffer = MemoryUtil.memAlloc(size());
PosTexNormalWriterUnsafe writer = Formats.POS_TEX_NORMAL.createWriter(buffer);
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
cuboid.buffer(writer);
@ -65,12 +64,6 @@ public class ModelPart implements Model {
@Override
public void delete() {
if (reader instanceof AutoCloseable closeable) {
try {
closeable.close();
} catch (Exception e) {
//
}
}
reader.delete();
}
}

View file

@ -42,11 +42,19 @@ public final class BakedModelBuilder implements Bufferable {
}
@Override
public void bufferInto(ModelBlockRenderer blockRenderer, VertexConsumer consumer, Random random) {
public void bufferInto(VertexConsumer consumer, ModelBlockRenderer blockRenderer, Random random) {
BakedModel model = DefaultLayerFilteringBakedModel.wrap(this.model);
if (consumer instanceof ShadeSeparatingVertexConsumer shadeSeparatingWrapper) {
model = shadeSeparatingWrapper.wrapModel(model);
}
blockRenderer.tesselateBlock(renderWorld, model, referenceState, BlockPos.ZERO, poseStack, consumer, false, random, 42, OverlayTexture.NO_OVERLAY);
}
public BlockModel toModel(String name) {
return BlockModel.of(this, name);
}
public BlockModel toModel() {
return toModel(referenceState.toString());
}
}

View file

@ -1,8 +1,12 @@
package com.jozufozu.flywheel.core.model;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.Formats;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
@ -17,28 +21,55 @@ public class BlockModel implements Model {
private final VertexList reader;
private final String name;
public BlockModel(BlockState state) {
this(Minecraft.getInstance()
public BlockModel(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, int unshadedStartVertex, String name) {
if (drawState.format() != DefaultVertexFormat.BLOCK) {
throw new RuntimeException("Cannot use buffered data with non-block format '" + drawState.format() + "'");
}
reader = Formats.BLOCK.createReader(vertexBuffer, drawState.vertexCount(), unshadedStartVertex);
this.name = name;
}
public BlockModel(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, String name) {
if (drawState.format() != DefaultVertexFormat.BLOCK) {
throw new RuntimeException("Cannot use buffered data with non-block format '" + drawState.format() + "'");
}
reader = Formats.BLOCK.createReader(vertexBuffer, drawState.vertexCount());
this.name = name;
}
public BlockModel(ShadeSeparatedBufferedData data, String name) {
this(data.vertexBuffer(), data.drawState(), data.unshadedStartVertex(), name);
}
public static BlockModel of(Bufferable bufferable, String name) {
ShadeSeparatedBufferedData data = bufferable.build();
BlockModel model = new BlockModel(data, name);
data.release();
return model;
}
public static BlockModel of(BakedModel model, BlockState referenceState) {
ShadeSeparatedBufferedData data = ModelUtil.getBufferedData(model, referenceState);
BlockModel blockModel = new BlockModel(data, referenceState.toString());
data.release();
return blockModel;
}
public static BlockModel of(BlockState state) {
return of(Minecraft.getInstance()
.getBlockRenderer()
.getBlockModel(state), state);
}
public BlockModel(BakedModel model, BlockState referenceState) {
this(new BakedModelBuilder(model).withReferenceState(referenceState), referenceState.toString());
}
public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) {
this(new BakedModelBuilder(model).withReferenceState(referenceState)
.withPoseStack(ms), referenceState.toString());
}
public BlockModel(Bufferable bufferable, String name) {
this(bufferable.build(), name);
}
public BlockModel(ShadeSeparatedBufferBuilder bufferBuilder, String name) {
this.name = name;
reader = Formats.BLOCK.createReader(bufferBuilder);
public static BlockModel of(BakedModel model, BlockState referenceState, PoseStack ms) {
ShadeSeparatedBufferedData data = ModelUtil.getBufferedData(model, referenceState, ms);
BlockModel blockModel = new BlockModel(data, referenceState.toString());
data.release();
return blockModel;
}
@Override
@ -63,12 +94,6 @@ public class BlockModel implements Model {
@Override
public void delete() {
if (reader instanceof AutoCloseable closeable) {
try {
closeable.close();
} catch (Exception e) {
//
}
}
reader.delete();
}
}

View file

@ -8,12 +8,12 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
/**
* An interface for objects that can "rendered" into a BufferBuilder.
* An interface for objects that can buffered into a VertexConsumer.
*/
public interface Bufferable {
void bufferInto(ModelBlockRenderer renderer, VertexConsumer consumer, Random random);
void bufferInto(VertexConsumer consumer, ModelBlockRenderer renderer, Random random);
default ShadeSeparatedBufferBuilder build() {
return ModelUtil.getBufferBuilder(this);
default ShadeSeparatedBufferedData build() {
return ModelUtil.getBufferedData(this);
}
}

View file

@ -1,14 +1,19 @@
package com.jozufozu.flywheel.core.model;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Random;
import java.util.function.Supplier;
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderType;
@ -22,39 +27,53 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
public class ModelUtil {
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
public static ShadeSeparatedBufferBuilder getBufferBuilder(Bufferable bufferable) {
public static ShadeSeparatedBufferedData endAndCombine(BufferBuilder shadedBuilder, BufferBuilder unshadedBuilder) {
int unshadedStartVertex = ((BufferBuilderExtension) shadedBuilder).flywheel$getVertices();
unshadedBuilder.end();
Pair<DrawState, ByteBuffer> unshadedData = unshadedBuilder.popNextBuffer();
BufferBuilderHelper.fixByteOrder(unshadedBuilder, unshadedData.getSecond());
((BufferBuilderExtension) shadedBuilder).flywheel$appendBufferUnsafe(unshadedData.getSecond());
shadedBuilder.end();
Pair<DrawState, ByteBuffer> data = shadedBuilder.popNextBuffer();
return new ShadeSeparatedBufferedData.NativeImpl(data.getSecond(), data.getFirst(), unshadedStartVertex);
}
public static ShadeSeparatedBufferedData getBufferedData(Bufferable bufferable) {
ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer();
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
objects.begin();
bufferable.bufferInto(blockRenderer, objects.shadeSeparatingWrapper, objects.random);
bufferable.bufferInto(objects.shadeSeparatingWrapper, blockRenderer, objects.random);
objects.end();
return objects.separatedBufferBuilder;
return objects.end();
}
public static ShadeSeparatedBufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack poseStack) {
public static ShadeSeparatedBufferedData getBufferedData(BakedModel model, BlockState referenceState) {
return new BakedModelBuilder(model).withReferenceState(referenceState)
.build();
}
public static ShadeSeparatedBufferedData getBufferedData(BakedModel model, BlockState referenceState, PoseStack poseStack) {
return new BakedModelBuilder(model).withReferenceState(referenceState)
.withPoseStack(poseStack)
.build();
}
public static ShadeSeparatedBufferBuilder getBufferBuilder(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) {
public static ShadeSeparatedBufferedData getBufferedData(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) {
return new BakedModelBuilder(model).withReferenceState(referenceState)
.withPoseStack(poseStack)
.withRenderWorld(renderWorld)
.build();
}
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
public static ShadeSeparatedBufferedData getBufferedDataFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
return new WorldModelBuilder(layer).withRenderWorld(renderWorld)
.withBlocks(blocks)
.build();
}
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, PoseStack poseStack) {
public static ShadeSeparatedBufferedData getBufferedDataFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, PoseStack poseStack) {
return new WorldModelBuilder(layer).withRenderWorld(renderWorld)
.withBlocks(blocks)
.withPoseStack(poseStack)
@ -75,20 +94,18 @@ public class ModelUtil {
private static class ThreadLocalObjects {
public final Random random = new Random();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final ShadeSeparatedBufferBuilder separatedBufferBuilder = new ShadeSeparatedBufferBuilder(512);
public final BufferBuilder shadedBuilder = new BufferBuilder(512);
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
private void begin() {
this.separatedBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
this.shadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
this.unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
this.shadeSeparatingWrapper.prepare(this.separatedBufferBuilder, this.unshadedBuilder);
this.shadeSeparatingWrapper.prepare(this.shadedBuilder, this.unshadedBuilder);
}
private void end() {
private ShadeSeparatedBufferedData end() {
this.shadeSeparatingWrapper.clear();
this.unshadedBuilder.end();
this.separatedBufferBuilder.appendUnshadedVertices(this.unshadedBuilder);
this.separatedBufferBuilder.end();
return ModelUtil.endAndCombine(shadedBuilder, unshadedBuilder);
}
}
}

View file

@ -1,28 +0,0 @@
package com.jozufozu.flywheel.core.model;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.datafixers.util.Pair;
public class ShadeSeparatedBufferBuilder extends BufferBuilder {
protected int unshadedStartVertex;
public ShadeSeparatedBufferBuilder(int capacity) {
super(capacity);
}
public void appendUnshadedVertices(BufferBuilder unshadedBuilder) {
Pair<DrawState, ByteBuffer> data = unshadedBuilder.popNextBuffer();
ByteBuffer buffer = data.getSecond();
BufferBuilderHelper.fixByteOrder(unshadedBuilder, buffer);
unshadedStartVertex = ((BufferBuilderExtension) this).flywheel$getVertices();
((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(buffer);
}
public int getUnshadedStartVertex() {
return unshadedStartVertex;
}
}

View file

@ -0,0 +1,51 @@
package com.jozufozu.flywheel.core.model;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.FlwUtil;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
public interface ShadeSeparatedBufferedData {
ByteBuffer vertexBuffer();
BufferBuilder.DrawState drawState();
int unshadedStartVertex();
void release();
static final class NativeImpl implements ShadeSeparatedBufferedData {
private final ByteBuffer vertexBuffer;
private final BufferBuilder.DrawState drawState;
private final int unshadedStartVertex;
public NativeImpl(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, int unshadedStartVertex) {
this.vertexBuffer = FlwUtil.copyBuffer(vertexBuffer);
this.drawState = drawState;
this.unshadedStartVertex = unshadedStartVertex;
}
@Override
public ByteBuffer vertexBuffer() {
return vertexBuffer;
}
@Override
public DrawState drawState() {
return drawState;
}
@Override
public int unshadedStartVertex() {
return unshadedStartVertex;
}
@Override
public void release() {
MemoryUtil.memFree(vertexBuffer);
}
}
}

View file

@ -36,7 +36,7 @@ public final class WorldModelBuilder implements Bufferable {
}
@Override
public void bufferInto(ModelBlockRenderer modelRenderer, VertexConsumer consumer, Random random) {
public void bufferInto(VertexConsumer consumer, ModelBlockRenderer modelRenderer, Random random) {
BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer();
ModelBlockRenderer.enableCaching();
@ -86,7 +86,7 @@ public final class WorldModelBuilder implements Bufferable {
return this;
}
public BlockModel intoMesh(String name) {
return new BlockModel(this, name);
public BlockModel toModel(String name) {
return BlockModel.of(this, name);
}
}

View file

@ -1,39 +1,31 @@
package com.jozufozu.flywheel.core.vertex;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.mojang.blaze3d.platform.MemoryTracker;
import com.jozufozu.flywheel.util.FlwUtil;
public abstract class AbstractVertexList implements VertexList, AutoCloseable {
public abstract class AbstractVertexList implements VertexList {
protected final ByteBuffer contents;
protected final long base;
protected final int vertexCount;
protected AbstractVertexList(ByteBuffer copyFrom, int vertexCount) {
this.contents = MemoryTracker.create(copyFrom.capacity());
this.contents = FlwUtil.copyBuffer(copyFrom);
this.vertexCount = vertexCount;
this.base = MemoryUtil.memAddress(this.contents);
init(copyFrom);
}
private void init(ByteBuffer copyFrom) {
this.contents.order(copyFrom.order());
this.contents.put(copyFrom);
((Buffer) this.contents).flip();
}
@Override
public void close() {
MemoryUtil.memFree(contents);
}
@Override
public int getVertexCount() {
return vertexCount;
}
@Override
public void delete() {
MemoryUtil.memFree(contents);
}
}

View file

@ -2,15 +2,9 @@ package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.datafixers.util.Pair;
public class BlockVertex implements VertexType {
@ -38,6 +32,10 @@ public class BlockVertex implements VertexType {
return new BlockVertexListUnsafe(buffer, vertexCount);
}
public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex);
}
@Override
public String getShaderHeader() {
return """
@ -58,26 +56,4 @@ Vertex FLWCreateVertex() {
}
""";
}
public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex);
}
public VertexList createReader(BufferBuilder bufferBuilder) {
// TODO: try to avoid virtual model rendering
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
BufferBuilder.DrawState drawState = pair.getFirst();
if (drawState.format() != DefaultVertexFormat.BLOCK) {
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format());
}
ByteBuffer buffer = pair.getSecond();
BufferBuilderHelper.fixByteOrder(bufferBuilder, buffer);
if (bufferBuilder instanceof ShadeSeparatedBufferBuilder separated) {
return createReader(buffer, drawState.vertexCount(), separated.getUnshadedStartVertex());
} else {
return createReader(buffer, drawState.vertexCount());
}
}
}

View file

@ -1,28 +0,0 @@
package com.jozufozu.flywheel.mixin.atlas;
import java.util.stream.Stream;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.jozufozu.flywheel.core.crumbling.AtlasInfo;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.profiling.ProfilerFiller;
@Mixin(TextureAtlas.class)
public abstract class AtlasDataMixin {
@Shadow
public abstract ResourceLocation location();
@Inject(method = "prepareToStitch", at = @At("RETURN"))
public void stealAtlasData(ResourceManager resourceManager, Stream<ResourceLocation> locationStream, ProfilerFiller profiler, int mipMapLevels, CallbackInfoReturnable<TextureAtlas.Preparations> cir) {
AtlasInfo._setAtlasData(location(), (SheetDataAccessor) cir.getReturnValue());
}
}

View file

@ -1,17 +0,0 @@
package com.jozufozu.flywheel.mixin.atlas;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.renderer.texture.TextureAtlas;
@Mixin(TextureAtlas.Preparations.class)
public interface SheetDataAccessor {
@Accessor("width")
int flywheel$getWidth();
@Accessor("height")
int flywheel$getHeight();
}

View file

@ -1,9 +1,12 @@
package com.jozufozu.flywheel.util;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Stream;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.mixin.BlockEntityRenderDispatcherAccessor;
import net.minecraft.client.Minecraft;
@ -73,4 +76,17 @@ public class FlwUtil {
public static <R> Stream<R> mapValues(Map<?, R> map) {
return map.values().stream();
}
/**
* The returned buffer is backed by native memory and will cause a memory leak if not freed using {@link MemoryUtil#memFree(java.nio.Buffer)}.
*/
public static ByteBuffer copyBuffer(ByteBuffer buffer) {
int pos = buffer.position();
ByteBuffer copy = MemoryUtil.memAlloc(buffer.remaining());
copy.order(buffer.order());
copy.put(buffer);
buffer.position(pos);
copy.flip();
return copy;
}
}

View file

@ -4,15 +4,60 @@ uniform float uTime;
uniform mat4 uViewProjection;
uniform vec3 uCameraPos;
uniform vec2 uTextureScale;
uniform sampler2D uBlockAtlas;
uniform sampler2D uLightMap;
uniform sampler2D uCrumbling;
uniform vec2 uWindowSize;
#if defined(VERTEX_SHADER)
// Replicates the result of SheetedDecalTextureGenerator.java
vec2 crumblingUV(vec3 pos, vec3 normal) {
float maxLen = -2;
int face = 2;
if (-normal.y > maxLen) {
maxLen = -normal.y;
face = 0;
}
if (normal.y > maxLen) {
maxLen = normal.y;
face = 1;
}
if (-normal.z > maxLen) {
maxLen = -normal.z;
face = 2;
}
if (normal.z > maxLen) {
maxLen = normal.z;
face = 3;
}
if (-normal.x > maxLen) {
maxLen = -normal.x;
face = 4;
}
if (normal.x > maxLen) {
maxLen = normal.x;
face = 5;
}
if (face == 0) {
return vec2(pos.x, -pos.z);
} else if (face == 1) {
return vec2(pos.x, pos.z);
} else if (face == 3) {
return vec2(pos.x, -pos.y);
} else if (face == 4) {
return vec2(-pos.z, -pos.y);
} else if (face == 5) {
return vec2(pos.z, -pos.y);
} else { // face == 2
return vec2(-pos.x, -pos.y);
}
}
vec4 FLWVertex(inout Vertex v) {
v.texCoords = crumblingUV(v.pos, normalize(v.normal));
FragDistance = cylindrical_distance(v.pos, uCameraPos);
return uViewProjection * vec4(v.pos, 1.);
@ -23,10 +68,7 @@ vec4 FLWVertex(inout Vertex v) {
out vec4 fragColor;
vec4 FLWBlockTexture(vec2 texCoords) {
vec4 cr = texture(uCrumbling, texCoords * uTextureScale);
float diffuseAlpha = texture(uBlockAtlas, texCoords).a;
cr.a = cr.a * diffuseAlpha;
return cr;
return texture(uBlockAtlas, texCoords);
}
void FLWFinalizeColor(vec4 color) {

View file

@ -4,7 +4,6 @@ uniform float uTime;
uniform mat4 uViewProjection;
uniform vec3 uCameraPos;
uniform vec2 uTextureScale;
uniform sampler2D uBlockAtlas;
uniform sampler2D uLightMap;

View file

@ -19,8 +19,6 @@
"PausedPartialTickAccessor",
"RenderTexturesMixin",
"RenderTypeMixin",
"atlas.AtlasDataMixin",
"atlas.SheetDataAccessor",
"instancemanage.ChunkRebuildHooksMixin",
"instancemanage.InstanceAddMixin",
"instancemanage.InstanceRemoveMixin",