Jump to content

[Solved][1.12.2] Rendering issues with dynamic block model


Recommended Posts

Posted (edited)

Hello :)

I'm currently working on the mod that let players make blocks emit light. To achive this I am swaping original block with a custom one that uses texture of the original block. Original block state is stored in tile entity. I'm also using IBakedModel in conjunction with ModelBakeEvent to dynamically generate a model. It's all working fine but I have encountered some lesser rendering issues that I don't know are possible to fix :)

 

1. SOLVED. Transparent blocks like Ice that are directly behind my block are rendering sides (see picture below). This is probably imposible to fix due to BlockBreakable#shouldSideBeRendered implementation. (Opposite case is fine - fixed in my block's shouldSideBeRendered method).

  Reveal hidden contents

 

2. My block is lacking shades (since it's emitting light) and looks "out of place" when next to "normal" blocks, especially when looking from the side . See picture below. 

  Reveal hidden contents

 

3. Rendering gliches when in third person.

  Reveal hidden contents

 

4. SOLVED. I cannot set block particles (like block break particles). I have no access to extendedState in getParticleTexture method in my bakedModel, so I can't get the texture of original block. 

 

The code of my mod is available on GitHub, especially Block and bakedModel.

 

If anyone has an idea how to fix any of above issues I will be really gratefull. Thanks!

Edited by Pyre540
Issue solved
Posted

1. Override doesSideBlockRendering

2. Have ambientOcclusion be true in your model

About Me

  Reveal hidden contents

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted (edited)

Hey, thanks for answer :)

  On 4/12/2019 at 8:58 AM, Cadiboo said:

1. Override doesSideBlockRendering

Expand  

Thanks, that works great :)

    @Override
    public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
        IBlockState neighbourState = world.getBlockState(pos.offset(face));
        Block neighbourBlock = neighbourState.getBlock();
        Block originalBlock = getOriginalBlock(world, pos);

        if ((originalBlock.getBlockLayer() == BlockRenderLayer.TRANSLUCENT || originalBlock.getBlockLayer() == BlockRenderLayer.CUTOUT)
                && ((neighbourBlock == this && originalBlock == getOriginalBlock(world, pos.offset(face))) || originalBlock == neighbourBlock)) {
            return true;
        }
        return super.doesSideBlockRendering(state, world, pos, face);
    }

 

  On 4/12/2019 at 8:58 AM, Cadiboo said:

2. Have ambientOcclusion be true in your model

Expand  

That unfortunately didn't help :/

{
  "parent": "block/cube_all",
  "ambientocclusion": true,
  "textures": {
    "all": "minecraft:blocks/glowstone"
  }
}

 

I also fixed the issue with particle textures (issue 4):

  Reveal hidden contents

 

So 2 down and 2 to go :)

Edited by Pyre540
Posted

Is there a way to "force" Minecraft to render block using BlockModelRenderer#renderModelSmooth method directly instead of BlockModelRenderer#renderModel method?

Posted

Set the game settings smooth lighting to smooth

About Me

  Reveal hidden contents

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted

I'm sorry I should be more specific with my question. I'm trying to do something with issue #2. In BlockModelRenderer#renderModel there is a flag that determines if the block should be rendered "Smooth" or "Flat".

boolean flag = Minecraft.isAmbientOcclusionEnabled() && stateIn.getLightValue(worldIn, posIn) == 0 && modelIn.isAmbientOcclusion(stateIn);


Ambient Occlusion is enabled in the game and in my model. The problem is that my block is emitting light so stateIn.getLightValue(worldIn, posIn) is greater then 0. In my last post I was asking if I could "force" the game to use renderModelSmooth method directly to bypass light value check.


I can achive the effect I want quite easly by doing somthing like that in my block: 

  Reveal hidden contents


But that is obviously bad (at least I think it is) and can probably cause hard to find bugs in the future, so I'm trying to avoid that.


Can I achive this effect in some other way? For example by getting rid of my block's model completly and using TESR/FastTESR to just render "original" block model?

Posted

Ok so I finally got some time to play with FastTESR idea and it ended up pretty well - I achieved the effect I wanted on almost all blocks. The biggest issue with this approach turned out to be transparent blocks. They were really glitchy due to rendering order. So I end up rendering them in the correct order (furthest to nearest) in RenderWorldLastEvent and the rest (solid, cutout...) in FastTESR. At first everything looked very good, but unfortunately I found 2 new issues.


1. Transparent blocks look good during the day, but at night or in another dark environment they are too bright.

  Reveal hidden contents


