Aggressively cache RenderMaterials
This commit is contained in:
parent
ed42e4da9f
commit
97de0d1b9c
@ -5,6 +5,8 @@ import io.github.cottonmc.templates.model.TemplateModelVariantProvider;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
|
||||
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
@ -13,10 +15,17 @@ import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourceType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.ChunkSectionPos;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class TemplatesClient implements ClientModInitializer {
|
||||
public static TemplateModelVariantProvider provider = new TemplateModelVariantProvider();
|
||||
|
||||
public static @NotNull Renderer getFabricRenderer() {
|
||||
return Objects.requireNonNull(RendererAccess.INSTANCE.getRenderer(), "A Fabric Rendering API implementation is required to use Templates!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
Templates.chunkRerenderProxy = (world, pos) -> {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.cottonmc.templates.model;
|
||||
|
||||
import io.github.cottonmc.templates.TemplatesClient;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
@ -18,8 +19,7 @@ public class SlopeBaseMesh {
|
||||
public static final int TAG_BOTTOM = Direction.DOWN.ordinal();
|
||||
|
||||
public static Mesh make() {
|
||||
Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
||||
if(renderer == null) throw new IllegalStateException("RenderAccess.INSTANCE not populated - no Fabric Renderer API?");
|
||||
Renderer renderer = TemplatesClient.getFabricRenderer();
|
||||
|
||||
MeshBuilder builder = renderer.meshBuilder();
|
||||
QuadEmitter qu = builder.getEmitter();
|
||||
|
@ -1,19 +1,13 @@
|
||||
package io.github.cottonmc.templates.model;
|
||||
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
|
||||
import net.fabricmc.fabric.api.util.TriState;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.color.block.BlockColorProvider;
|
||||
import net.minecraft.client.render.RenderLayers;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@ -22,17 +16,15 @@ import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class SlopeQuadTransformFactory implements TemplateQuadTransformFactory {
|
||||
public SlopeQuadTransformFactory(TemplateAppearanceManager tam) {
|
||||
this.tam = tam;
|
||||
this.r = Objects.requireNonNull(RendererAccess.INSTANCE.getRenderer(), "A Fabric Rendering API implementation is required");
|
||||
}
|
||||
|
||||
private final TemplateAppearanceManager tam;
|
||||
private final Renderer r;
|
||||
|
||||
@Override
|
||||
public @NotNull RenderContext.QuadTransform blockTransformer(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier) {
|
||||
@ -41,40 +33,31 @@ public class SlopeQuadTransformFactory implements TemplateQuadTransformFactory {
|
||||
Block block = template.getBlock();
|
||||
|
||||
TemplateAppearance appearance;
|
||||
RenderMaterial material;
|
||||
int globalTint;
|
||||
int globalTint = 0xFFFFFF;
|
||||
|
||||
if(block == Blocks.AIR) {
|
||||
appearance = tam.getDefaultAppearance();
|
||||
material = r.materialFinder().clear().blendMode(BlendMode.CUTOUT).find();
|
||||
globalTint = 0xFFFFFF;
|
||||
} else {
|
||||
appearance = tam.getAppearance(template);
|
||||
material = r.materialFinder().clear()
|
||||
.disableDiffuse(false)
|
||||
.ambientOcclusion(TriState.FALSE)
|
||||
.blendMode(BlendMode.fromRenderLayer(RenderLayers.getBlockLayer(template)))
|
||||
.find();
|
||||
|
||||
BlockColorProvider tint = ColorProviderRegistry.BLOCK.get(block);
|
||||
if(tint != null) globalTint = 0xFF000000 | tint.getColor(template, blockView, pos, 1);
|
||||
else globalTint = 0xFFFFFF;
|
||||
}
|
||||
|
||||
return new Transformer(appearance, material, globalTint);
|
||||
return new Transformer(appearance, globalTint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RenderContext.QuadTransform itemTransformer(ItemStack stack, Supplier<Random> randomSupplier) {
|
||||
return new Transformer(tam.getDefaultAppearance(), r.materialFinder().clear().find(), 0xFFFFFF);
|
||||
return new Transformer(tam.getDefaultAppearance(), 0xFFFFFF);
|
||||
}
|
||||
|
||||
public static record Transformer(TemplateAppearance appearance, RenderMaterial material, int color) implements RenderContext.QuadTransform {
|
||||
public static record Transformer(TemplateAppearance appearance, int color) implements RenderContext.QuadTransform {
|
||||
private static final Direction[] DIRECTIONS = Direction.values();
|
||||
|
||||
@Override
|
||||
public boolean transform(MutableQuadView quad) {
|
||||
quad.material(material);
|
||||
quad.material(appearance.getRenderMaterial());
|
||||
|
||||
//The quad tag numbers were selected so this magic trick works:
|
||||
Direction dir = DIRECTIONS[quad.tag()];
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.cottonmc.templates.model;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -8,27 +9,10 @@ import java.util.Objects;
|
||||
|
||||
public interface TemplateAppearance {
|
||||
@NotNull Sprite getParticleSprite(); //TODO: plug this in
|
||||
|
||||
@NotNull RenderMaterial getRenderMaterial();
|
||||
@NotNull Sprite getSprite(Direction dir);
|
||||
boolean hasColor(Direction dir);
|
||||
|
||||
record SingleSprite(@NotNull Sprite defaultSprite) implements TemplateAppearance {
|
||||
public SingleSprite(Sprite defaultSprite) {
|
||||
this.defaultSprite = Objects.requireNonNull(defaultSprite);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sprite getParticleSprite() {
|
||||
return defaultSprite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sprite getSprite(Direction dir) {
|
||||
return defaultSprite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasColor(Direction dir) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,15 @@
|
||||
package io.github.cottonmc.templates.model;
|
||||
|
||||
import io.github.cottonmc.templates.TemplatesClient;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.util.TriState;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderLayers;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.texture.MissingSprite;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
@ -13,22 +18,34 @@ import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class TemplateAppearanceManager {
|
||||
public TemplateAppearanceManager(Function<SpriteIdentifier, Sprite> spriteLookup) {
|
||||
Sprite defaultSprite = spriteLookup.apply(DEFAULT_SPRITE_ID);
|
||||
if(defaultSprite == null) throw new IllegalStateException("Couldn't locate " + DEFAULT_SPRITE_ID + " !");
|
||||
defaultAppearance = new TemplateAppearance.SingleSprite(defaultSprite);
|
||||
SpriteIdentifier defaultSpriteId = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, new Identifier("minecraft:block/scaffolding_top"));
|
||||
Sprite defaultSprite = spriteLookup.apply(defaultSpriteId);
|
||||
if(defaultSprite == null) throw new IllegalStateException("Couldn't locate " + defaultSpriteId + " !");
|
||||
|
||||
MaterialFinder finder = TemplatesClient.getFabricRenderer().materialFinder();
|
||||
|
||||
for(BlendMode blend : BlendMode.values()) {
|
||||
blockMaterials.put(blend, finder.clear().disableDiffuse(false).ambientOcclusion(TriState.FALSE).blendMode(blend).find());
|
||||
}
|
||||
|
||||
this.defaultAppearance = new SingleSpriteAppearance(defaultSprite, blockMaterials.get(BlendMode.CUTOUT));
|
||||
}
|
||||
|
||||
private static final SpriteIdentifier DEFAULT_SPRITE_ID = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, new Identifier("minecraft:block/scaffolding_top"));
|
||||
private final TemplateAppearance defaultAppearance;
|
||||
|
||||
//Mutable, append-only cache:
|
||||
private final ConcurrentHashMap<BlockState, TemplateAppearance> appearanceCache = new ConcurrentHashMap<>();
|
||||
|
||||
//Immutable contents:
|
||||
private final EnumMap<BlendMode, RenderMaterial> blockMaterials = new EnumMap<>(BlendMode.class);
|
||||
|
||||
public TemplateAppearance getDefaultAppearance() {
|
||||
return defaultAppearance;
|
||||
}
|
||||
@ -63,20 +80,25 @@ public class TemplateAppearanceManager {
|
||||
//Just for space-usage purposes, we store the particle in sprites[6] instead of using another field.
|
||||
sprites[6] = model.getParticleSprite();
|
||||
|
||||
//Fill out any missing values in the sprites array
|
||||
//Fill out any missing values in the sprites array. Failure to pick textures shouldn't lead to NPEs later on.
|
||||
for(int i = 0; i < sprites.length; i++) {
|
||||
if(sprites[i] == null) sprites[i] = defaultAppearance.getParticleSprite();
|
||||
}
|
||||
|
||||
return new ComputedApperance(sprites, hasColorMask);
|
||||
return new ComputedApperance(sprites, hasColorMask, blockMaterials.get(BlendMode.fromRenderLayer(RenderLayers.getBlockLayer(state))));
|
||||
}
|
||||
|
||||
private static record ComputedApperance(@NotNull Sprite[] sprites, byte hasColorMask) implements TemplateAppearance {
|
||||
private static record ComputedApperance(@NotNull Sprite[] sprites, byte hasColorMask, RenderMaterial mat) implements TemplateAppearance {
|
||||
@Override
|
||||
public @NotNull Sprite getParticleSprite() {
|
||||
return sprites[6];
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RenderMaterial getRenderMaterial() {
|
||||
return mat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sprite getSprite(Direction dir) {
|
||||
return sprites[dir.ordinal()];
|
||||
@ -87,4 +109,26 @@ public class TemplateAppearanceManager {
|
||||
return (hasColorMask & (1 << dir.ordinal())) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static record SingleSpriteAppearance(@NotNull Sprite defaultSprite, RenderMaterial mat) implements TemplateAppearance {
|
||||
@Override
|
||||
public @NotNull Sprite getParticleSprite() {
|
||||
return defaultSprite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RenderMaterial getRenderMaterial() {
|
||||
return mat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sprite getSprite(Direction dir) {
|
||||
return defaultSprite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasColor(Direction dir) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user