mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-26 15:06:28 +01:00
Don't tell me what to do!
- Respect minecraft's entity shadows option. - Early exit in InstanceRecycler#discardExtra when there's no extra. - Shadow radius <= 0 disables shadows. - More documentation in ShadowComponent.
This commit is contained in:
parent
380e078cb2
commit
f47eaa53c1
2 changed files with 56 additions and 29 deletions
|
@ -59,12 +59,15 @@ public class InstanceRecycler<I extends Instance> {
|
|||
* Call this after your last call to {@link #get()} each frame.
|
||||
*/
|
||||
public void discardExtra() {
|
||||
for (int i = count; i < instances.size(); i++) {
|
||||
instances.get(i)
|
||||
.delete();
|
||||
var size = instances.size();
|
||||
if (count == size) {
|
||||
// No extra instances, early exit to avoid creating the sublist.
|
||||
return;
|
||||
}
|
||||
instances.subList(count, instances.size())
|
||||
.clear();
|
||||
|
||||
var extra = instances.subList(count, size);
|
||||
extra.forEach(Instance::delete);
|
||||
extra.clear();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.jozufozu.flywheel.lib.instance.ShadowInstance;
|
|||
import com.jozufozu.flywheel.lib.material.SimpleMaterial;
|
||||
import com.jozufozu.flywheel.lib.model.QuadMesh;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -33,6 +34,15 @@ import net.minecraft.world.level.chunk.ChunkAccess;
|
|||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
/**
|
||||
* A component that uses instances to render an entity's shadow.
|
||||
*
|
||||
* <p>Use {@link #radius(float)} to set the radius of the shadow, in blocks.
|
||||
* <br>
|
||||
* Use {@link #strength(float)} to set the strength of the shadow.
|
||||
* <br>
|
||||
* The shadow will be cast on blocks at most {@code min(radius, 2 * strength)} blocks below the entity.</p>
|
||||
*/
|
||||
public class ShadowComponent {
|
||||
|
||||
private final VisualizationContext context;
|
||||
|
@ -41,9 +51,9 @@ public class ShadowComponent {
|
|||
private final InstanceRecycler<ShadowInstance> instances = new InstanceRecycler<>(this::instance);
|
||||
private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||
|
||||
private float radius = 0.5F;
|
||||
// Defaults taken from EntityRenderer.
|
||||
private float radius = 0;
|
||||
private float strength = 1.0F;
|
||||
private boolean enabled = true;
|
||||
|
||||
public ShadowComponent(VisualizationContext context, Entity entity) {
|
||||
this.context = context;
|
||||
|
@ -51,33 +61,49 @@ public class ShadowComponent {
|
|||
this.entity = entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the radius of the shadow, in blocks, clamped to a maximum of 32.
|
||||
*
|
||||
* <p>Setting this to {@code <= 0} will disable the shadow.</p>
|
||||
*
|
||||
* @param radius The radius of the shadow, in blocks.
|
||||
*/
|
||||
public void radius(float radius) {
|
||||
this.radius = radius;
|
||||
this.radius = Math.min(radius, 32);
|
||||
}
|
||||
|
||||
public void strength(float weight) {
|
||||
this.strength = weight;
|
||||
}
|
||||
|
||||
public void enabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
|
||||
if (!enabled) {
|
||||
instances.delete();
|
||||
}
|
||||
/**
|
||||
* Set the strength of the shadow.
|
||||
*
|
||||
* @param strength The strength of the shadow.
|
||||
*/
|
||||
public void strength(float strength) {
|
||||
this.strength = strength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the shadow instances. You'd typically call this in your visual's
|
||||
* {@link com.jozufozu.flywheel.api.visual.DynamicVisual#beginFrame(VisualFrameContext) beginFrame} method.
|
||||
*
|
||||
* @param context The frame context.
|
||||
*/
|
||||
public void beginFrame(VisualFrameContext context) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
instances.resetCount();
|
||||
|
||||
boolean shadowsEnabled = Minecraft.getInstance().options.entityShadows()
|
||||
.get();
|
||||
if (shadowsEnabled && radius > 0 && !entity.isInvisible()) {
|
||||
setupInstances(context);
|
||||
}
|
||||
|
||||
instances.discardExtra();
|
||||
}
|
||||
|
||||
private void setupInstances(VisualFrameContext context) {
|
||||
double entityX = Mth.lerp(context.partialTick(), entity.xOld, entity.getX());
|
||||
double entityY = Mth.lerp(context.partialTick(), entity.yOld, entity.getY());
|
||||
double entityZ = Mth.lerp(context.partialTick(), entity.zOld, entity.getZ());
|
||||
float castDistance = Math.min(strength / 0.5F, radius);
|
||||
float castDistance = Math.min(strength * 2, radius);
|
||||
int minXPos = Mth.floor(entityX - (double) radius);
|
||||
int maxXPos = Mth.floor(entityX + (double) radius);
|
||||
int minYPos = Mth.floor(entityY - (double) castDistance);
|
||||
|
@ -92,16 +118,14 @@ public class ShadowComponent {
|
|||
|
||||
for (int y = minYPos; y <= maxYPos; ++y) {
|
||||
pos.setY(y);
|
||||
float actualWeight = strength - (float) (entityY - pos.getY()) * 0.5F;
|
||||
maybeSetupShadowInstance(chunkaccess, (float) entityX, (float) entityZ, actualWeight);
|
||||
float strengthGivenYFalloff = strength - (float) (entityY - pos.getY()) * 0.5F;
|
||||
maybeSetupShadowInstance(chunkaccess, (float) entityX, (float) entityZ, strengthGivenYFalloff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
instances.discardExtra();
|
||||
}
|
||||
|
||||
private void maybeSetupShadowInstance(ChunkAccess pChunk, float entityX, float entityZ, float weight) {
|
||||
private void maybeSetupShadowInstance(ChunkAccess pChunk, float entityX, float entityZ, float strength) {
|
||||
// TODO: cache this?
|
||||
var maxLocalRawBrightness = level.getMaxLocalRawBrightness(pos);
|
||||
if (maxLocalRawBrightness <= 3) {
|
||||
|
@ -109,7 +133,7 @@ public class ShadowComponent {
|
|||
return;
|
||||
}
|
||||
float blockBrightness = LightTexture.getBrightness(level.dimensionType(), maxLocalRawBrightness);
|
||||
float alpha = weight * 0.5F * blockBrightness;
|
||||
float alpha = strength * 0.5F * blockBrightness;
|
||||
if (!(alpha >= 0.0F)) {
|
||||
// Too far away/too weak to render.
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue