Search in sources :

Example 1 with BlockRenderView

use of net.minecraft.world.BlockRenderView in project Primeval by devs-immortal.

the class PrimevalFluids method setupFluidRendering.

/*
     * Fluid rendering setup from Spectrum,
     * Made by DaFaqs, credit to him for this
     * method
     */
@Environment(EnvType.CLIENT)
private static void setupFluidRendering(final Fluid still, final Fluid flowing, final Identifier textureFluidId, final int color) {
    final Identifier stillSpriteId = new Identifier(textureFluidId.getNamespace(), "block/" + textureFluidId.getPath());
    final Identifier flowingSpriteId = new Identifier(textureFluidId.getNamespace(), "block/" + textureFluidId.getPath() + "_flow");
    // If they're not already present, add the sprites to the block atlas
    ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE).register((atlasTexture, registry) -> {
        registry.register(stillSpriteId);
        registry.register(flowingSpriteId);
    });
    final Identifier fluidId = Registry.FLUID.getId(still);
    final Identifier listenerId = new Identifier(fluidId.getNamespace(), fluidId.getPath() + "_reload_listener");
    final Sprite[] fluidSprites = { null, null };
    ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() {

        /**
         * Get the sprites from the block atlas when resources are reloaded
         */
        @Override
        public void reload(ResourceManager manager) {
            final Function<Identifier, Sprite> atlas = MinecraftClient.getInstance().getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE);
            fluidSprites[0] = atlas.apply(stillSpriteId);
            fluidSprites[1] = atlas.apply(flowingSpriteId);
        }

        @Override
        public Identifier getFabricId() {
            return listenerId;
        }
    });
    // The FluidRenderer gets the sprites and color from a FluidRenderHandler during rendering
    final FluidRenderHandler renderHandler = new FluidRenderHandler() {

        @Override
        public Sprite[] getFluidSprites(BlockRenderView view, BlockPos pos, FluidState state) {
            return fluidSprites;
        }

        @Override
        public int getFluidColor(BlockRenderView view, BlockPos pos, FluidState state) {
            return color;
        }
    };
    FluidRenderHandlerRegistry.INSTANCE.register(still, renderHandler);
// FluidRenderHandlerRegistry.INSTANCE.register(flowing, renderHandler); // Temp removed because of flowing shenanigans
}
Also used : SimpleSynchronousResourceReloadListener(net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener) Function(java.util.function.Function) Identifier(net.minecraft.util.Identifier) BlockRenderView(net.minecraft.world.BlockRenderView) Sprite(net.minecraft.client.texture.Sprite) BlockPos(net.minecraft.util.math.BlockPos) ResourceManager(net.minecraft.resource.ResourceManager) FluidRenderHandler(net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler) FluidState(net.minecraft.fluid.FluidState) Environment(net.fabricmc.api.Environment)

Example 2 with BlockRenderView

use of net.minecraft.world.BlockRenderView in project canvas by vram-guild.

the class AoCalculator method gatherFace.

/**
 * Computes smoothed brightness and Ao shading for four corners of a block face.
 * Outer block face is what you normally see and what you get get when second
 * parameter is true. Inner is light *within* the block and usually darker. It
 * is blended with the outer face for inset surfaces, but is also used directly
 * in vanilla logic for some blocks that aren't full opaque cubes. Except for
 * parameterization, the logic itself is practically identical to vanilla.
 */
