Jump to content

[1.14.2] TESR Fast


Simon_kungen

Recommended Posts

Hi

 

I never really got an actual answer on my last question, so I'm going to ask again:

 

I would like to render a TileEntity Special Render to render fluids in my bucket model:

2019-08-10_20_06_06_2.png.af7d00475cd07c766ffa8671df45947a.png

 

The problem is that I don't know how to "stitch" everything together, and the colour doesn't seem to change either. I realized instead of rendering a whole cuboid I could only render a square only visible from the top, which would reduce the number of vertexes to only four (4). I got something to render in-game, but I couldn't really find any way to have them render as I wanted:

2019-08-14_20_02.59_2.png.8c829cf95d25bc748695217088b99097.png

 

The idea was to make a visual illustration of how full the bucket is. So changing the y value of the square would give the effect of the bucket filling up.

 

bucket_render_example.png.7e69949b9261e7d1772674455dfe1e36.png

 

 

The class with the TESR Fast:

Spoiler

public class TreeTapTileEntityRenderer<T extends TreeTapTileEntity> extends TileEntityRendererFast<T>
{

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

        BlockPos pos = te.getPos();

        net.minecraft.world.IEnviromentBlockReader world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        BlockState state = world.getBlockState(pos);


        if (state.has(BlockProperties.BUCKET))
            if (state.get(BlockProperties.BUCKET) != BucketType.NONE && te.getVolume() > 0) {
                //buffer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());

                render(te,x,y,z,buffer,state, te.getFluidType());


            }


    }

    private void render(T te, double x, double y, double z, BufferBuilder buffer, BlockState state, FluidType type)
    {
        buffer.setTranslation(x,y,z);


        buffer.pos(0,0,0).color(0,0,1,1).endVertex();
        buffer.pos(4,0,0).color(0,0,1,1).endVertex();
        buffer.pos(0,0,4).color(0,0,1,1).endVertex();
        buffer.pos(4,0,4).color(0,0,1,1).endVertex();


    }

 

 

 

Link to comment
Share on other sites

  • 2 weeks later...

Some more details:

I have found other pieces of code where a cuboid was rendered, but I feel like it would be a big waste to render all that when only a tiny part of the "fluid" is visible at any time. A square has four (4) vertices while a cuboid has twelve (12) vertices, so it's pretty obvious which one to chose.

Another problem I'm facing is that even the cluttered mess visible on the second image is still black, which is not at all what I'm expecting out of a blue liquid.

Link to comment
Share on other sites

I think there's two things going on here.

 

First, you're not giving it a texture of what to render.  If you look at the pnc-repressurized example you linked, you'll note the TextureAtlasSprite still = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(f.getStill().toString()); code, along with the inclusion of .tex() in each of the buffer calls.  You'll want to include something quite similar.  (My suspicion is that this it the step that is needed to bring the rest together for you.)

 

The values you are providing to .color() may or may not need to be fiddled with, depending on the colour of your original texture. 

 

Second, the values you are passing to each buffer() call.  "1" is "one block", so the fours used are, well, four blocks.  To keep the fluid in your bucket, you'll want some fractions in there.

 

I wholly agree that you only need to render the 'top' of the fluid.

 

As an aside, this is in the context of 1.12.2 -- but I very much doubt it has changed any for 1.14.2.

Link to comment
Share on other sites

On 8/26/2019 at 9:04 AM, Ommina said:

I think there's two things going on here.

 

First, you're not giving it a texture of what to render.  If you look at the pnc-repressurized example you linked, you'll note the TextureAtlasSprite still = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(f.getStill().toString()); code, along with the inclusion of .tex() in each of the buffer calls.  You'll want to include something quite similar.  (My suspicion is that this it the step that is needed to bring the rest together for you.)

 

The values you are providing to .color() may or may not need to be fiddled with, depending on the colour of your original texture. 

 

Second, the values you are passing to each buffer() call.  "1" is "one block", so the fours used are, well, four blocks.  To keep the fluid in your bucket, you'll want some fractions in there.

 

I wholly agree that you only need to render the 'top' of the fluid.

 

As an aside, this is in the context of 1.12.2 -- but I very much doubt it has changed any for 1.14.2.

 

Alright, I added this to the code, and you can see the result that happened:

 

TextureAtlasSprite sprite = Minecraft.getInstance().getTextureMap().getAtlasSprite("minecraft:water_still");
float u1 = sprite.getMinU(), v1 = sprite.getMinV(), u2 = sprite.getMaxU(), v2 = sprite.getMaxV();

