Enable AO on all blocks except the slopes

This commit is contained in:
quat1024 2023-08-02 01:51:43 -04:00
parent 93e385a856
commit 78e3e82bbe
9 changed files with 73 additions and 27 deletions

View File

@ -74,4 +74,6 @@ Templates's slope blocks use this model, because it's otherwise impossible to ma
3. Create a blockstate json for your block, and point it at the ID you decided for your special model in 1). 3. Create a blockstate json for your block, and point it at the ID you decided for your special model in 1).
* You may use the `x`, `y`, and `uvlock` properties as normal. * You may use the `x`, `y`, and `uvlock` properties as normal.
Ambient occlusion now defaults to "on" (since 2.1.1). If this looks bad on your model, you can reset it with a `.disableAo()` call on your UnbakedModel.
You may create a regular item model, or use ours by calling `TemplatesClient.provider.assignItemModel`, passing the ID of the special model & the items you want to assign it to. (The reason you have to do this instead of simply creating a regular item model and setting its `parent`, is that `JsonUnbakedModel`s can't have non-`JsonUnbakedModel`s as their `parent`, and even a trivial item model with only the `parent` field set counts as a `JsonUnbakedModel`. This isn't a problem for block models because blockstates are a layer of indirection before model loading.) You may create a regular item model, or use ours by calling `TemplatesClient.provider.assignItemModel`, passing the ID of the special model & the items you want to assign it to. (The reason you have to do this instead of simply creating a regular item model and setting its `parent`, is that `JsonUnbakedModel`s can't have non-`JsonUnbakedModel`s as their `parent`, and even a trivial item model with only the `parent` field set counts as a `JsonUnbakedModel`. This isn't a problem for block models because blockstates are a layer of indirection before model loading.)

View File