private AoFaceData gatherFace(final int lightFace, boolean isOnBlockFace) {
    final int faceDataIndex = isOnBlockFace ? lightFace : lightFace + 6;
    final int mask = 1 << faceDataIndex;
    final AoFaceData fd = faceData[faceDataIndex];
    if ((completionFlags & mask) == 0) {
        completionFlags |= mask;
        fd.resetCalc();
        final BlockRenderView world = blockInfo.blockView;
        final BlockPos pos = blockInfo.blockPos;
        final BlockPos.Mutable centerPos = lightPos;
        final BlockPos.Mutable searchPos = this.searchPos;
        // all following offsets, which avoids anisotropy in smooth lighting.
        if (isOnBlockFace) {
            BlockPosHelper.fastFaceOffset(centerPos, pos, lightFace);
            if (world.getBlockState(centerPos).isFullOpaque(world, centerPos)) {
                centerPos.set(pos);
            }
        } else {
            centerPos.set(pos);
        }
        fd.center = brightnessFunc.applyAsInt(centerPos);
        final int aoCenter = Math.round(aoFunc.apply(centerPos) * 255);
        final AoFace aoFace = AoFace.get(lightFace);
        // vanilla was further offsetting these in the direction of the light face
        // but it was actually mis-sampling and causing visible artifacts in certain situation
        // PERF: use clearness cache in chunk info
        fastFaceOffset(searchPos, centerPos, aoFace.neighbors[BOTTOM]);
        final boolean bottomClear = !world.getBlockState(searchPos).isFullOpaque(world, searchPos);
        fd.bottom = bottomClear ? brightnessFunc.applyAsInt(searchPos) : OPAQUE;
        final int aoBottom = Math.round(aoFunc.apply(searchPos) * 255);
        fastFaceOffset(searchPos, centerPos, aoFace.neighbors[TOP]);
        final boolean topClear = !world.getBlockState(searchPos).isFullOpaque(world, searchPos);
        fd.top = topClear ? brightnessFunc.applyAsInt(searchPos) : OPAQUE;
        final int aoTop = Math.round(aoFunc.apply(searchPos) * 255);
        fastFaceOffset(searchPos, centerPos, aoFace.neighbors[LEFT]);
        final boolean leftClear = !world.getBlockState(searchPos).isFullOpaque(world, searchPos);
        fd.left = leftClear ? brightnessFunc.applyAsInt(searchPos) : OPAQUE;
        final int aoLeft = Math.round(aoFunc.apply(searchPos) * 255);
        fastFaceOffset(searchPos, centerPos, aoFace.neighbors[RIGHT]);
        final boolean rightClear = !world.getBlockState(searchPos).isFullOpaque(world, searchPos);
        fd.right = rightClear ? brightnessFunc.applyAsInt(searchPos) : OPAQUE;
        final int aoRight = Math.round(aoFunc.apply(searchPos) * 255);
        if (!(leftClear || bottomClear)) {
            // both not clear
            fd.aoBottomLeft = (Math.min(aoLeft, aoBottom) + aoBottom + aoLeft + 1 + aoCenter) >> 2;
            fd.bottomLeft = OPAQUE;
        } else {
            // at least one clear
            fastFaceOffset(searchPos, fastFaceOffset(searchPos, centerPos, aoFace.neighbors[BOTTOM]), aoFace.neighbors[LEFT]);
            final boolean cornerClear = !world.getBlockState(searchPos).isFullOpaque(world, searchPos);
            fd.bottomLeft = cornerClear ? brightnessFunc.applyAsInt(searchPos) : OPAQUE;
            // bitwise divide by four, rounding up
            fd.aoBottomLeft = (Math.round(aoFunc.apply(searchPos) * 255) + aoBottom + aoCenter + aoLeft + 1) >> 2;
        }
        if (!(rightClear || bottomClear)) {
            // both not clear
            fd.aoBottomRight = (Math.min(aoRight, aoBottom) + aoBottom + aoRight + 1 + aoCenter) >> 2;
            fd.bottomRight = OPAQUE;
        } else {
            // at least one clear
            fastFaceOffset(searchPos, fastFaceOffset(searchPos, centerPos, aoFace.neighbors[BOTTOM]), aoFace.neighbors[RIGHT]);
            final boolean cornerClear = !world.getBlockState(searchPos).isFullOpaque(world, searchPos);
            fd.bottomRight = cornerClear ? brightnessFunc.applyAsInt(searchPos) : OPAQUE;
            fd.aoBottomRight = (Math.round(aoFunc.apply(searchPos) * 255) + aoBottom + aoCenter + aoRight + 1) >> 2;
        }
        if (!(leftClear || topClear)) {
            // both not clear
            fd.aoTopLeft = (Math.min(aoLeft, aoTop) + aoTop + aoLeft + 1 + aoCenter) >> 2;
            fd.topLeft = OPAQUE;
        } else {
            // at least one clear
            fastFaceOffset(searchPos, fastFaceOffset(searchPos, centerPos, aoFace.neighbors[TOP]), aoFace.neighbors[LEFT]);
            final boolean cornerClear = !world.getBlockState(searchPos).isFullOpaque(world, searchPos);
            fd.topLeft = cornerClear ? brightnessFunc.applyAsInt(searchPos) : OPAQUE;
            fd.aoTopLeft = (Math.round(aoFunc.apply(searchPos) * 255) + aoTop + aoCenter + aoLeft + 1) >> 2;
        }
        if (!(rightClear || topClear)) {
            // both not clear
            fd.aoTopRight = (Math.min(aoRight, aoTop) + aoTop + aoRight + 1 + aoCenter) >> 2;
            fd.topRight = OPAQUE;
        } else {
            // at least one clear
            fastFaceOffset(searchPos, fastFaceOffset(searchPos, centerPos, aoFace.neighbors[TOP]), aoFace.neighbors[RIGHT]);
            final boolean cornerClear = !world.getBlockState(searchPos).isFullOpaque(world, searchPos);
            fd.topRight = cornerClear ? brightnessFunc.applyAsInt(searchPos) : OPAQUE;
            fd.aoTopRight = (Math.round(aoFunc.apply(searchPos) * 255) + aoTop + aoCenter + aoRight + 1) >> 2;
        }
    }
    return fd;
}
Also used : BlockRenderView(net.minecraft.world.BlockRenderView) BlockPos(net.minecraft.util.math.BlockPos)