2. Looking at my block through another transparent block, my block has a different color (has ambient acclusion?). I probably can live with this issue but if someone know how to fix this, it would be great :)

  Reveal hidden contents

 

My last concern is performance, but I don't think I can do something with it in current approach.

 

My FastTESR:

public class FastTESREnlightenedBlock extends FastTESR<TileEntityEnlightenedBlock> {

    private BlockRendererDispatcher blockRenderer;

    @Override
    public void renderTileEntityFast(TileEntityEnlightenedBlock te, double x, double y, double z, float partialTicks, int destroyStage, float partial, BufferBuilder buffer) {

        IBlockState originalBlockState = te.getOriginalBlockState();

        if (originalBlockState.getBlock().getBlockLayer() == BlockRenderLayer.TRANSLUCENT) {
            return;
        }

        if(blockRenderer == null) {
            blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        }

        BlockPos pos = te.getPos();
        World world = te.getWorld();
        IBlockState blockState = world.getBlockState(pos);
        IBakedModel model = blockRenderer.getModelForState(originalBlockState);

        buffer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());

        if (Minecraft.isAmbientOcclusionEnabled()) {
            blockRenderer.getBlockModelRenderer().renderModelSmooth(world, model, blockState, pos, buffer, true, MathHelper.getPositionRandom(pos));
        } else {
            blockRenderer.getBlockModelRenderer().renderModelFlat(world, model, blockState, pos, buffer, true, MathHelper.getPositionRandom(pos));
        }
    }
}

 

RenderWorldLastEvent:

    @SubscribeEvent
    public static void onRenderLastEvent(RenderWorldLastEvent event) {
        EntityPlayerSP player = Minecraft.getMinecraft().player;
        WorldClient world = Minecraft.getMinecraft().world;

        List<TileEntity> loadedTileEntityList = world.loadedTileEntityList;
        List<TileEntityEnlightenedBlock> alphas = loadedTileEntityList.stream()
                .filter(te -> te instanceof TileEntityEnlightenedBlock)
                //.filter(te -> canPlayerSeeTile(world, player, te))
                .map(te -> (TileEntityEnlightenedBlock)te)
                .filter(te -> te.getOriginalBlockState().getBlock().getBlockLayer() == BlockRenderLayer.TRANSLUCENT)
                .collect(Collectors.toList());

        if (alphas.isEmpty()) {
            return;
        }

        final double partialTicks = (double)event.getPartialTicks();
        final double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
        final double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
        final double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;

        for (TileEntityEnlightenedBlock alpha : alphas) {
            alpha.setDistanceToPlayer(alpha.getDistanceSq(playerX, playerY, playerZ));
        }

        alphas.sort(Comparator.comparingDouble(TileEntityEnlightenedBlock::getDistanceToPlayer).reversed());

        for (TileEntityEnlightenedBlock alpha : alphas) {
            BlockPos pos = alpha.getPos();
            final double x = (double)pos.getX() - playerX;
            final double y = (double)pos.getY() - playerY;
            final double z = (double)pos.getZ() - playerZ;

            renderTransparentBlock(world, alpha, pos, x, y, z);
        }
    }

    private static void renderTransparentBlock(WorldClient world, TileEntityEnlightenedBlock alpha, BlockPos pos, double x, double y, double z) {
        GlStateManager.pushMatrix();
        RenderHelper.disableStandardItemLighting();
        if (Minecraft.isAmbientOcclusionEnabled()) {
            GlStateManager.shadeModel(GL11.GL_SMOOTH);
        } else {
            GlStateManager.shadeModel(GL11.GL_FLAT);
        }
        GlStateManager.disableLighting();
        GlStateManager.enableCull();
        GlStateManager.enableBlend();
        GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GlStateManager.disableAlpha();
        GlStateManager.enableDepth();
        GlStateManager.depthMask(false);

        GlStateManager.translate(x - alpha.getPos().getX(), y - alpha.getPos().getY(), z - alpha.getPos().getZ());

        IBlockState originalBlockState = alpha.getOriginalBlockState();
        IBlockState blockState = world.getBlockState(pos);
        BlockRendererDispatcher renderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        IBakedModel model = renderer.getModelForState(originalBlockState);

        Tessellator tessellator = Tessellator.getInstance();
        tessellator.getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
        if (Minecraft.isAmbientOcclusionEnabled()) {
            renderer.getBlockModelRenderer().renderModelSmooth(world, model, blockState, pos, tessellator.getBuffer(), true, MathHelper.getPositionRandom(pos));
        } else {
            renderer.getBlockModelRenderer().renderModelFlat(world, model, blockState, pos, tessellator.getBuffer(), true, MathHelper.getPositionRandom(pos));
        }
        tessellator.draw();

        RenderHelper.enableStandardItemLighting();
        GlStateManager.popMatrix();

        GlStateManager.enableLighting();
        GlStateManager.disableCull();
        GlStateManager.disableBlend();
        GlStateManager.enableAlpha();
        GlStateManager.depthMask(true);
    }

 