@ -30,7 +30,7 @@ if(rootProject.file("private.gradle").exists()) { //Publishing details
archivesBaseName = "templates" archivesBaseName = "templates"
group = "io.github.cottonmc" group = "io.github.cottonmc"
version = "2.1.0+1.20.1" version = "2.1.1+1.20.1"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -128,10 +128,10 @@ public class TemplatesClient implements ClientModInitializer {
provider.addTemplateModel(Templates.id("wall_side_tall_special") , new UnbakedJsonRetexturedModel(Templates.id("block/wall_side_tall"))); provider.addTemplateModel(Templates.id("wall_side_tall_special") , new UnbakedJsonRetexturedModel(Templates.id("block/wall_side_tall")));
//mesh models //mesh models
provider.addTemplateModel(Templates.id("slope_special") , new UnbakedMeshRetexturedModel(Templates.id("block/slope_base"), SlopeBaseMesh::makeUpright)); provider.addTemplateModel(Templates.id("slope_special") , new UnbakedMeshRetexturedModel(Templates.id("block/slope_base"), SlopeBaseMesh::makeUpright).disableAo());
provider.addTemplateModel(Templates.id("slope_side_special") , new UnbakedMeshRetexturedModel(Templates.id("block/slope_base"), SlopeBaseMesh::makeSide)); provider.addTemplateModel(Templates.id("slope_side_special") , new UnbakedMeshRetexturedModel(Templates.id("block/slope_base"), SlopeBaseMesh::makeSide).disableAo());
provider.addTemplateModel(Templates.id("tiny_slope_special") , new UnbakedMeshRetexturedModel(Templates.id("block/tiny_slope_base"), SlopeBaseMesh::makeTinyUpright)); provider.addTemplateModel(Templates.id("tiny_slope_special") , new UnbakedMeshRetexturedModel(Templates.id("block/tiny_slope_base"), SlopeBaseMesh::makeTinyUpright).disableAo());
provider.addTemplateModel(Templates.id("tiny_slope_side_special") , new UnbakedMeshRetexturedModel(Templates.id("block/tiny_slope_base"), SlopeBaseMesh::makeTinySide)); provider.addTemplateModel(Templates.id("tiny_slope_side_special") , new UnbakedMeshRetexturedModel(Templates.id("block/tiny_slope_base"), SlopeBaseMesh::makeTinySide).disableAo());
//item only models //item only models
provider.addTemplateModel(Templates.id("button_inventory_special") , new UnbakedAutoRetexturedModel(new Identifier("block/button_inventory"))); provider.addTemplateModel(Templates.id("button_inventory_special") , new UnbakedAutoRetexturedModel(new Identifier("block/button_inventory")));

View File

@ -27,19 +27,26 @@ import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier; import java.util.function.Supplier;
public abstract class RetexturingBakedModel extends ForwardingBakedModel { public abstract class RetexturingBakedModel extends ForwardingBakedModel {
@Deprecated(forRemoval = true) //binary-compat from before there was an AO boolean
public RetexturingBakedModel(BakedModel baseModel, TemplateAppearanceManager tam, ModelBakeSettings settings, BlockState itemModelState) { public RetexturingBakedModel(BakedModel baseModel, TemplateAppearanceManager tam, ModelBakeSettings settings, BlockState itemModelState) {
this(baseModel, tam, settings, itemModelState, true);
}
public RetexturingBakedModel(BakedModel baseModel, TemplateAppearanceManager tam, ModelBakeSettings settings, BlockState itemModelState, boolean ao) {
this.wrapped = baseModel; this.wrapped = baseModel;
this.tam = tam; this.tam = tam;
this.facePermutation = MeshTransformUtil.facePermutation(settings); this.facePermutation = MeshTransformUtil.facePermutation(settings);
this.uvlock = settings.isUvLocked(); this.uvlock = settings.isUvLocked();
this.itemModelState = itemModelState; this.itemModelState = itemModelState;
this.ao = ao;
} }
protected final TemplateAppearanceManager tam; protected final TemplateAppearanceManager tam;
protected final Map<Direction, Direction> facePermutation; //immutable protected final Map<Direction, Direction> facePermutation; //immutable
protected final boolean uvlock; protected final boolean uvlock;
protected final BlockState itemModelState; protected final BlockState itemModelState;
protected final boolean ao;
private static record CacheKey(BlockState state, TemplateAppearance appearance) {} private static record CacheKey(BlockState state, TemplateAppearance appearance) {}
private final ConcurrentMap<CacheKey, Mesh> retexturedMeshes = new ConcurrentHashMap<>(); //mutable, append-only cache private final ConcurrentMap<CacheKey, Mesh> retexturedMeshes = new ConcurrentHashMap<>(); //mutable, append-only cache
@ -132,7 +139,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
@Override @Override
public boolean transform(MutableQuadView quad) { public boolean transform(MutableQuadView quad) {
quad.material(ta.getRenderMaterial()); quad.material(ta.getRenderMaterial(ao));
int tag = quad.tag(); int tag = quad.tag();
if(tag == 0) return true; //Pass the quad through unmodified. if(tag == 0) return true; //Pass the quad through unmodified.

View File

@ -8,8 +8,14 @@ import org.jetbrains.annotations.NotNull;
public interface TemplateAppearance { public interface TemplateAppearance {
@NotNull Sprite getParticleSprite(); //TODO: plug this in (particle mixins don't use it atm) @NotNull Sprite getParticleSprite(); //TODO: plug this in (particle mixins don't use it atm)
@NotNull RenderMaterial getRenderMaterial(); @NotNull RenderMaterial getRenderMaterial(boolean ao);
@NotNull Sprite getSprite(Direction dir); @NotNull Sprite getSprite(Direction dir);
int getBakeFlags(Direction dir); int getBakeFlags(Direction dir);
boolean hasColor(Direction dir); boolean hasColor(Direction dir);
//binary-compat
@Deprecated(forRemoval = true)
default @NotNull RenderMaterial getRenderMaterial() {
return getRenderMaterial(false);
}
} }

View File

@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function; import java.util.function.Function;
@ -34,16 +35,19 @@ public class TemplateAppearanceManager {
public TemplateAppearanceManager(Function<SpriteIdentifier, Sprite> spriteLookup) { public TemplateAppearanceManager(Function<SpriteIdentifier, Sprite> spriteLookup) {
MaterialFinder finder = TemplatesClient.getFabricRenderer().materialFinder(); MaterialFinder finder = TemplatesClient.getFabricRenderer().materialFinder();
for(BlendMode blend : BlendMode.values()) { for(BlendMode blend : BlendMode.values()) {
blockMaterials.put(blend, finder.clear().disableDiffuse(false).ambientOcclusion(TriState.FALSE).blendMode(blend).find()); finder.clear().disableDiffuse(false).blendMode(blend);
materialsWithoutAo.put(blend, finder.ambientOcclusion(TriState.FALSE).find());
materialsWithAo.put(blend, finder.ambientOcclusion(TriState.DEFAULT).find()); //not "true" since that *forces* AO, i just want to *allow* AO
} }
Sprite defaultSprite = spriteLookup.apply(DEFAULT_SPRITE_ID); Sprite defaultSprite = spriteLookup.apply(DEFAULT_SPRITE_ID);
if(defaultSprite == null) throw new IllegalStateException("Couldn't locate " + DEFAULT_SPRITE_ID + " !"); if(defaultSprite == null) throw new IllegalStateException("Couldn't locate " + DEFAULT_SPRITE_ID + " !");
this.defaultAppearance = new SingleSpriteAppearance(defaultSprite, blockMaterials.get(BlendMode.CUTOUT), serialNumber.getAndIncrement()); this.defaultAppearance = new SingleSpriteAppearance(defaultSprite, materialsWithoutAo.get(BlendMode.CUTOUT), serialNumber.getAndIncrement());
Sprite barrier = spriteLookup.apply(BARRIER_SPRITE_ID); Sprite barrier = spriteLookup.apply(BARRIER_SPRITE_ID);
if(barrier == null) barrier = defaultSprite; //eh if(barrier == null) barrier = defaultSprite; //eh
this.barrierItemAppearance = new SingleSpriteAppearance(barrier, blockMaterials.get(BlendMode.CUTOUT), serialNumber.getAndIncrement()); this.barrierItemAppearance = new SingleSpriteAppearance(barrier, materialsWithoutAo.get(BlendMode.CUTOUT), serialNumber.getAndIncrement());
} }
@ApiStatus.Internal //shouldn't have made this public, just maintaining abi compat @ApiStatus.Internal //shouldn't have made this public, just maintaining abi compat
@ -55,7 +59,9 @@ public class TemplateAppearanceManager {
private final ConcurrentHashMap<BlockState, TemplateAppearance> appearanceCache = new ConcurrentHashMap<>(); //Mutable, append-only cache private final ConcurrentHashMap<BlockState, TemplateAppearance> appearanceCache = new ConcurrentHashMap<>(); //Mutable, append-only cache
private final AtomicInteger serialNumber = new AtomicInteger(0); //Mutable private final AtomicInteger serialNumber = new AtomicInteger(0); //Mutable
private final EnumMap<BlendMode, RenderMaterial> blockMaterials = new EnumMap<>(BlendMode.class); //Immutable contents
private final EnumMap<BlendMode, RenderMaterial> materialsWithAo = new EnumMap<>(BlendMode.class);
private final EnumMap<BlendMode, RenderMaterial> materialsWithoutAo = new EnumMap<>(BlendMode.class); //Immutable contents
public TemplateAppearance getDefaultAppearance() { public TemplateAppearance getDefaultAppearance() {
return defaultAppearance; return defaultAppearance;
@ -65,8 +71,9 @@ public class TemplateAppearanceManager {
return appearanceCache.computeIfAbsent(state, this::computeAppearance); return appearanceCache.computeIfAbsent(state, this::computeAppearance);
} }
public RenderMaterial getCachedMaterial(BlockState state) { public RenderMaterial getCachedMaterial(BlockState state, boolean ao) {
return blockMaterials.get(BlendMode.fromRenderLayer(RenderLayers.getBlockLayer(state))); Map<BlendMode, RenderMaterial> m = ao ? materialsWithAo : materialsWithoutAo;
return m.get(BlendMode.fromRenderLayer(RenderLayers.getBlockLayer(state)));
} }
//I'm pretty sure ConcurrentHashMap semantics allow for this function to be called multiple times on the same key, on different threads. //I'm pretty sure ConcurrentHashMap semantics allow for this function to be called multiple times on the same key, on different threads.
@ -152,25 +159,28 @@ public class TemplateAppearanceManager {
sprites, sprites,
bakeFlags, bakeFlags,
hasColorMask, hasColorMask,
getCachedMaterial(state), getCachedMaterial(state, true),
getCachedMaterial(state, false),
serialNumber.getAndIncrement() serialNumber.getAndIncrement()
); );
} }
@SuppressWarnings("ClassCanBeRecord")
private static final class ComputedApperance implements TemplateAppearance { private static final class ComputedApperance implements TemplateAppearance {
private final Sprite @NotNull[] sprites; private final Sprite @NotNull[] sprites;
private final int @NotNull[] bakeFlags; private final int @NotNull[] bakeFlags;
private final byte hasColorMask; private final byte hasColorMask;
private final RenderMaterial mat;
private final int id; private final int id;
private final RenderMaterial matWithAo;
private final RenderMaterial matWithoutAo;
private ComputedApperance(@NotNull Sprite @NotNull[] sprites, int @NotNull[] bakeFlags, byte hasColorMask, RenderMaterial mat, int id) { private ComputedApperance(@NotNull Sprite @NotNull[] sprites, int @NotNull[] bakeFlags, byte hasColorMask, RenderMaterial withAo, RenderMaterial withoutAo, int id) {
this.sprites = sprites; this.sprites = sprites;
this.bakeFlags = bakeFlags; this.bakeFlags = bakeFlags;
this.hasColorMask = hasColorMask; this.hasColorMask = hasColorMask;
this.mat = mat;
this.id = id; this.id = id;
this.matWithAo = withAo;
this.matWithoutAo = withoutAo;
} }
@Override @Override
@ -179,8 +189,8 @@ public class TemplateAppearanceManager {
} }
@Override @Override
public @NotNull RenderMaterial getRenderMaterial() { public @NotNull RenderMaterial getRenderMaterial(boolean ao) {
return mat; return ao ? matWithAo : matWithoutAo;
} }
@Override @Override
@ -213,7 +223,7 @@ public class TemplateAppearanceManager {
@Override @Override
public String toString() { public String toString() {
return "ComputedApperance{sprites=%s, bakeFlags=%s, hasColorMask=%s, mat=%s, id=%d}".formatted(Arrays.toString(sprites), Arrays.toString(bakeFlags), hasColorMask, mat, id); return "ComputedApperance{sprites=%s, bakeFlags=%s, hasColorMask=%s, matWithoutAo=%s, matWithAo=%s, id=%d}".formatted(Arrays.toString(sprites), Arrays.toString(bakeFlags), hasColorMask, matWithoutAo, matWithAo, id);
} }
} }
@ -235,7 +245,7 @@ public class TemplateAppearanceManager {
} }
@Override @Override
public @NotNull RenderMaterial getRenderMaterial() { public @NotNull RenderMaterial getRenderMaterial(boolean ao) {
return mat; return mat;
} }

View File

@ -39,6 +39,12 @@ public class UnbakedAutoRetexturedModel implements UnbakedModel {
protected final Identifier parent; protected final Identifier parent;
protected final BlockState itemModelState; protected final BlockState itemModelState;
protected boolean ao = true;
public UnbakedAutoRetexturedModel disableAo() {
ao = false;
return this;
}
@Override @Override
public Collection<Identifier> getModelDependencies() { public Collection<Identifier> getModelDependencies() {
return Collections.singletonList(parent); return Collections.singletonList(parent);
@ -58,7 +64,8 @@ public class UnbakedAutoRetexturedModel implements UnbakedModel {
baker.bake(parent, modelBakeSettings), baker.bake(parent, modelBakeSettings),
TemplatesClient.provider.getOrCreateTemplateApperanceManager(spriteLookup), TemplatesClient.provider.getOrCreateTemplateApperanceManager(spriteLookup),
modelBakeSettings, modelBakeSettings,
itemModelState itemModelState,
ao
) { ) {
@Override @Override
protected Mesh getBaseMesh(BlockState state) { protected Mesh getBaseMesh(BlockState state) {
@ -70,7 +77,7 @@ public class UnbakedAutoRetexturedModel implements UnbakedModel {
Renderer r = TemplatesClient.getFabricRenderer(); Renderer r = TemplatesClient.getFabricRenderer();
MeshBuilder builder = r.meshBuilder(); MeshBuilder builder = r.meshBuilder();
QuadEmitter emitter = builder.getEmitter(); QuadEmitter emitter = builder.getEmitter();
RenderMaterial mat = tam.getCachedMaterial(state); RenderMaterial mat = tam.getCachedMaterial(state, false);
Random rand = Random.create(42); Random rand = Random.create(42);

View File

@ -42,6 +42,12 @@ public class UnbakedJsonRetexturedModel implements UnbakedModel {
protected final Identifier parent; protected final Identifier parent;
protected final BlockState itemModelState; protected final BlockState itemModelState;
protected boolean ao = true;
public UnbakedJsonRetexturedModel disableAo() {
ao = false;
return this;
}
@Override @Override
public Collection<Identifier> getModelDependencies() { public Collection<Identifier> getModelDependencies() {
return Collections.singletonList(parent); return Collections.singletonList(parent);
@ -69,7 +75,8 @@ public class UnbakedJsonRetexturedModel implements UnbakedModel {
baker.bake(parent, modelBakeSettings), baker.bake(parent, modelBakeSettings),
TemplatesClient.provider.getOrCreateTemplateApperanceManager(spriteLookup), TemplatesClient.provider.getOrCreateTemplateApperanceManager(spriteLookup),
modelBakeSettings, modelBakeSettings,
itemModelState itemModelState,
ao
) { ) {
@Override @Override
protected Mesh getBaseMesh(BlockState state) { protected Mesh getBaseMesh(BlockState state) {
@ -81,7 +88,7 @@ public class UnbakedJsonRetexturedModel implements UnbakedModel {
Renderer r = TemplatesClient.getFabricRenderer(); Renderer r = TemplatesClient.getFabricRenderer();
MeshBuilder builder = r.meshBuilder(); MeshBuilder builder = r.meshBuilder();
QuadEmitter emitter = builder.getEmitter(); QuadEmitter emitter = builder.getEmitter();
RenderMaterial mat = tam.getCachedMaterial(state); RenderMaterial mat = tam.getCachedMaterial(state, false);
Random rand = Random.create(42); Random rand = Random.create(42);

View File

@ -30,6 +30,12 @@ public class UnbakedMeshRetexturedModel implements UnbakedModel {
protected final Identifier parent; protected final Identifier parent;
protected final Function<Function<SpriteIdentifier, Sprite>, Mesh> baseMeshFactory; protected final Function<Function<SpriteIdentifier, Sprite>, Mesh> baseMeshFactory;
protected boolean ao = true;
public UnbakedMeshRetexturedModel disableAo() {
ao = false;
return this;
}
@Override @Override
public Collection<Identifier> getModelDependencies() { public Collection<Identifier> getModelDependencies() {
return Collections.singletonList(parent); return Collections.singletonList(parent);
@ -48,7 +54,8 @@ public class UnbakedMeshRetexturedModel implements UnbakedModel {
baker.bake(parent, modelBakeSettings), baker.bake(parent, modelBakeSettings),
TemplatesClient.provider.getOrCreateTemplateApperanceManager(spriteLookup), TemplatesClient.provider.getOrCreateTemplateApperanceManager(spriteLookup),
modelBakeSettings, modelBakeSettings,
Blocks.AIR.getDefaultState() Blocks.AIR.getDefaultState(),
ao
) { ) {
@Override @Override
protected Mesh getBaseMesh(BlockState state) { protected Mesh getBaseMesh(BlockState state) {