Example 3 with BlockRenderView

use of net.minecraft.world.BlockRenderView in project Indium by comp500.

the class AoCalculator method computeFace.

/**
 * Computes smoothed brightness and Ao shading for four corners of a block face.
 * Outer block face is what you normally see and what you get get when second
 * parameter is true. Inner is light *within* the block and usually darker.
 * It is blended with the outer face for inset surfaces, but is also used directly
 * in vanilla logic for some blocks that aren't full opaque cubes.
 * Except for parameterization, the logic itself is practically identical to vanilla.
 */
private AoFaceData computeFace(Direction lightFace, boolean isOnBlockFace, boolean shade) {
    final int faceDataIndex = isOnBlockFace ? lightFace.getId() : lightFace.getId() + 6;
    final int mask = 1 << faceDataIndex;
    final AoFaceData result = faceData[faceDataIndex];
    if ((completionFlags & mask) == 0) {
        completionFlags |= mask;
        final BlockRenderView world = blockInfo.blockView;
        final BlockPos pos = blockInfo.blockPos;
        final BlockPos.Mutable lightPos = this.lightPos;
        final BlockPos.Mutable searchPos = this.searchPos;
        lightPos.set(isOnBlockFace ? pos.offset(lightFace) : pos);
        AoFace aoFace = AoFace.get(lightFace);
        searchPos.set(lightPos).move(aoFace.neighbors[0]);
        final int light0 = brightnessFunc.applyAsInt(searchPos);
        final float ao0 = aoFunc.apply(searchPos);
        searchPos.set(lightPos).move(aoFace.neighbors[1]);
        final int light1 = brightnessFunc.applyAsInt(searchPos);
        final float ao1 = aoFunc.apply(searchPos);
        searchPos.set(lightPos).move(aoFace.neighbors[2]);
        final int light2 = brightnessFunc.applyAsInt(searchPos);
        final float ao2 = aoFunc.apply(searchPos);
        searchPos.set(lightPos).move(aoFace.neighbors[3]);
        final int light3 = brightnessFunc.applyAsInt(searchPos);
        final float ao3 = aoFunc.apply(searchPos);
        // vanilla was further offsetting these in the direction of the light face
        // but it was actually mis-sampling and causing visible artifacts in certain situation
        // .setOffset(lightFace);
        searchPos.set(lightPos).move(aoFace.neighbors[0]);
        if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET)
            searchPos.move(lightFace);
        final boolean isClear0 = world.getBlockState(searchPos).getOpacity(world, searchPos) == 0;
        // .setOffset(lightFace);
        searchPos.set(lightPos).move(aoFace.neighbors[1]);
        if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET)
            searchPos.move(lightFace);
        final boolean isClear1 = world.getBlockState(searchPos).getOpacity(world, searchPos) == 0;
        // .setOffset(lightFace);
        searchPos.set(lightPos).move(aoFace.neighbors[2]);
        if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET)
            searchPos.move(lightFace);
        final boolean isClear2 = world.getBlockState(searchPos).getOpacity(world, searchPos) == 0;
        // .setOffset(lightFace);
        searchPos.set(lightPos).move(aoFace.neighbors[3]);
        if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET)
            searchPos.move(lightFace);
        final boolean isClear3 = world.getBlockState(searchPos).getOpacity(world, searchPos) == 0;
        // c = corner - values at corners of face
        int cLight0, cLight1, cLight2, cLight3;
        float cAo0, cAo1, cAo2, cAo3;
        // then we use values from the outwardly diagonal corner. (outwardly = position is one more away from light face)
        if (!isClear2 && !isClear0) {
            cAo0 = ao0;
            cLight0 = light0;
        } else {
            searchPos.set(lightPos).move(aoFace.neighbors[0]).move(aoFace.neighbors[2]);
            cAo0 = aoFunc.apply(searchPos);
            cLight0 = brightnessFunc.applyAsInt(searchPos);
        }
        if (!isClear3 && !isClear0) {
            cAo1 = ao0;
            cLight1 = light0;
        } else {
            searchPos.set(lightPos).move(aoFace.neighbors[0]).move(aoFace.neighbors[3]);
            cAo1 = aoFunc.apply(searchPos);
            cLight1 = brightnessFunc.applyAsInt(searchPos);
        }
        if (!isClear2 && !isClear1) {
            cAo2 = ao1;
            cLight2 = light1;
        } else {
            searchPos.set(lightPos).move(aoFace.neighbors[1]).move(aoFace.neighbors[2]);
            cAo2 = aoFunc.apply(searchPos);
            cLight2 = brightnessFunc.applyAsInt(searchPos);
        }
        if (!isClear3 && !isClear1) {
            cAo3 = ao1;
            cLight3 = light1;
        } else {
            searchPos.set(lightPos).move(aoFace.neighbors[1]).move(aoFace.neighbors[3]);
            cAo3 = aoFunc.apply(searchPos);
            cLight3 = brightnessFunc.applyAsInt(searchPos);
        }
        // If on block face or neighbor isn't occluding, "center" will be neighbor brightness
        // Doesn't use light pos because logic not based solely on this block's geometry
        int lightCenter;
        searchPos.set(pos).move(lightFace);
        if (isOnBlockFace || !world.getBlockState(searchPos).isOpaqueFullCube(world, searchPos)) {
            lightCenter = brightnessFunc.applyAsInt(searchPos);
        } else {
            lightCenter = brightnessFunc.applyAsInt(pos);
        }
        float aoCenter = aoFunc.apply(isOnBlockFace ? lightPos : pos);
        float worldBrightness = world.getBrightness(lightFace, shade);
        result.a0 = ((ao3 + ao0 + cAo1 + aoCenter) * 0.25F) * worldBrightness;
        result.a1 = ((ao2 + ao0 + cAo0 + aoCenter) * 0.25F) * worldBrightness;
        result.a2 = ((ao2 + ao1 + cAo2 + aoCenter) * 0.25F) * worldBrightness;
        result.a3 = ((ao3 + ao1 + cAo3 + aoCenter) * 0.25F) * worldBrightness;
        result.l0(meanBrightness(light3, light0, cLight1, lightCenter));
        result.l1(meanBrightness(light2, light0, cLight0, lightCenter));
        result.l2(meanBrightness(light2, light1, cLight2, lightCenter));
        result.l3(meanBrightness(light3, light1, cLight3, lightCenter));
    }
    return result;
}
Also used : BlockRenderView(net.minecraft.world.BlockRenderView) BlockPos(net.minecraft.util.math.BlockPos)