buffer.pos(0,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(4,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(0,0,4).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(4,0,4).color(1,1,1,1).tex(u1, v2).endVertex();

 

Spoiler

treetap_test3.gif

 

 

Link to comment
Share on other sites

When you see stuff rendering all over the place like that, the values bring provided to the .pos() function need to be prodded.

 

4 is too large.  Also, pay attention to the order.  It counts.

 

As an aside, when testing the renderer, start with just one instance of the TE in your test world.  It's a lot easier to see the effects of a change when you can be confident that you're not seeing overlap from nearby tiles. 

Link to comment
Share on other sites

12 hours ago, Ommina said:

When you see stuff rendering all over the place like that, the values bring provided to the .pos() function need to be prodded.

 

4 is too large.  Also, pay attention to the order.  It counts.

 

As an aside, when testing the renderer, start with just one instance of the TE in your test world.  It's a lot easier to see the effects of a change when you can be confident that you're not seeing overlap from nearby tiles. 

Umm... ok, so I changed the 4 to 0.1:

buffer.pos(0,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(0,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(0.1,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(0.1,0,0).color(1,1,1,1).tex(u1, v2).endVertex();

 

But I can't seem to get them to all stick together, I tried a bunch of combinations but there are about 64 different combinations. What order were you thinking? None of the combinations I tried gave any hints on what order they should be in.

Link to comment
Share on other sites

Hm.  Well, you want a horizontal plane, so I'd try something to the effect of:

 

buffer.pos(0.06, 0.5, 0.06).color(1,1,1,1).tex(u1, v1).endVertex();
buffer.pos(0.06, 0.5, 0.93).color(1,1,1,1).tex(u2, v1).endVertex();
buffer.pos(0.93, 0.5, 0.93).color(1,1,1,1).tex(u2, v2).endVertex();
buffer.pos(0.93, 0.5, 0.06).color(1,1,1,1).tex(u1, v2).endVertex();

 

and see if it explodes.

Link to comment
Share on other sites

11 minutes ago, Ommina said:

Hm.  Well, you want a horizontal plane, so I'd try something to the effect of:

 


buffer.pos(0.06, 0.5, 0.06).color(1,1,1,1).tex(u1, v1).endVertex();
buffer.pos(0.06, 0.5, 0.93).color(1,1,1,1).tex(u2, v1).endVertex();
buffer.pos(0.93, 0.5, 0.93).color(1,1,1,1).tex(u2, v2).endVertex();
buffer.pos(0.93, 0.5, 0.06).color(1,1,1,1).tex(u1, v2).endVertex();

 

and see if it explodes.

2019-08-28_10_20_04.thumb.png.1945649d5e20b553141fe095f41bcd81.png

Link to comment
Share on other sites

It feels like there should be a "stitch" function or something I've missed. Something I discovered just now is that the server crashes when I attach the renderer:

ClientRegistry.bindTileEntitySpecialRenderer(TreeTapTileEntity.class, new TreeTapTileEntityRenderer());

 

java.lang.RuntimeException: Attempted to load class net/minecraft/client/renderer/tileentity/TileEntityRenderer for invalid dist DEDICATED_SERVER

Link to comment
Share on other sites

15 minutes ago, diesieben07 said:

Read the documentation on bindTileEntitySpecialRenderer as to when it must be called.

"In order to register a TESR, call ClientRegistry#bindTileEntitySpecialRenderer passing the tile entity class to be renderer with this TER and the instance of the TER to use to render all TEs of this class."

 

Pretty sure that's everything I'm doing:

 

Spoiler

public IntercraftCore()
{

  FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientSetup);
  
}

public void onClientSetup(final FMLClientSetupEvent event)
{
    ClientRegistry.bindTileEntitySpecialRenderer(TreeTapTileEntity.class, new TreeTapTileEntityRenderer());
}

 

 

 

Link to comment
Share on other sites

7 hours ago, Ommina said:

As for the rendering explosion, post the updated code and I'll give it a go locally.  I've got a block to port from 1.12 that has pretty much identical rendering, so I'll work on that and see where it leads.

I have everything on Github, here is where the TileEntity and renderer is.

Link to comment
Share on other sites

  • 2 months later...

(I'm the author of the code in PneumaticCraft: Repressurized).

 

I think where you're going wrong here is order of quad definitions.  It looks like you're trying to render the top face of the block, right?  (And skipping the others because they aren't visible in your block).  So, looking at my code for EnumFacing.UP, the vertex order goes:

  • minX, maxZ
  • maxX, maxZ
  • maxX, minZ
  • minX, minZ

... which is not the order you're using.  The vertex order is vitally important, and should wind clockwise if you're looking at the face from the outside (e.g. for the UP face, when you're facing downward).  Get the order wrong and the quad will look screwy.  The same applies to the UV coordinates; they also have to wind in the same way.

 

Finally, you probably do need to light the quad; the PNC:R code shows you how (with the .lightmap() method).

Edited by desht
Link to comment
Share on other sites

49 minutes ago, desht said:

(I'm the author of the code in PneumaticCraft: Repressurized).

 

I think where you're going wrong here is order of quad definitions.  It looks like you're trying to render the top face of the block, right?  (And skipping the others because they aren't visible in your block).  So, looking at my code for EnumFacing.UP, the vertex order goes:

  • minX, maxZ
  • maxX, maxZ
  • maxX, minZ
  • minX, minZ

... which is not the order you're using.  The vertex order is vitally important, and should wind clockwise if you're looking at the face from the outside (e.g. for the UP face, when you're facing downward).  Get the order wrong and the quad will look screwy.  The same applies to the UV coordinates; they also have to wind in the same way.

 

Finally, you probably do need to light the quad; the PNC:R code shows you how (with the .lightmap() method).

Ok, I changed the order of them now to this:

TextureAtlasSprite sprite = Minecraft.getInstance().getTextureMap().getAtlasSprite("minecraft:water_still");
float u1 = sprite.getMinU(), v1 = sprite.getMinV(), u2 = sprite.getMaxU(), v2 = sprite.getMaxV();


buffer.pos(0.06, 0.5, 0.93).color(1,1,1,te.fluidType.getAlpha()).tex(u1, v2).endVertex();
buffer.pos(0.93, 0.5, 0.93).color(1,1,1,te.fluidType.getAlpha()).tex(u2, v2).endVertex();
buffer.pos(0.93, 0.5, 0.06).color(1,1,1,te.fluidType.getAlpha()).tex(u2, v1).endVertex();
buffer.pos(0.06, 0.5, 0.06).color(1,1,1,te.fluidType.getAlpha()).tex(u1, v1).endVertex();

 

Not sure if this is the right order or if the other part in your code is important. The thing I do not understand about your code is the shouldRender function here:

...
if (tankRenderInfo.shouldRender(EnumFacing.UP)) { // <-- This part.
            int upCombined = getWorld().getCombinedLight(te.getPos().up(), 0);
            int upLMa = upCombined >> 16 & 65535;
            int upLMb = upCombined & 65535;
            buffer.pos(bounds.minX, bounds.maxY, bounds.maxZ).color(1.0f, 1.0f, 1.0f, FLUID_ALPHA).tex(u1, v2).lightmap(upLMa, upLMb).endVertex();
            buffer.pos(bounds.maxX, bounds.maxY, bounds.maxZ).color(1.0f, 1.0f, 1.0f, FLUID_ALPHA).tex(u2, v2).lightmap(upLMa, upLMb).endVertex();
            buffer.pos(bounds.maxX, bounds.maxY, bounds.minZ).color(1.0f, 1.0f, 1.0f, FLUID_ALPHA).tex(u2, v1).lightmap(upLMa, upLMb).endVertex();
            buffer.pos(bounds.minX, bounds.maxY, bounds.minZ).color(1.0f, 1.0f, 1.0f, FLUID_ALPHA).tex(u1, v1).lightmap(upLMa, upLMb).endVertex();
        }
...

 

The EnumFacing.UP is most likely the one I need as you mentioned, but I have no idea in what context. In your code, you use a class getTanksToRender with a function including a BitSet object, which I do not know is used for.

Link to comment
Share on other sites

Ok, turns out the lightmap is pretty important:

2019-11-04_20_24_46.thumb.png.9c00b9a9542062caf8e990acf1a3b4e8.png

 

TextureAtlasSprite sprite = Minecraft.getInstance().getTextureMap().getAtlasSprite("minecraft:block/water_still");
float u1 = sprite.getMinU(), v1 = sprite.getMinV(), u2 = sprite.getMaxU(), v2 = sprite.getMaxV();

int upCombined = getWorld().getCombinedLight(te.getPos().up(), 0);
int upLMa = upCombined >> 16 & 65535;
int upLMb = upCombined & 65535;

float xMin = 0.06f,xMax = 0.93f,yLev = 0.125f,zMin = 0.06f,zMax = 0.93f;

buffer.pos(xMin, yLev, zMax).color(1,1,1,te.fluidType.getAlpha()).tex(u1, v2).lightmap(upLMa, upLMb).endVertex();
buffer.pos(xMax, yLev, zMax).color(1,1,1,te.fluidType.getAlpha()).tex(u2, v2).lightmap(upLMa, upLMb).endVertex();
buffer.pos(xMax, yLev, zMin).color(1,1,1,te.fluidType.getAlpha()).tex(u2, v1).lightmap(upLMa, upLMb).endVertex();
buffer.pos(xMin, yLev, zMin).color(1,1,1,te.fluidType.getAlpha()).tex(u1, v1).lightmap(upLMa, upLMb).endVertex();

 

Link to comment
Share on other sites

16 hours ago, Simon_kungen said:

The EnumFacing.UP is most likely the one I need as you mentioned, but I have no idea in what context. In your code, you use a class getTanksToRender with a function including a BitSet object, which I do not know is used for

The TankRenderInfo class just tells the rendering code where the tanks are in the model and which faces of the fluid AABB to render.  That bitset is just a compact way of storing which of the 6 faces need to be rendered; the FastFluidTESR class is abstract and implemented by the renderers for various tile entities, each of which have differing rendering requirements (e.g. some only need to render the top face of the fluid, some need to render the sides too since the block model has transparent sides, and some have multiple tanks to render, like the Refinery with both an input and output tank).  You don't really need that extra code if you're only ever planning to render the top face of the fluid.

  • Thanks 1
Link to comment
Share on other sites

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.