Full source code is available on GitHub

Posted

You might want to look at how Blocks are rendered in RenderChunk#rebuildChunk

About Me

  Reveal hidden contents

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted

Hey, thanks for reply.
I looked into that method, but unfortunately I don't think I know what part of code you had in mind and for which issue. Can you elaborate?

Posted

That’s the vanilla code that renders all the blocks for a chunk, translucency works right for it so I was thinking you might want to compare your code to it

About Me

  Reveal hidden contents

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted

I finally solved the issue with block brightness. It turned out to be really easy fix. All I had to do was add two lines of code:

Minecraft.getMinecraft().entityRenderer.enableLightmap();
//Rest of rendering stuff here
Minecraft.getMinecraft().entityRenderer.disableLightmap();

 

I also changed the structure of the code to call the drawing method for the transparent blocks only once. Here's updated code:

    @SubscribeEvent
    public static void onRenderLastEvent(RenderWorldLastEvent event) {
        EntityPlayerSP player = Minecraft.getMinecraft().player;
        WorldClient world = Minecraft.getMinecraft().world;

        List<TileEntity> loadedTileEntityList = world.loadedTileEntityList;
        List<TileEntityEnlightenedBlock> alphas = loadedTileEntityList.stream()
                .filter(te -> te instanceof TileEntityEnlightenedBlock)
                .map(te -> (TileEntityEnlightenedBlock)te)
                .filter(te -> te.getOriginalBlockState().getBlock().getBlockLayer() == BlockRenderLayer.TRANSLUCENT)
                .collect(Collectors.toList());

        if (alphas.isEmpty()) {
            return;
        }

        final double partialTicks = (double)event.getPartialTicks();
        final double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
        final double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
        final double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;

        for (TileEntityEnlightenedBlock alpha : alphas) {
            alpha.setDistanceToPlayer(alpha.getDistanceSq(playerX, playerY, playerZ));
        }
        alphas.sort(Comparator.comparingDouble(TileEntityEnlightenedBlock::getDistanceToPlayer).reversed());

        preRenderTransparentBlocks();

        Tessellator tessellator = Tessellator.getInstance();
        BufferBuilder buffer = tessellator.getBuffer();
        buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);

        for (TileEntityEnlightenedBlock alpha : alphas) {
            BlockPos pos = alpha.getPos();
            final double x = (double)pos.getX() - playerX;
            final double y = (double)pos.getY() - playerY;
            final double z = (double)pos.getZ() - playerZ;

            renderTransparentBlock(world, alpha, pos, x, y, z, buffer);
        }
        buffer.setTranslation(0, 0, 0);
        tessellator.draw();

        postRenderTransparentBlocks();
    }

    private static void preRenderTransparentBlocks() {
        Minecraft.getMinecraft().entityRenderer.enableLightmap();
        GlStateManager.pushMatrix();
        if (Minecraft.isAmbientOcclusionEnabled()) {
            GlStateManager.shadeModel(GL11.GL_SMOOTH);
        } else {
            GlStateManager.shadeModel(GL11.GL_FLAT);
        }
        GlStateManager.disableLighting();
        GlStateManager.enableCull();
        GlStateManager.enableBlend();
        GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GlStateManager.disableAlpha();
        GlStateManager.enableDepth();
        GlStateManager.depthMask(false);
    }

    private static void renderTransparentBlock(WorldClient world, TileEntityEnlightenedBlock alpha, BlockPos pos, double x, double y, double z, BufferBuilder buffer) {

        buffer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());

        IBlockState originalBlockState = alpha.getOriginalBlockState();
        IBlockState blockState = world.getBlockState(pos);
        BlockRendererDispatcher renderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        IBakedModel model = renderer.getModelForState(originalBlockState);

        if (Minecraft.isAmbientOcclusionEnabled()) {
            renderer.getBlockModelRenderer().renderModelSmooth(world, model, blockState, pos, buffer, true, MathHelper.getPositionRandom(pos));
        } else {
            renderer.getBlockModelRenderer().renderModelFlat(world, model, blockState, pos, buffer, true, MathHelper.getPositionRandom(pos));
        }
    }

    private static void postRenderTransparentBlocks() {
        GlStateManager.popMatrix();
        GlStateManager.enableLighting();
        GlStateManager.disableCull();
        GlStateManager.disableBlend();
        GlStateManager.enableAlpha();
        GlStateManager.depthMask(true);
        Minecraft.getMinecraft().entityRenderer.disableLightmap();
    }

 