Example 4 with BlockRenderView

use of net.minecraft.world.BlockRenderView in project Paradise-Lost by devs-immortal.

the class FluidRenderSetup method setupFluidRendering.

public static void setupFluidRendering(final Fluid still, final Fluid flowing, final Identifier textureFluidId, final int color) {
    final Identifier stillSpriteId = new Identifier(textureFluidId.getNamespace(), "block/" + textureFluidId.getPath() + "_still");
    final Identifier flowingSpriteId = new Identifier(textureFluidId.getNamespace(), "block/" + textureFluidId.getPath() + "_flow");
    // If they're not already present, add the sprites to the block atlas
    ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE).register((atlasTexture, registry) -> {
        registry.register(stillSpriteId);
        registry.register(flowingSpriteId);
    });
    final Identifier fluidId = Registry.FLUID.getId(still);
    final Identifier listenerId = new Identifier(fluidId.getNamespace(), fluidId.getPath() + "_reload_listener");
    final Sprite[] fluidSprites = { null, null };
    ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() {

        @Override
        public Identifier getFabricId() {
            return listenerId;
        }

        /**
         * Get the sprites from the block atlas when resources are reloaded
         */
        @Override
        public void apply(ResourceManager resourceManager) {
            final Function<Identifier, Sprite> atlas = MinecraftClient.getInstance().getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE);
            fluidSprites[0] = atlas.apply(stillSpriteId);
            fluidSprites[1] = atlas.apply(flowingSpriteId);
        }
    });
    // The FluidRenderer gets the sprites and color from a FluidRenderHandler during rendering
    final FluidRenderHandler renderHandler = new FluidRenderHandler() {

        @Override
        public Sprite[] getFluidSprites(BlockRenderView view, BlockPos pos, FluidState state) {
            return fluidSprites;
        }

        @Override
        public int getFluidColor(BlockRenderView view, BlockPos pos, FluidState state) {
            return color;
        }
    };
    FluidRenderHandlerRegistry.INSTANCE.register(still, renderHandler);
    FluidRenderHandlerRegistry.INSTANCE.register(flowing, renderHandler);
}
Also used : SimpleSynchronousResourceReloadListener(net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener) Function(java.util.function.Function) Identifier(net.minecraft.util.Identifier) BlockRenderView(net.minecraft.world.BlockRenderView) Sprite(net.minecraft.client.texture.Sprite) BlockPos(net.minecraft.util.math.BlockPos) ResourceManager(net.minecraft.resource.ResourceManager) FluidRenderHandler(net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler) FluidState(net.minecraft.fluid.FluidState)

