Compat with Canvas emissive shaders, fixes

This commit is contained in:
paulevsGitch 2021-08-01 14:05:41 +03:00
parent bcc3b076c2
commit b05f5a728f
15 changed files with 210 additions and 6 deletions

View file

@ -1,12 +1,14 @@
package ru.bclib.api; package ru.bclib.api;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.loader.api.FabricLoader;
import ru.bclib.integration.ModIntegration; import ru.bclib.integration.ModIntegration;
import java.util.List; import java.util.List;
public class ModIntegrationAPI { public class ModIntegrationAPI {
private static final List<ModIntegration> INTEGRATIONS = Lists.newArrayList(); private static final List<ModIntegration> INTEGRATIONS = Lists.newArrayList();
private static final boolean HAS_CANVAS = FabricLoader.getInstance().isModLoaded("canvas");
/** /**
* Registers mod integration * Registers mod integration
@ -38,4 +40,8 @@ public class ModIntegrationAPI {
} }
}); });
} }
public static boolean hasCanvas() {
return HAS_CANVAS;
}
} }

View file

@ -12,7 +12,6 @@ public class BCLibClient implements ClientModInitializer {
ModIntegrationAPI.registerAll(); ModIntegrationAPI.registerAll();
BaseBlockEntityRenders.register(); BaseBlockEntityRenders.register();
DataExchangeAPI.prepareClientside(); DataExchangeAPI.prepareClientside();
PostInitAPI.postInit(true); PostInitAPI.postInit(true);
} }
} }

View file

@ -0,0 +1,23 @@
package ru.bclib.client.models;
import com.google.common.collect.Sets;
import net.minecraft.resources.ResourceLocation;
import java.util.Set;
public class CustomModelData {
private static final Set<ResourceLocation> TRANSPARENT_EMISSION = Sets.newConcurrentHashSet();
public static void clear() {
TRANSPARENT_EMISSION.clear();
}
public static void addTransparent(ResourceLocation blockID) {
TRANSPARENT_EMISSION.add(blockID);
}
public static boolean isTransparentEmissive(ResourceLocation rawLocation) {
String name = rawLocation.getPath().replace("materialmaps/block/", "").replace(".json", "");
return TRANSPARENT_EMISSION.contains(new ResourceLocation(rawLocation.getNamespace(), name));
}
}

View file

@ -0,0 +1,32 @@
package ru.bclib.client.render;
import com.google.common.collect.Sets;
import net.minecraft.resources.ResourceLocation;
import java.util.Set;
public class EmissiveTextureInfo {
private static final Set<ResourceLocation> EMISSIVE_TEXTURES = Sets.newHashSet();
private static final Set<ResourceLocation> EMISSIVE_BLOCKS = Sets.newHashSet();
public static void clear() {
EMISSIVE_TEXTURES.clear();
EMISSIVE_BLOCKS.clear();
}
public static void addTexture(ResourceLocation texture) {
EMISSIVE_TEXTURES.add(texture);
}
public static void addBlock(ResourceLocation blockID) {
EMISSIVE_BLOCKS.add(blockID);
}
public static boolean isEmissiveTexture(ResourceLocation texture) {
return EMISSIVE_TEXTURES.contains(texture);
}
public static boolean isEmissiveBlock(ResourceLocation blockID) {
return EMISSIVE_BLOCKS.contains(blockID);
}
}

View file

@ -2,10 +2,13 @@ package ru.bclib.mixin.client;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.renderer.block.BlockModelShaper; import net.minecraft.client.renderer.block.BlockModelShaper;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.block.model.multipart.MultiPart; import net.minecraft.client.renderer.block.model.multipart.MultiPart;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
@ -14,6 +17,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -22,9 +26,13 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.At.Shift;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.bclib.api.ModIntegrationAPI;
import ru.bclib.client.render.EmissiveTextureInfo;
import ru.bclib.interfaces.BlockModelProvider; import ru.bclib.interfaces.BlockModelProvider;
import ru.bclib.interfaces.ItemModelProvider; import ru.bclib.interfaces.ItemModelProvider;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -68,13 +76,15 @@ public abstract class ModelBakeryMixin {
if (defaultModel instanceof MultiPart) { if (defaultModel instanceof MultiPart) {
states.forEach(blockState -> { states.forEach(blockState -> {
ResourceLocation stateID = BlockModelShaper.stateToModelLocation(blockID, blockState); ResourceLocation stateID = BlockModelShaper.stateToModelLocation(blockID, blockState);
topLevel.put(stateID, defaultModel);
cache.put(stateID, defaultModel); cache.put(stateID, defaultModel);
}); });
} }
else { else {
states.forEach(blockState -> { states.forEach(blockState -> {
ResourceLocation stateID = BlockModelShaper.stateToModelLocation(blockID, blockState); ResourceLocation stateID = BlockModelShaper.stateToModelLocation(blockID, blockState);
UnbakedModel model = provider.getModelVariant(stateID, blockState, cache); UnbakedModel model = stateID.equals(defaultStateID) ? defaultModel : provider.getModelVariant(stateID, blockState, cache);
topLevel.put(stateID, model);
cache.put(stateID, model); cache.put(stateID, model);
}); });
} }
@ -85,8 +95,8 @@ public abstract class ModelBakeryMixin {
if (!resourceManager.hasResource(storageID)) { if (!resourceManager.hasResource(storageID)) {
ResourceLocation itemID = new ModelResourceLocation(blockID.getNamespace(), blockID.getPath(), "inventory"); ResourceLocation itemID = new ModelResourceLocation(blockID.getNamespace(), blockID.getPath(), "inventory");
BlockModel model = provider.getItemModel(itemID); BlockModel model = provider.getItemModel(itemID);
cache.put(itemID, model);
topLevel.put(itemID, model); topLevel.put(itemID, model);
cache.put(itemID, model);
} }
} }
}); });
@ -98,8 +108,8 @@ public abstract class ModelBakeryMixin {
ResourceLocation itemID = new ModelResourceLocation(registryID.getNamespace(), registryID.getPath(), "inventory"); ResourceLocation itemID = new ModelResourceLocation(registryID.getNamespace(), registryID.getPath(), "inventory");
ItemModelProvider provider = (ItemModelProvider) item; ItemModelProvider provider = (ItemModelProvider) item;
BlockModel model = provider.getItemModel(registryID); BlockModel model = provider.getItemModel(registryID);
cache.put(itemID, model);
topLevel.put(itemID, model); topLevel.put(itemID, model);
cache.put(itemID, model);
} }
}); });
@ -110,4 +120,44 @@ public abstract class ModelBakeryMixin {
topLevelModels.putAll(topLevel); topLevelModels.putAll(topLevel);
unbakedCache.putAll(cache); unbakedCache.putAll(cache);
} }
@Inject(method = "<init>*", at = @At("TAIL"))
private void bclib_findEmissiveModels(ResourceManager resourceManager, BlockColors blockColors, ProfilerFiller profiler, int mipmap, CallbackInfo info) {
if (!ModIntegrationAPI.hasCanvas()) {
return;
}
Map<ResourceLocation, UnbakedModel> cacheCopy = new HashMap<>(unbakedCache);
Set<Pair<String, String>> strings = Sets.newConcurrentHashSet();
Registry.BLOCK.keySet().forEach(blockID -> {
Block block = Registry.BLOCK.get(blockID);
ImmutableList<BlockState> states = block.getStateDefinition().getPossibleStates();
boolean addBlock = false;
for (BlockState state: states) {
ResourceLocation stateID = BlockModelShaper.stateToModelLocation(blockID, state);
UnbakedModel model = cacheCopy.get(stateID);
if (model == null) {
continue;
}
Collection<Material> materials = model.getMaterials(cacheCopy::get, strings);
if (materials == null) {
continue;
}
for (Material material: materials) {
if (EmissiveTextureInfo.isEmissiveTexture(material.texture())) {
addBlock = true;
break;
}
}
if (addBlock) {
break;
}
}
if (addBlock) {
EmissiveTextureInfo.addBlock(blockID);
}
});
}
} }

View file

@ -0,0 +1,59 @@
package ru.bclib.mixin.client;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.FallbackResourceManager;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.SimpleReloadableResourceManager;
import net.minecraft.server.packs.resources.SimpleResource;
import org.spongepowered.asm.mixin.Final;
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.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.bclib.BCLib;
import ru.bclib.api.ModIntegrationAPI;
import ru.bclib.client.render.EmissiveTextureInfo;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
@Mixin(SimpleReloadableResourceManager.class)
public class SimpleReloadableResourceManagerMixin {
@Final
@Shadow
private Map<String, FallbackResourceManager> namespacedPacks;
private Resource bclib_alphaEmissionMaterial;
@Inject(method = "getResource", at = @At("HEAD"), cancellable = true)
private void bclib_getResource(ResourceLocation resourceLocation, CallbackInfoReturnable<Resource> info) throws IOException {
if (!ModIntegrationAPI.hasCanvas()) {
return;
}
if (!resourceLocation.getPath().startsWith("materialmaps")) {
return;
}
if (!resourceLocation.getPath().contains("/block/")) {
return;
}
String name = resourceLocation.getPath().replace("materialmaps/block/", "").replace(".json", "");
ResourceLocation blockID = new ResourceLocation(resourceLocation.getNamespace(), name);
if (!EmissiveTextureInfo.isEmissiveBlock(blockID)) {
return;
}
ResourceManager resourceManager = this.namespacedPacks.get(resourceLocation.getNamespace());
if (resourceManager != null) {
resourceLocation = BCLib.makeID("materialmaps/block/alpha_emission.json");
info.setReturnValue(resourceManager.getResource(resourceLocation));
}
}
}

View file

@ -14,6 +14,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.bclib.BCLib; import ru.bclib.BCLib;
import ru.bclib.client.render.EmissiveTextureInfo;
import java.io.IOException; import java.io.IOException;
@ -26,6 +27,9 @@ public class TextureAtlasMixin {
private void bclib_onAtlasInit(ResourceLocation resourceLocation, CallbackInfo info) { private void bclib_onAtlasInit(ResourceLocation resourceLocation, CallbackInfo info) {
boolean hasOptifine = FabricLoader.getInstance().isModLoaded("optifabric"); boolean hasOptifine = FabricLoader.getInstance().isModLoaded("optifabric");
bclib_modifyAtlas = !hasOptifine && resourceLocation.toString().equals("minecraft:textures/atlas/blocks.png"); bclib_modifyAtlas = !hasOptifine && resourceLocation.toString().equals("minecraft:textures/atlas/blocks.png");
if (bclib_modifyAtlas) {
EmissiveTextureInfo.clear();
}
} }
@Inject(method = "load(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$Info;IIIII)Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;", at = @At("HEAD"), cancellable = true) @Inject(method = "load(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$Info;IIIII)Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;", at = @At("HEAD"), cancellable = true)
@ -91,6 +95,7 @@ public class TextureAtlasMixin {
posY, posY,
sprite sprite
); );
EmissiveTextureInfo.addTexture(location);
info.setReturnValue(result); info.setReturnValue(result);
} }
} }

View file

@ -0,0 +1,3 @@
{
"defaultMaterial": "bclib:alpha_emission"
}

View file

@ -0,0 +1,8 @@
{
"layers": [
{
"vertexSource": "canvas:shaders/material/default.vert",
"fragmentSource": "bclib:shaders/material/alpha_emission.frag"
}
]
}

View file

@ -0,0 +1,14 @@
#include frex:shaders/api/fragment.glsl
#include frex:shaders/lib/math.glsl
// Value near 254
bool isEmissive(float alpha) {
return 0.9960 < alpha && alpha < 0.9962;
}
void frx_startFragment(inout frx_FragmentData fragData) {
if (isEmissive(fragData.spriteColor.a)) {
fragData.emissivity = 1.0;
fragData.spriteColor.a = 1.0;
}
}

View file

@ -11,6 +11,7 @@ uniform vec4 FogColor;
in float vertexDistance; in float vertexDistance;
in vec4 vertexColor; in vec4 vertexColor;
in vec2 texCoord0; in vec2 texCoord0;
in vec4 normal;
out vec4 fragColor; out vec4 fragColor;

View file

@ -9,10 +9,11 @@ uniform float FogEnd;
uniform vec4 FogColor; uniform vec4 FogColor;
in float vertexDistance; in float vertexDistance;
in vec4 vertexColor;
in vec4 lightMapColor; in vec4 lightMapColor;
in vec4 overlayColor; in vec4 overlayColor;
in vec4 vertexColor;
in vec2 texCoord0; in vec2 texCoord0;
in vec4 normal;
out vec4 fragColor; out vec4 fragColor;

View file

@ -11,7 +11,8 @@ uniform vec4 FogColor;
in float vertexDistance; in float vertexDistance;
in vec4 vertexColor; in vec4 vertexColor;
in vec2 texCoord0; in vec2 texCoord0;
in vec4 overlayColor; in vec2 texCoord1;
in vec4 normal;
out vec4 fragColor; out vec4 fragColor;

View file

@ -11,6 +11,7 @@ uniform vec4 FogColor;
in float vertexDistance; in float vertexDistance;
in vec4 vertexColor; in vec4 vertexColor;
in vec2 texCoord0; in vec2 texCoord0;
in vec4 normal;
out vec4 fragColor; out vec4 fragColor;

View file

@ -4,6 +4,7 @@
"package": "ru.bclib.mixin.client", "package": "ru.bclib.mixin.client",
"compatibilityLevel": "JAVA_16", "compatibilityLevel": "JAVA_16",
"client": [ "client": [
"SimpleReloadableResourceManagerMixin",
"EnchantingTableBlockMixin", "EnchantingTableBlockMixin",
"BackgroundRendererMixin", "BackgroundRendererMixin",
"TextureAtlasMixin", "TextureAtlasMixin",