Search in sources :

Example 1 with ChunkRebuildHelper

use of grondag.canvas.chunk.ChunkRebuildHelper in project canvas by vram-guild.

the class MixinChunkRenderer method onRebuildChunk.

@Inject(method = "rebuildChunk", at = @At("HEAD"), cancellable = true, require = 1)
private void onRebuildChunk(final float x, final float y, final float z, final ChunkRenderTask chunkRenderTask, final CallbackInfo ci) {
    final TerrainRenderContext renderContext = TerrainRenderContext.POOL.get();
    final ChunkRebuildHelper help = renderContext.chunkRebuildHelper;
    help.clear();
    final ChunkRenderData chunkRenderData = ChunkRenderDataStore.claim();
    final ChunkRenderDataExt chunkDataExt = (ChunkRenderDataExt) chunkRenderData;
    final BlockPos.Mutable origin = this.origin;
    final World world = this.world;
    if (world != null) {
        chunkRenderTask.getLock().lock();
        try {
            if (chunkRenderTask.getStage() != ChunkRenderTask.Stage.COMPILING) {
                return;
            }
            chunkRenderTask.setRenderData(chunkRenderData);
        } finally {
            chunkRenderTask.getLock().unlock();
        }
        // PERF: avoid allocation
        final ChunkOcclusionGraphBuilder visibilityData = new ChunkOcclusionGraphBuilder();
        // PERF: avoid allocation
        final HashSet<BlockEntity> blockEntities = Sets.newHashSet();
        final ChunkRendererRegion vanillaRegion = chunkRenderTask.takeRegion();
        if (vanillaRegion != null) {
            final FastRenderRegion renderRegion = ((ChunkRendererRegionExt) vanillaRegion).canvas_fastRegion();
            ++chunkUpdateCount;
            help.prepareCollectors(origin.getX(), origin.getY(), origin.getZ());
            renderContext.setChunkTask(chunkRenderTask);
            /**
             * Capture the block layer result flags so our renderer can update them when more
             * than one layer is rendered for a single model. This is also where we signal the
             * renderer to prepare for a new chunk using the data we've accumulated up to this point.
             */
            renderContext.prepare((ChunkRenderer) (Object) this, origin);
            // NB: We don't use this and it probably isn't needed but leaving just in case - cost is low
            BlockModelRenderer.enableBrightnessCache();
            final BlockRenderManager blockRenderManager = MinecraftClient.getInstance().getBlockRenderManager();
            final BlockPos.Mutable searchPos = help.searchPos;
            final int xMin = origin.getX();
            final int yMin = origin.getY();
            final int zMin = origin.getZ();
            final int xMax = xMin + 16;
            final int yMax = yMin + 16;
            final int zMax = zMin + 16;
            for (int xPos = xMin; xPos < xMax; xPos++) {
                for (int yPos = yMin; yPos < yMax; yPos++) {
                    for (int zPos = zMin; zPos < zMax; zPos++) {
                        final BlockState blockState = renderRegion.getBlockState(xPos, yPos, zPos);
                        searchPos.set(xPos, yPos, zPos);
                        if (blockState.isFullOpaque(renderRegion, searchPos)) {
                            visibilityData.markClosed(searchPos);
                        }
                        if (blockState.getBlock().hasBlockEntity()) {
                            final BlockEntity blockEntity = renderRegion.getBlockEntity(searchPos, WorldChunk.CreationType.CHECK);
                            if (blockEntity != null) {
                                final BlockEntityRenderer<BlockEntity> blockEntityRenderer = BlockEntityRenderDispatcher.INSTANCE.get(blockEntity);
                                if (blockEntityRenderer != null) {
                                    // Fixes MC-112730 - no reason to render both globally and in chunk
                                    if (blockEntityRenderer.method_3563(blockEntity)) {
                                        // global renderer - like beacons
                                        blockEntities.add(blockEntity);
                                    } else {
                                        // chunk-local renderer
                                        chunkRenderData.addBlockEntity(blockEntity);
                                    }
                                }
                            }
                        }
                        BlockRenderLayer renderLayer;
                        // UGLY: we are relying on knowledge that fluid state is directly derived from block state, which
                        // may not be true in future versions and may break.  However, is significantly faster to re-use block
                        // state here vs. retrieving it again.
                        final FluidState fluidState = blockState.getFluidState();
                        if (!fluidState.isEmpty()) {
                            renderLayer = fluidState.getRenderLayer();
                            // TODO: apply appropriate shader props for fluids
                            final FluidBufferBuilder fluidBuilder = help.fluidBuilder.prepare(help.getCollector(renderLayer).get(Canvas.MATERIAL_STANDARD, ShaderProps.waterProps()), searchPos, renderLayer);
                            blockRenderManager.tesselateFluid(searchPos, renderRegion, fluidBuilder, fluidState);
                        }
                        if (blockState.getRenderType() == BlockRenderType.MODEL) {
                            renderContext.tesselateBlock(blockState, searchPos);
                        }
                    }
                }
            }
            if (!help.solidCollector.isEmpty()) {
                chunkRenderData.markBufferInitialized(BlockRenderLayer.SOLID);
                chunkDataExt.canvas_setNonEmpty(BlockRenderLayer.SOLID);
                final UploadableChunk.Solid abandoned = uploadSolid.getAndSet(help.solidCollector.packUploadSolid());
                if (abandoned != null) {
                    abandoned.cancel();
                }
            }
            if (!help.translucentCollector.isEmpty()) {
                final VertexCollectorList vcl = help.translucentCollector;
                chunkRenderData.markBufferInitialized(BlockRenderLayer.TRANSLUCENT);
                chunkDataExt.canvas_setNonEmpty(BlockRenderLayer.TRANSLUCENT);
                vcl.setViewCoordinates(x, y, z);
                chunkDataExt.canvas_collectorState(vcl.getCollectorState(null));
                final UploadableChunk.Translucent abandoned = uploadTranslucent.getAndSet(vcl.packUploadTranslucent());
                if (abandoned != null) {
                    abandoned.cancel();
                }
            }
            /**
             * Release all references. Probably not necessary but would be $#%! to debug if it is.
             */
            renderContext.release();
            BlockModelRenderer.disableBrightnessCache();
        }
        chunkRenderData.setOcclusionGraph(visibilityData.build());
        lock.lock();
        try {
            help.tileEntitiesToAdd.addAll(blockEntities);
            help.tileEntitiesToRemove.addAll(this.blockEntities);
            help.tileEntitiesToAdd.removeAll(this.blockEntities);
            help.tileEntitiesToRemove.removeAll(blockEntities);
            this.blockEntities.clear();
            this.blockEntities.addAll(blockEntities);
            renderer.updateBlockEntities(help.tileEntitiesToRemove, help.tileEntitiesToAdd);
        } finally {
            lock.unlock();
        }
    }
    ci.cancel();
}
Also used : ChunkRendererRegion(net.minecraft.client.render.chunk.ChunkRendererRegion) ChunkRebuildHelper(grondag.canvas.chunk.ChunkRebuildHelper) ChunkRenderData(net.minecraft.client.render.chunk.ChunkRenderData) FluidBufferBuilder(grondag.canvas.buffer.packing.FluidBufferBuilder) ChunkRenderDataExt(grondag.canvas.chunk.ChunkRenderDataExt) World(net.minecraft.world.World) TerrainRenderContext(grondag.canvas.apiimpl.rendercontext.TerrainRenderContext) ChunkOcclusionGraphBuilder(net.minecraft.client.render.chunk.ChunkOcclusionGraphBuilder) BlockRenderManager(net.minecraft.client.render.block.BlockRenderManager) BlockPos(net.minecraft.util.math.BlockPos) BlockEntity(net.minecraft.block.entity.BlockEntity) BlockState(net.minecraft.block.BlockState) VertexCollectorList(grondag.canvas.buffer.packing.VertexCollectorList) UploadableChunk(grondag.canvas.chunk.UploadableChunk) FastRenderRegion(grondag.canvas.chunk.FastRenderRegion) BlockRenderLayer(net.minecraft.block.BlockRenderLayer) ChunkRendererRegionExt(grondag.canvas.chunk.ChunkRendererRegionExt) FluidState(net.minecraft.fluid.FluidState) Inject(org.spongepowered.asm.mixin.injection.Inject)

