Jump to content

Rendering block outlines of hidden blocks.


Jontom Xire

Recommended Posts

One of the X-Ray mods renders an outline of certain blocks, even when they are hidden. I want to be able to do the same, but restricted by range.

 

I have been searching the reverse engineered documentation, but still have next to no idea how to achieve this. My best guess so far is to subscribe to the RenderLevelStageEvent event and then iterate through all blocks within range, test if they need to be outlined/highlighted, and then....stuff them into the OutlineBufferSource to be rendered some how?

 

I am not asking for code (although that would be nice) but just a few hints of the basic process.

 

Many thanks.

Link to comment
Share on other sites

6 hours ago, Jontom Xire said:

I have been searching the reverse engineered documentation, but still have next to no idea how to achieve this. My best guess so far is to subscribe to the RenderLevelStageEvent event and then iterate through all blocks within range, test if they need to be outlined/highlighted, and then....stuff them into the OutlineBufferSource to be rendered some how?

More or less. It would be better if you could store all the blocks you want to outline once so that you can just loop through that list. You may also want to take a look at the GameRenderer to see how block outlining is done when the player hovers over it and just modify the depth test.

Link to comment
Share on other sites

Thanks.

 

Where do I find the source code for the GameRenderer, or do you just mean look at the APIs available?

RenderLevelStageEvent gives me a LevelRenderer which has a renderLineBox() function. I am going to have a go with that but am not sure if the line box will be rendered in front even though the vertex positions are behind other blocks.

 

Link to comment
Share on other sites

Here is my code. It is late, I am tired, I have worked hard to get something sensible to compile in the face of significantly incomplete documentation, and it doesn't work. I would be so very very grateful if someone could help me work out why this isn't working.


    @SubscribeEvent
    public static void onViewBlocks(RenderLevelStageEvent event)
    {
        Minecraft  minecraft = Minecraft.getInstance();
        Player     player    = (Player)(minecraft.player);
        if (RenderLevelStageEvent.Stage.AFTER_SOLID_BLOCKS == event.getStage())
        {
            ClientLevel         level           = minecraft.level;
            LevelRenderer       renderer        = event.getLevelRenderer();
            OutlineBufferSource buffer_source   = minecraft.renderBuffers().outlineBufferSource();
            VertexConsumer      vertex_consumer = buffer_source.getBuffer(RenderType.lines());

            // Highlight all blocks within 4 blocks range.
            int                 min_x           = player.getBlockX() - 4;
            int                 max_x           = player.getBlockX() + 4;
            int                 min_y           = player.getBlockY() - 4;
            int                 max_y           = player.getBlockY() + 4;
            int                 min_z           = player.getBlockZ() - 4;
            int                 max_z           = player.getBlockZ() + 4;

            for (int x = min_x; x < max_x; x++)
            {
                for (int y = min_y; y < max_y; y++)
                {
                    for (int z = min_z; z < max_z; z++)
                    {
                         BlockPos block = new BlockPos(x, y, z)
                         Vec3 centre = block.getCenter();

                         if (centre.distanceToSqr(player.getEyePosition()) <= m_range_squared)
                         {
                             int ore = getOre(level.getBlockState(block).getBlock());  // Check that the block is an ore we want to highlight.

                             if (-1 < ore) {

                                         // If I put debug in here, it successfully reports the block as to be highlighted.

                                         renderer.renderLineBox(vertex_consumer,
                                                                (centre.x - 0.5),
                                                                (centre.y - 0.5),
                                                                (centre.z - 0.5),
                                                                (centre.x + 0.5),
                                                                (centre.y + 0.5),
                                                                (centre.z + 0.5),
                                                                ORE_COLOURS[ore].r,
                                                                ORE_COLOURS[ore].g,
                                                                ORE_COLOURS[ore].b,
                                                                0.5f);         // Not sure if 0.0 is solid colour or transparent. I'm tired. Forgive me!
                             }
                    }
                }
            }
        }
    }

 

Link to comment
Share on other sites

21 hours ago, Jontom Xire said:

I have worked hard to get something sensible to compile in the face of significantly incomplete documentation, and it doesn't work.

Less incomplete documentation, and more nobody in the community has wanted to document this. Makes sense if you think about how complicated it is.

21 hours ago, Jontom Xire said:

I would be so very very grateful if someone could help me work out why this isn't working.

From what I can gather, your position is most likely wrong. You need to subtract the camera location from the position such that it properly appears in the space. As for the transparency, 1 is opaque, 0 is transparent.

Link to comment
Share on other sites

On 2/6/2023 at 3:24 PM, ChampionAsh5357 said:

From what I can gather, your position is most likely wrong. You need to subtract the camera location from the position such that it properly appears in the space.

Like this?

    centre = centre - player.getEyePosition();

Do I not also need to apply camera view angle rotation or anything? I was hoping that the level renderer would apply all necessary scaling, translation, and rotation.

Link to comment
Share on other sites

1 hour ago, Jontom Xire said:

    centre = centre - player.getEyePosition();

No, the camera location. You have access to the camera from the GameRenderer to which you can then grab the position via #getPosition to subtract from the position you want the lines to render.

1 hour ago, Jontom Xire said:

Do I not also need to apply camera view angle rotation or anything? I was hoping that the level renderer would apply all necessary scaling, translation, and rotation.

Those should already be applied for you within the matrix stack. The only thing not transformed in most cases is the translation and that's typically when rendering on screen.

Link to comment
Share on other sites

  • 2 weeks later...

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.

×
×
  • Create New...

Important Information

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