Add partial support for non-shaded quads

- Add ShadeSeparatedBufferBuilder and other code to allow separating all
non-shaded vertices to the end of the buffer
- Add ShadedVertexList to allow defining if a certain vertex is shaded
or not
- Add new methods to ModelUtil with arguments for more flexibility
- Refactor VirtualEmptyBlockGetter to allow defining arbitrary light
values
- Add shaded argument to DiffuseLightCalculator
This commit is contained in:
PepperCode1 2022-02-18 20:39:19 -08:00
parent 52f66dec9d
commit 0c74be53f6
14 changed files with 371 additions and 108 deletions

View file

@ -0,0 +1,5 @@
package com.jozufozu.flywheel.api.vertex;
public interface ShadedVertexList extends VertexList {
boolean isShaded(int index);
}

View file

@ -12,6 +12,8 @@ import com.mojang.blaze3d.vertex.VertexFormat;
*/
public interface BufferBuilderExtension {
int flywheel$getVertices();
/**
* Frees the internal ByteBuffer, if it exists.
*/
@ -24,4 +26,12 @@ public interface BufferBuilderExtension {
* @param vertexCount The number of vertices in the buffer.
*/
void flywheel$injectForRender(ByteBuffer buffer, VertexFormat format, int vertexCount);
/**
* Appends the remaining bytes from the given buffer to this BufferBuilder.
* @param buffer The buffer from which to copy bytes.
* @throws IllegalStateException If this BufferBuilder is not started or is the process of writing a vertex
* @throws IllegalArgumentException If the given buffer does not contain a whole number of vertices
*/
void flywheel$appendBufferUnsafe(ByteBuffer buffer);
}

View file

@ -16,7 +16,7 @@ import com.jozufozu.flywheel.core.QuadConverter;
* </p>
*
* <pre>{@code
* IModel model = ...;
* Model model = ...;
* VecBuffer into = ...;
*
* int initial = VecBuffer.unwrap().position();

View file

@ -1,5 +1,8 @@
package com.jozufozu.flywheel.core.model;
import java.util.function.IntPredicate;
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.util.DiffuseLightCalculator;
import com.jozufozu.flywheel.util.transform.Transform;
@ -19,12 +22,18 @@ public class ModelTransformer {
private final Model model;
private final VertexList reader;
private final IntPredicate shadedPredicate;
public final Context context = new Context();
public ModelTransformer(Model model) {
this.model = model;
reader = model.getReader();
if (reader instanceof ShadedVertexList shaded) {
shadedPredicate = shaded::isShaded;
} else {
shadedPredicate = index -> true;
}
}
public void renderInto(Params params, PoseStack input, VertexConsumer builder) {
@ -82,7 +91,7 @@ public class ModelTransformer {
a = reader.getA(i);
}
if (context.outputColorDiffuse) {
float instanceDiffuse = diffuseCalculator.getDiffuse(nx, ny, nz);
float instanceDiffuse = diffuseCalculator.getDiffuse(nx, ny, nz, shadedPredicate.test(i));
int colorR = transformColor(r, instanceDiffuse);
int colorG = transformColor(g, instanceDiffuse);
int colorB = transformColor(b, instanceDiffuse);

View file

@ -38,6 +38,8 @@ public class ModelUtil {
*/
public static final BlockRenderDispatcher VANILLA_RENDERER = createVanillaRenderer();
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
private static BlockRenderDispatcher createVanillaRenderer() {
BlockRenderDispatcher defaultDispatcher = Minecraft.getInstance().getBlockRenderer();
BlockRenderDispatcher dispatcher = new BlockRenderDispatcher(null, null, null);
@ -54,23 +56,47 @@ public class ModelUtil {
return dispatcher;
}
public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) {
public static ShadeSeparatedBufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack poseStack) {
return getBufferBuilder(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, poseStack);
}
public static ShadeSeparatedBufferBuilder getBufferBuilder(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) {
ModelBlockRenderer blockRenderer = VANILLA_RENDERER.getModelRenderer();
BufferBuilder builder = new BufferBuilder(512);
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512);
BufferBuilder unshadedBuilder = objects.unshadedBuilder;
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder,
false, new Random(), 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
shadeSeparatingWrapper.prepare(builder, unshadedBuilder);
blockRenderer.tesselateBlock(renderWorld, model, referenceState, BlockPos.ZERO, poseStack, shadeSeparatingWrapper,
false, objects.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
shadeSeparatingWrapper.clear();
unshadedBuilder.end();
builder.appendUnshadedVertices(unshadedBuilder);
builder.end();
return builder;
}
public static BufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
ModelBlockRenderer modelRenderer = VANILLA_RENDERER.getModelRenderer();
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
return getBufferBuilderFromTemplate(renderWorld, layer, blocks, new PoseStack());
}
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, PoseStack poseStack) {
ModelBlockRenderer modelRenderer = VANILLA_RENDERER.getModelRenderer();
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
Random random = objects.random;
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512);
BufferBuilder unshadedBuilder = objects.unshadedBuilder;
PoseStack ms = new PoseStack();
Random random = new Random();
BufferBuilder builder = new BufferBuilder(512);
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
shadeSeparatingWrapper.prepare(builder, unshadedBuilder);
ForgeHooksClient.setRenderType(layer);
ModelBlockRenderer.enableCaching();
@ -84,16 +110,20 @@ public class ModelUtil {
BlockPos pos = info.pos;
ms.pushPose();
ms.translate(pos.getX(), pos.getY(), pos.getZ());
modelRenderer.tesselateBlock(renderWorld, VANILLA_RENDERER.getBlockModel(state), state, pos, ms, builder,
poseStack.pushPose();
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
modelRenderer.tesselateBlock(renderWorld, VANILLA_RENDERER.getBlockModel(state), state, pos, poseStack, shadeSeparatingWrapper,
true, random, 42, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE);
ms.popPose();
poseStack.popPose();
}
ModelBlockRenderer.clearCache();
ForgeHooksClient.setRenderType(null);
shadeSeparatingWrapper.clear();
unshadedBuilder.end();
builder.appendUnshadedVertices(unshadedBuilder);
builder.end();
return builder;
}
@ -107,4 +137,10 @@ public class ModelUtil {
return stack;
};
}
private static class ThreadLocalObjects {
public final Random random = new Random();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
}
}

View file

@ -0,0 +1,25 @@
package com.jozufozu.flywheel.core.model;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.datafixers.util.Pair;
public class ShadeSeparatedBufferBuilder extends BufferBuilder {
protected int unshadedStartVertex;
public ShadeSeparatedBufferBuilder(int capacity) {
super(capacity);
}
public void appendUnshadedVertices(BufferBuilder unshadedBuilder) {
Pair<DrawState, ByteBuffer> data = unshadedBuilder.popNextBuffer();
unshadedStartVertex = ((BufferBuilderExtension) this).flywheel$getVertices();
((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(data.getSecond());
}
public int getUnshadedStartVertex() {
return unshadedStartVertex;
}
}

View file

@ -0,0 +1,84 @@
package com.jozufozu.flywheel.core.model;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.block.model.BakedQuad;
public class ShadeSeparatingVertexConsumer implements VertexConsumer {
protected VertexConsumer shadedConsumer;
protected VertexConsumer unshadedConsumer;
public void prepare(VertexConsumer shadedConsumer, VertexConsumer unshadedConsumer) {
this.shadedConsumer = shadedConsumer;
this.unshadedConsumer = unshadedConsumer;
}
public void clear() {
shadedConsumer = null;
unshadedConsumer = null;
}
@Override
public void putBulkData(PoseStack.Pose poseEntry, BakedQuad quad, float[] colorMuls, float red, float green, float blue, int[] combinedLights, int combinedOverlay, boolean mulColor) {
if (quad.isShade()) {
shadedConsumer.putBulkData(poseEntry, quad, colorMuls, red, green, blue, combinedLights, combinedOverlay, mulColor);
} else {
unshadedConsumer.putBulkData(poseEntry, quad, colorMuls, red, green, blue, combinedLights, combinedOverlay, mulColor);
}
}
@Override
public void putBulkData(PoseStack.Pose matrixEntry, BakedQuad bakedQuad, float[] baseBrightness, float red, float green, float blue, float alpha, int[] lightmapCoords, int overlayCoords, boolean readExistingColor) {
if (bakedQuad.isShade()) {
shadedConsumer.putBulkData(matrixEntry, bakedQuad, baseBrightness, red, green, blue, alpha, lightmapCoords, overlayCoords, readExistingColor);
} else {
unshadedConsumer.putBulkData(matrixEntry, bakedQuad, baseBrightness, red, green, blue, alpha, lightmapCoords, overlayCoords, readExistingColor);
}
}
@Override
public VertexConsumer vertex(double x, double y, double z) {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
@Override
public VertexConsumer color(int red, int green, int blue, int alpha) {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
@Override
public VertexConsumer uv(float u, float v) {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
@Override
public VertexConsumer overlayCoords(int u, int v) {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
@Override
public VertexConsumer uv2(int u, int v) {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
@Override
public VertexConsumer normal(float x, float y, float z) {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
@Override
public void endVertex() {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
@Override
public void defaultColor(int red, int green, int blue, int alpha) {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
@Override
public void unsetDefaultColor() {
throw new UnsupportedOperationException("ShadeSeparatingVertexConsumer only supports putBulkData!");
}
}

View file

@ -6,6 +6,7 @@ import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.datafixers.util.Pair;
@ -57,6 +58,10 @@ Vertex FLWCreateVertex() {
""";
}
public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex);
}
public VertexList createReader(BufferBuilder bufferBuilder) {
// TODO: try to avoid virtual model rendering
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
@ -66,6 +71,10 @@ Vertex FLWCreateVertex() {
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format());
}
return new BlockVertexListUnsafe(pair.getSecond(), drawState.vertexCount());
if (bufferBuilder instanceof ShadeSeparatedBufferBuilder separated) {
return createReader(pair.getSecond(), drawState.vertexCount(), separated.getUnshadedStartVertex());
} else {
return createReader(pair.getSecond(), drawState.vertexCount());
}
}
}

View file

@ -2,7 +2,9 @@ package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
import com.jozufozu.flywheel.util.RenderMath;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.datafixers.util.Pair;
@ -104,4 +106,20 @@ public class BlockVertexList implements VertexList {
return vertexCount;
}
public static class Shaded extends BlockVertexList implements ShadedVertexList {
private final int unshadedStartVertex;
public Shaded(ShadeSeparatedBufferBuilder builder) {
super(builder);
unshadedStartVertex = builder.getUnshadedStartVertex();
}
@Override
public boolean isShaded(int index) {
return index < unshadedStartVertex;
}
}
}

View file

@ -4,6 +4,7 @@ import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.util.RenderMath;
@ -97,4 +98,21 @@ public class BlockVertexListUnsafe implements VertexList {
public int getVertexCount() {
return vertexCount;
}
public static class Shaded extends BlockVertexListUnsafe implements ShadedVertexList {
private final int unshadedStartVertex;
public Shaded(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
super(buffer, vertexCount);
this.unshadedStartVertex = unshadedStartVertex;
}
@Override
public boolean isShaded(int index) {
return index < unshadedStartVertex;
}
}
}

View file

@ -22,115 +22,119 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
public enum VirtualEmptyBlockGetter implements BlockAndTintGetter {
INSTANCE;
private final LevelLightEngine lightEngine = new LevelLightEngine(new LightChunkGetter() {
@Override
public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) {
return VirtualEmptyBlockGetter.this;
}
@Override
public BlockGetter getLevel() {
return VirtualEmptyBlockGetter.this;
}
}, false, false) {
private static final LayerLightEventListener SKY_DUMMY_LISTENER = new LayerLightEventListener() {
@Override
public void checkBlock(BlockPos pos) {
}
@Override
public void onBlockEmissionIncrease(BlockPos pos, int p_164456_) {
}
@Override
public boolean hasLightWork() {
return false;
}
@Override
public int runUpdates(int p_164449_, boolean p_164450_, boolean p_164451_) {
return p_164449_;
}
@Override
public void updateSectionStatus(SectionPos pos, boolean p_75838_) {
}
@Override
public void enableLightSources(ChunkPos pos, boolean p_164453_) {
}
@Override
public DataLayer getDataLayerData(SectionPos pos) {
return null;
}
@Override
public int getLightValue(BlockPos pos) {
return 15;
}
};
@Override
public LayerLightEventListener getLayerListener(LightLayer layer) {
if (layer == LightLayer.BLOCK) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
} else {
return SKY_DUMMY_LISTENER;
}
}
@Override
public int getRawBrightness(BlockPos pos, int skyDarken) {
return 15 - skyDarken;
}
};
public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
public static final VirtualEmptyBlockGetter INSTANCE = new StaticLightImpl(0, 15);
public static final VirtualEmptyBlockGetter FULL_BRIGHT = new StaticLightImpl(15, 15);
public static final VirtualEmptyBlockGetter FULL_DARK = new StaticLightImpl(0, 0);
public static boolean is(BlockAndTintGetter blockGetter) {
return blockGetter == INSTANCE;
return blockGetter instanceof VirtualEmptyBlockGetter;
}
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
default BlockEntity getBlockEntity(BlockPos pos) {
return null;
}
@Override
public BlockState getBlockState(BlockPos pos) {
default BlockState getBlockState(BlockPos pos) {
return Blocks.AIR.defaultBlockState();
}
@Override
public FluidState getFluidState(BlockPos pos) {
default FluidState getFluidState(BlockPos pos) {
return Fluids.EMPTY.defaultFluidState();
}
@Override
public int getHeight() {
default int getHeight() {
return 1;
}
@Override
public int getMinBuildHeight() {
default int getMinBuildHeight() {
return 0;
}
@Override
public float getShade(Direction direction, boolean bool) {
default float getShade(Direction direction, boolean shaded) {
return 1f;
}
@Override
public LevelLightEngine getLightEngine() {
return lightEngine;
}
@Override
public int getBlockTint(BlockPos pos, ColorResolver resolver) {
default int getBlockTint(BlockPos pos, ColorResolver resolver) {
Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getOrThrow(Biomes.PLAINS);
return resolver.getColor(plainsBiome, pos.getX(), pos.getZ());
}
public static class StaticLightImpl implements VirtualEmptyBlockGetter {
private final LevelLightEngine lightEngine;
public StaticLightImpl(int blockLight, int skyLight) {
lightEngine = new LevelLightEngine(new LightChunkGetter() {
@Override
public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) {
return StaticLightImpl.this;
}
@Override
public BlockGetter getLevel() {
return StaticLightImpl.this;
}
}, false, false) {
private final LayerLightEventListener blockListener = createStaticListener(blockLight);
private final LayerLightEventListener skyListener = createStaticListener(skyLight);
@Override
public LayerLightEventListener getLayerListener(LightLayer layer) {
return layer == LightLayer.BLOCK ? blockListener : skyListener;
}
};
}
private static LayerLightEventListener createStaticListener(int light) {
return new LayerLightEventListener() {
@Override
public void checkBlock(BlockPos pos) {
}
@Override
public void onBlockEmissionIncrease(BlockPos pos, int p_164456_) {
}
@Override
public boolean hasLightWork() {
return false;
}
@Override
public int runUpdates(int p_164449_, boolean p_164450_, boolean p_164451_) {
return p_164449_;
}
@Override
public void updateSectionStatus(SectionPos pos, boolean p_75838_) {
}
@Override
public void enableLightSources(ChunkPos pos, boolean p_164453_) {
}
@Override
public DataLayer getDataLayerData(SectionPos pos) {
return null;
}
@Override
public int getLightValue(BlockPos pos) {
return light;
}
};
}
@Override
public LevelLightEngine getLightEngine() {
return lightEngine;
}
}
}

View file

@ -20,16 +20,10 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension {
private ByteBuffer buffer;
@Shadow
private boolean building;
private int nextElementByte;
@Shadow
public abstract void begin(VertexFormat.Mode p_166780_, VertexFormat p_166781_);
@Shadow
private VertexFormat.Mode mode;
@Shadow
private VertexFormat format;
private int vertices;
@Shadow
@Nullable
@ -39,7 +33,22 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension {
private int elementIndex;
@Shadow
private int vertices;
private VertexFormat format;
@Shadow
private VertexFormat.Mode mode;
@Shadow
private boolean building;
@Shadow
private void ensureCapacity(int increaseAmount) {
}
@Override
public int flywheel$getVertices() {
return vertices;
}
@Override
public void flywheel$freeBuffer() {
@ -61,4 +70,29 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension {
this.currentElement = this.format.getElements().get(0);
this.elementIndex = 0;
}
@Override
public void flywheel$appendBufferUnsafe(ByteBuffer buffer) {
if (!building) {
throw new IllegalStateException("BufferBuilder not started");
}
if (elementIndex != 0) {
throw new IllegalStateException("Cannot append buffer while building vertex");
}
int numBytes = buffer.remaining();
if (numBytes % format.getVertexSize() != 0) {
throw new IllegalArgumentException("Cannot append buffer with non-whole number of vertices");
}
int numVertices = numBytes / format.getVertexSize();
ensureCapacity(numBytes + format.getVertexSize());
int originalPosition = this.buffer.position();
this.buffer.position(nextElementByte);
MemoryUtil.memCopy(buffer, this.buffer);
this.buffer.position(originalPosition);
nextElementByte += numBytes;
vertices += numVertices;
}
}

View file

@ -2,10 +2,9 @@ package com.jozufozu.flywheel.util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraftforge.client.model.pipeline.LightUtil;
public interface DiffuseLightCalculator {
DiffuseLightCalculator DEFAULT = LightUtil::diffuseLight;
DiffuseLightCalculator DEFAULT = RenderMath::diffuseLight;
DiffuseLightCalculator NETHER = RenderMath::diffuseLightNether;
static DiffuseLightCalculator forCurrentLevel() {
@ -16,5 +15,5 @@ public interface DiffuseLightCalculator {
return level.effects().constantAmbientLight() ? NETHER : DEFAULT;
}
float getDiffuse(float normalX, float normalY, float normalZ);
float getDiffuse(float normalX, float normalY, float normalZ, boolean shaded);
}

View file

@ -1,5 +1,7 @@
package com.jozufozu.flywheel.util;
import net.minecraftforge.client.model.pipeline.LightUtil;
public class RenderMath {
/**
@ -68,7 +70,17 @@ public class RenderMath {
return (float) (((((target - current) % 360) + 540) % 360) - 180);
}
public static float diffuseLightNether(float x, float y, float z) {
public static float diffuseLight(float x, float y, float z, boolean shaded) {
if (!shaded) {
return 1f;
}
return LightUtil.diffuseLight(x, y, z);
}
public static float diffuseLightNether(float x, float y, float z, boolean shaded) {
if (!shaded) {
return 0.9f;
}
return Math.min(x * x * 0.6f + y * y * 0.9f + z * z * 0.8f, 1f);
}
}