Aggregations

TerrainRenderContext (grondag.canvas.apiimpl.rendercontext.TerrainRenderContext)1 FluidBufferBuilder (grondag.canvas.buffer.packing.FluidBufferBuilder)1 VertexCollectorList (grondag.canvas.buffer.packing.VertexCollectorList)1 ChunkRebuildHelper (grondag.canvas.chunk.ChunkRebuildHelper)1 ChunkRenderDataExt (grondag.canvas.chunk.ChunkRenderDataExt)1 ChunkRendererRegionExt (grondag.canvas.chunk.ChunkRendererRegionExt)1 FastRenderRegion (grondag.canvas.chunk.FastRenderRegion)1 UploadableChunk (grondag.canvas.chunk.UploadableChunk)1 BlockRenderLayer (net.minecraft.block.BlockRenderLayer)1 BlockState (net.minecraft.block.BlockState)1 BlockEntity (net.minecraft.block.entity.BlockEntity)1 BlockRenderManager (net.minecraft.client.render.block.BlockRenderManager)1 ChunkOcclusionGraphBuilder (net.minecraft.client.render.chunk.ChunkOcclusionGraphBuilder)1 ChunkRenderData (net.minecraft.client.render.chunk.ChunkRenderData)1 ChunkRendererRegion (net.minecraft.client.render.chunk.ChunkRendererRegion)1 FluidState (net.minecraft.fluid.FluidState)1 BlockPos (net.minecraft.util.math.BlockPos)1 World (net.minecraft.world.World)1 Inject (org.spongepowered.asm.mixin.injection.Inject)1