[1.20.1] Accessing certain bones during render break the UV mapping
baileyholl opened this issue ยท 6 comments
Easy to reproduce, simply fetching a bone in any render method will break UV mappings and causes all sorts of whacky behavior.
@Override
public void actuallyRender(PoseStack stack, EnchantingApparatusTile tile, BakedGeoModel model, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
CoreGeoBone frame = model.getBone("frame_all").orElse(null);
super.....
}
Commenting out that line will fix it back to proper UV mappings.
This happens in render recursively, preRender, actually render, and more.
Note: this has a different behavior on which bone you fetch. It seems like the higher up in the heirarchy, the more breaking? Sometimes if I pick a bone that has children, it just simply doesnt render other parts of the model.
You're telling the game to render an ItemStack
Which has the game bind the items atlas to the renderbuffer
You're then not rebinding the entity texture to the renderbuffer, so it's then rendering as if it's using your item's texture
You need to re-bind your buffer afterwards if you're changing it
If it worked in Geckolib3, it was either a coincidence, or a miracle of a combination of bugs that ended up working
This is absolutely how rendering works in mc - if you rebind the buffer, it's gone until you rebind it back
There's definitely more to this than is being shown
getBone
literally just does a loop through a list and checks for string matches
There's absolutely nothing involved in it that would change anything at all related to anything, let alone breaking UVs
Show the rest of your code
Oops sorry, got this one mixed up.
For context, in geckolib 3, we used renderRecursively
to translate the posestack to the bone to render an itemstack at the location.
In geckolib 4, rendering an itemstack in render recursively will break the mappings/model depending on which bone you pick. In actuallyRender
, it just breaks using the itemrenderer at all.
@Override
public void actuallyRender(PoseStack stack, EnchantingApparatusTile tile, BakedGeoModel model, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
double x = tile.getBlockPos().getX();
double y = tile.getBlockPos().getY();
double z = tile.getBlockPos().getZ();
if (tile.renderEntity == null || !ItemStack.matches(tile.renderEntity.getItem(), tile.getStack())) {
tile.renderEntity = new ItemEntity(tile.getLevel(), x, y, z, tile.getStack());
}
stack.pushPose();
ItemStack itemstack = tile.renderEntity.getItem();
Minecraft.getInstance().getItemRenderer().renderStatic(itemstack, ItemDisplayContext.GROUND, packedLight, OverlayTexture.NO_OVERLAY, stack, bufferSource, tile.getLevel(), (int) tile.getBlockPos().asLong());
stack.popPose();
super.actuallyRender(stack, tile, model, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
}
What breaks is different on which bone you use in renderRecursively, but you are right, the bone has nothing to do with this particular error - it was removing the render entirely when I marked it as null for testing ๐
This is an example using render recursively, which worked in geckolib 3. This method is unfortunately the only one that correctly translates items to the exact position of the bone.
public class StarbuncleRenderer extends GeoEntityRenderer<Starbuncle> {
public StarbuncleRenderer(EntityRendererProvider.Context manager) {
super(manager, new StarbuncleModel());
}
@Override
public void renderFinal(PoseStack poseStack, Starbuncle animatable, BakedGeoModel model, MultiBufferSource bufferSource, VertexConsumer buffer, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
super.renderFinal(poseStack, animatable, model, bufferSource, buffer, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
}
@Override
public void renderRecursively(PoseStack stack, Starbuncle animatable, GeoBone bone, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
if (bone.getName().equals("item")) {
stack.pushPose();
RenderUtils.translateToPivotPoint(stack, bone);
stack.translate(0, -0.10, 0);
stack.scale(0.75f, 0.75f, 0.75f);
ItemStack itemstack = animatable.getHeldStack();
if (animatable.dynamicBehavior != null) {
itemstack = animatable.dynamicBehavior.getStackForRender();
}
if(!itemstack.isEmpty()) {
Minecraft.getInstance().getItemRenderer().renderStatic(itemstack, ItemDisplayContext.GROUND, packedLight, OverlayTexture.NO_OVERLAY, stack, bufferSource, animatable.level, (int) animatable.getOnPos().asLong());
}
stack.popPose();
}
if (animatable.getCosmeticItem().getItem() instanceof ICosmeticItem cosmetic && cosmetic.getBone().equals(bone.getName())) {
CosmeticRenderUtil.renderCosmetic(bone, stack, bufferSource, animatable, packedLight);
}
super.renderRecursively(stack, animatable, bone, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
}
@Override
public ResourceLocation getTextureLocation(Starbuncle entity) {
return entity.getTexture(entity);
}
@Override
public RenderType getRenderType(Starbuncle animatable, ResourceLocation texture, @org.jetbrains.annotations.Nullable MultiBufferSource bufferSource, float partialTick) {
return RenderType.entityCutoutNoCull(texture);
}
}
public class StarbuncleModel extends GeoModel<Starbuncle> {
@Override
public void setCustomAnimations(Starbuncle entity, long uniqueID, @Nullable AnimationState customPredicate) {
super.setCustomAnimations(entity, uniqueID, customPredicate);
if (entity.partyCarby)
return;
if (customPredicate == null)
return;
this.getBone("basket").get().setHidden(!entity.isTamed());
CoreGeoBone head = this.getAnimationProcessor().getBone("head");
EntityModelData extraData = (EntityModelData) customPredicate.getExtraData().get(DataTickets.ENTITY_MODEL_DATA);
head.setRotX(extraData.headPitch() * 0.017453292F);
head.setRotY(extraData.netHeadYaw() * 0.017453292F);
}
@Override
public ResourceLocation getModelResource(Starbuncle carbuncle) {
return new ResourceLocation(ArsNouveau.MODID, "geo/starbuncle.geo.json");
}
@Override
public ResourceLocation getTextureResource(Starbuncle carbuncle) {
return carbuncle.getTexture(carbuncle);
}
@Override
public ResourceLocation getAnimationResource(Starbuncle carbuncle) {
return new ResourceLocation(ArsNouveau.MODID, "animations/starbuncle_animations.json");
}
}