Posted August 17, 20196 yr 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: 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: 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. 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(); }
August 25, 20196 yr Author 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.
August 26, 20196 yr 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.
August 27, 20196 yr Author 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
August 27, 20196 yr 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.
August 28, 20196 yr Author 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.
August 28, 20196 yr 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.
August 28, 20196 yr Author 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.
August 28, 20196 yr Author 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
August 28, 20196 yr Author 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()); }
August 28, 20196 yr 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.
August 29, 20196 yr Author 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.
November 4, 20195 yr Author So yeah, still not an answer to this, I'm not even close to having this work. What I finished doing though is the network message to change the values of the TileEntity for the client, so the renderer is what still remains. My code is pretty much the same and the idea too.
November 4, 20195 yr (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 November 4, 20195 yr by desht
November 4, 20195 yr Author 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.
November 4, 20195 yr Author Ok, turns out the lightmap is pretty important: 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();
November 5, 20195 yr 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.
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.