Search in sources :

Example 1 with ExtendedBlockView

use of net.minecraft.world.ExtendedBlockView in project fabric by FabricMC.

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) {
    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 ExtendedBlockView 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).setOffset(aoFace.neighbors[0]);
        final int light0 = brightnessFunc.applyAsInt(searchPos);
        final float ao0 = aoFunc.apply(searchPos);
        searchPos.set(lightPos).setOffset(aoFace.neighbors[1]);
        final int light1 = brightnessFunc.applyAsInt(searchPos);
        final float ao1 = aoFunc.apply(searchPos);
        searchPos.set(lightPos).setOffset(aoFace.neighbors[2]);
        final int light2 = brightnessFunc.applyAsInt(searchPos);
        final float ao2 = aoFunc.apply(searchPos);
        searchPos.set(lightPos).setOffset(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).setOffset(aoFace.neighbors[0]);
        if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET)
            searchPos.setOffset(lightFace);
        final boolean isClear0 = world.getBlockState(searchPos).getLightSubtracted(world, searchPos) == 0;
        // .setOffset(lightFace);
        searchPos.set(lightPos).setOffset(aoFace.neighbors[1]);
        if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET)
            searchPos.setOffset(lightFace);
        final boolean isClear1 = world.getBlockState(searchPos).getLightSubtracted(world, searchPos) == 0;
        // .setOffset(lightFace);
        searchPos.set(lightPos).setOffset(aoFace.neighbors[2]);
        if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET)
            searchPos.setOffset(lightFace);
        final boolean isClear2 = world.getBlockState(searchPos).getLightSubtracted(world, searchPos) == 0;
        // .setOffset(lightFace);
        searchPos.set(lightPos).setOffset(aoFace.neighbors[3]);
        if (!Indigo.FIX_SMOOTH_LIGHTING_OFFSET)
            searchPos.setOffset(lightFace);
        final boolean isClear3 = world.getBlockState(searchPos).getLightSubtracted(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).setOffset(aoFace.neighbors[0]).setOffset(aoFace.neighbors[2]);
            cAo0 = aoFunc.apply(searchPos);
            cLight0 = brightnessFunc.applyAsInt(searchPos);
        }
        if (!isClear3 && !isClear0) {
            cAo1 = ao0;
            cLight1 = light0;
        } else {
            searchPos.set(lightPos).setOffset(aoFace.neighbors[0]).setOffset(aoFace.neighbors[3]);
            cAo1 = aoFunc.apply(searchPos);
            cLight1 = brightnessFunc.applyAsInt(searchPos);
        }
        if (!isClear2 && !isClear1) {
            cAo2 = ao1;
            cLight2 = light1;
        } else {
            searchPos.set(lightPos).setOffset(aoFace.neighbors[1]).setOffset(aoFace.neighbors[2]);
            cAo2 = aoFunc.apply(searchPos);
            cLight2 = brightnessFunc.applyAsInt(searchPos);
        }
        if (!isClear3 && !isClear1) {
            cAo3 = ao1;
            cLight3 = light1;
        } else {
            searchPos.set(lightPos).setOffset(aoFace.neighbors[1]).setOffset(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((Vec3i) pos).setOffset(lightFace);
        if (isOnBlockFace || !world.getBlockState(searchPos).isFullOpaque(world, searchPos)) {
            lightCenter = brightnessFunc.applyAsInt(searchPos);
        } else {
            lightCenter = brightnessFunc.applyAsInt(pos);
        }
        float aoCenter = aoFunc.apply(isOnBlockFace ? lightPos : pos);
        result.a0 = (ao3 + ao0 + cAo1 + aoCenter) * 0.25F;
        result.a1 = (ao2 + ao0 + cAo0 + aoCenter) * 0.25F;
        result.a2 = (ao2 + ao1 + cAo2 + aoCenter) * 0.25F;
        result.a3 = (ao3 + ao1 + cAo3 + aoCenter) * 0.25F;
        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 : Vec3i(net.minecraft.util.math.Vec3i) BlockPos(net.minecraft.util.math.BlockPos) ExtendedBlockView(net.minecraft.world.ExtendedBlockView)

Example 2 with ExtendedBlockView

use of net.minecraft.world.ExtendedBlockView in project fabric by FabricMC.

the class FluidRenderHandlerRegistryImpl method onFluidRendererReload.

public void onFluidRendererReload(Sprite[] waterSprites, Sprite[] lavaSprites) {
    FluidRenderHandler waterHandler = new FluidRenderHandler() {

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

        @Override
        public int getFluidColor(ExtendedBlockView view, BlockPos pos, FluidState state) {
            if (view != null && pos != null) {
                return BiomeColors.getWaterColor(view, pos);
            } else {
                return Biomes.DEFAULT.getWaterColor();
            }
        }
    };
    // noinspection Convert2Lambda
    FluidRenderHandler lavaHandler = new FluidRenderHandler() {

        @Override
        public Sprite[] getFluidSprites(ExtendedBlockView view, BlockPos pos, FluidState state) {
            return lavaSprites;
        }
    };
    register(Fluids.WATER, waterHandler);
    register(Fluids.FLOWING_WATER, waterHandler);
    register(Fluids.LAVA, lavaHandler);
    register(Fluids.FLOWING_LAVA, lavaHandler);
    handlers.putAll(modHandlers);
}
Also used : Sprite(net.minecraft.client.texture.Sprite) BlockPos(net.minecraft.util.math.BlockPos) FluidRenderHandler(net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler) ExtendedBlockView(net.minecraft.world.ExtendedBlockView) FluidState(net.minecraft.fluid.FluidState)

Aggregations

BlockPos (net.minecraft.util.math.BlockPos)2 ExtendedBlockView (net.minecraft.world.ExtendedBlockView)2 FluidRenderHandler (net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler)1 Sprite (net.minecraft.client.texture.Sprite)1 FluidState (net.minecraft.fluid.FluidState)1 Vec3i (net.minecraft.util.math.Vec3i)1