Example 5 with BlockRenderView

use of net.minecraft.world.BlockRenderView in project Paradise-Lost by devs-immortal.

the class FluidRenderSetup method setupDenseAercloudRenderingBecauseItJustNeedsToBeASpecialSnowflakeWithOnlyAStillState.

public static void setupDenseAercloudRenderingBecauseItJustNeedsToBeASpecialSnowflakeWithOnlyAStillState(final Fluid still, final Identifier textureFluidId) {
    final Identifier stillSpriteId = new Identifier(textureFluidId.getNamespace(), "block/" + textureFluidId.getPath() + "_still");
    final Identifier flowingSpriteId = new Identifier(textureFluidId.getNamespace(), "block/" + textureFluidId.getPath() + "_flow");
    // If they're not already present, add the sprites to the block atlas
    ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE).register((atlasTexture, registry) -> {
        registry.register(stillSpriteId);
        registry.register(flowingSpriteId);
    });
    final Identifier fluidId = Registry.FLUID.getId(still);
    final Identifier listenerId = new Identifier(fluidId.getNamespace(), fluidId.getPath() + "_reload_listener");
    final Sprite[] fluidSprites = { null, null };
    ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() {

        @Override
        public Identifier getFabricId() {
            return listenerId;
        }

        /**
         * Get the sprites from the block atlas when resources are reloaded
         */
        @Override
        public void apply(ResourceManager resourceManager) {
            final Function<Identifier, Sprite> atlas = MinecraftClient.getInstance().getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE);
            fluidSprites[0] = atlas.apply(stillSpriteId);
            fluidSprites[1] = atlas.apply(flowingSpriteId);
        }
    });
    // The FluidRenderer gets the sprites and color from a FluidRenderHandler during rendering
    final FluidRenderHandler renderHandler = new FluidRenderHandler() {

        @Override
        public Sprite[] getFluidSprites(BlockRenderView view, BlockPos pos, FluidState state) {
            return fluidSprites;
        }

        @Override
        public int getFluidColor(BlockRenderView view, BlockPos pos, FluidState state) {
            return 0xFFFFFF;
        }
    };
    FluidRenderHandlerRegistry.INSTANCE.register(still, renderHandler);
}
Also used : SimpleSynchronousResourceReloadListener(net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener) Function(java.util.function.Function) Identifier(net.minecraft.util.Identifier) BlockRenderView(net.minecraft.world.BlockRenderView) Sprite(net.minecraft.client.texture.Sprite) BlockPos(net.minecraft.util.math.BlockPos) ResourceManager(net.minecraft.resource.ResourceManager) FluidRenderHandler(net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler) FluidState(net.minecraft.fluid.FluidState)

Aggregations

BlockPos (net.minecraft.util.math.BlockPos)5 BlockRenderView (net.minecraft.world.BlockRenderView)5 Function (java.util.function.Function)3 FluidRenderHandler (net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler)3 SimpleSynchronousResourceReloadListener (net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener)3 Sprite (net.minecraft.client.texture.Sprite)3 FluidState (net.minecraft.fluid.FluidState)3 ResourceManager (net.minecraft.resource.ResourceManager)3 Identifier (net.minecraft.util.Identifier)3 Environment (net.fabricmc.api.Environment)1