That being said, I think this topic can be considered solved. The only issue left is the issue with looking at my block through another transparent block, but as I said, this is not a big deal and I can live with that :)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Verified users can now unlock a $100 OFF Temu Coupon Code using the verified promo code [ALF401700]. This Temu $100 OFF code works for both new and existing customers and can be used to redeem up to 50% off your next order. Our exclusive Temu coupon code [ALF401700] delivers a flat $100 OFF on top of existing deals. First-time customers using code ALF401700 can save an extra 100% off select items. Returning users also qualify for an automatic $100 OFF discount just by applying this code at checkout. But wait—there’s more. With our Temu coupon codes for 2025, users can score up to 90% OFF on clearance items. Whether you’re shopping in the USA, Canada, UK, or elsewhere, Temu promo code ALF401700 unlocks extra discounts tailored to your account. Some users are saving 100% on items using this 2025 Temu promo code. 🔥 Temu Coupon Highlights Using Code [ALF401700]: Temu new user code – ALF401700: Save 50% off your first order + $100 OFF. Temu promo for existing customers – ALF401700: Enjoy flat $100 OFF instantly. Global availability: Works in the USA, UK, Canada, Germany, France, Japan, Chile, Colombia, Malaysia, Mexico, South Korea, Philippines, Saudi Arabia, Qatar, Pakistan, and more. Top 2025 Coupon Deal: Get $200 OFF plus 100% bonus discounts using code ALF401700. Top-Ranked Temu Deals for 2025 (Coupon Code: ALF401700): ✅ Temu $100 OFF Memorial Day Sale — Use ALF401700 ✅ Temu First Order Coupon — Use ALF401700 for 50% + $100 OFF ✅ Temu USA Coupon Code — Save $100 instantly with ALF401700 ✅ Temu Japan, Germany, Chile Codes — All support ALF401700 ✅ Temu Reddit Discount – $100 OFF: Valid for both new and old users ✅ Temu Coupon Bundle 2025 — $100 OFF + up to 50% slash ✅ 100% OFF Free Gift Code — Use ALF401700, no invite needed ✅ Temu Sign-Up Bonus Promo — Get a welcome $100 OFF instantly ✅ Free Temu Code for New Users — Use ALF401700, no referral required  Temu Clearance Codes 2025 — Use ALF401700 for 85–100% discounts Why ALF401700 is the Best Temu Code in 2025 Using Temu code ALF401700 is your ticket to massive savings, free shipping, first-order discounts, and stackable coupon bundles. Whether you're browsing electronics, fashion, home goods, or beauty products, this verified Temu discount code offers real savings—up to 90% OFF + $100 OFF on qualified orders. 💡 Pro Tip: Apply ALF401700 during checkout in the Temu app or website to activate your instant $100 discount, even if you’re not a new user. Temu $100 OFF Code by Country (All Use ALF401700): 🇺🇸 Temu USA – ALF401700 🇯🇵 Temu Japan – ALF401700 🇲🇽 Temu Mexico – ALF401700 🇨🇱 Temu Chile – ALF401700 🇨🇴 Temu Colombia – ALF401700 🇲🇾 Temu Malaysia – ALF401700 🇵🇭 Temu Philippines – ALF401700 🇰🇷 Temu Korea – ALF401700 🇵🇰 Temu Pakistan – ALF401700 🇫🇮 Temu Finland – ALF401700 🇸🇦 Temu Saudi Arabia – ALF401700 🇶🇦 Temu Qatar – ALF401700 🇫🇷 Temu France – ALF401700 🇩🇪 Temu Germany – ALF401700 🇮🇱 Temu Israel – ALF401700 Temu Coupon Code [ALF401700] Summary for SEO: Temu $100 OFF Code  Temu First Order Discount Code 2025  Temu Verified Promo Code ALF401700  Temu 50% OFF + $100 Bonus  Temu 100% OFF Code 2025  Temu App Promo ALF401700  Temu Working Discount Code 2025 
    • Hey there, nothing to do with the code, I am just suggesting you use Intelij IDEA. Trust me, it is the best.
    • Hey there, nothing to do with the code, I am just suggesting you use Intelij IDEA. Trust me, it is the best.
    • You can check the config of Geckolib and Mowzie's Mobs - maybe there is a way to disable some render features
    • You can use the .requires() function  the server also has a permission level of 4, which is the highest permission level.
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.