Fix dust appearing in the ground and fix clouds appearing black (use per-vertex lighting)

This commit is contained in:
Sollace 2024-02-13 15:35:26 +00:00
parent e97adc8841
commit 2754d41ee9
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
8 changed files with 124 additions and 33 deletions

View file

@ -27,6 +27,7 @@ public abstract class AbstractBillboardParticle extends AbstractGeometryBasedPar
RenderSystem.disableCull();
RenderSystem.enableBlend();
RenderSystem.enableDepthTest();
RenderSystem.defaultBlendFunc();
Vec3d cam = camera.getPos();

View file

@ -1,11 +1,16 @@
package com.minelittlepony.unicopia.client.particle;
import org.joml.Vector4f;
import com.minelittlepony.common.util.Color;
import com.minelittlepony.unicopia.client.render.RenderUtil;
import com.minelittlepony.unicopia.client.render.model.FanModel;
import com.minelittlepony.unicopia.client.render.model.VertexLightSource;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
@ -16,15 +21,15 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
public class DustCloudParticle extends AbstractBillboardParticle {
//private static final Identifier TEXTURE = new Identifier("textures/particle/big_smoke_3.png");
protected static final int SEGMENTS = 20;
protected static final int SEPARATION = 270 / SEGMENTS;
private float scaleFactor;
protected Sprite sprite;
private final RenderUtil.Vertex[] vertices;
private final FanModel model;
private final VertexLightSource lightSource;
public DustCloudParticle(BlockStateParticleEffect effect, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) {
super(world, x, y, z, velocityX, velocityY, velocityZ);
@ -33,14 +38,15 @@ public class DustCloudParticle extends AbstractBillboardParticle {
red = 0.6F;
green = 0.6F;
blue = 0.6F;
alpha = (float)world.getRandom().nextTriangular(0.6, 0.2);
alpha = (float)world.getRandom().nextTriangular(0.6, 0.2) * 0.3F;
scaleFactor = (float)world.getRandom().nextTriangular(2, 1.2);
sprite = MinecraftClient.getInstance().getBlockRenderManager().getModels().getModelParticleSprite(effect.getBlockState());
vertices = new RenderUtil.Vertex[]{
new RenderUtil.Vertex(-1, -1, 0, sprite.getMinU(), sprite.getMinV()),
new RenderUtil.Vertex(-1, 1, 0, sprite.getMaxU(), sprite.getMinV()),
new RenderUtil.Vertex( 1, 1, 0, sprite.getMaxU(), sprite.getMaxV()),
new RenderUtil.Vertex( 1, -1, 0, sprite.getMinU(), sprite.getMaxV())
lightSource = new VertexLightSource(world);
model = new FanModel(sprite) {
@Override
protected int getLightAt(Vector4f pos, int light) {
return lightSource.getLight(pos, light);
}
};
if (!effect.getBlockState().isOf(Blocks.GRASS_BLOCK)) {
int i = MinecraftClient.getInstance().getBlockColors().getColor(effect.getBlockState(), world, BlockPos.ofFloored(x, y, z), 0);
@ -60,26 +66,29 @@ public class DustCloudParticle extends AbstractBillboardParticle {
super.tick();
scaleFactor += 0.001F;
scale(MathHelper.clamp(age / 5F, 0, 1) * scaleFactor);
lightSource.tick();
}
@Override
protected void renderQuads(Tessellator te, BufferBuilder buffer, float x, float y, float z, float tickDelta) {
float scale = getScale(tickDelta);
float scale = getScale(tickDelta) * 0.5F;
float alpha = this.alpha * (1 - ((float)age / maxAge));
MatrixStack matrices = new MatrixStack();
matrices.translate(x, y, z);
matrices.scale(scale, scale * 0.5F, scale);
matrices.scale(1, 0.5F, 1);
float angle = ((this.age + tickDelta) % 360) / SEGMENTS;
float angle = (MathHelper.sin((this.age + tickDelta) / 100F) * 360) / SEGMENTS;
for (int i = 0; i < SEGMENTS; i++) {
matrices.push();
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees((i * angle) % 360));
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees((SEPARATION * i + angle) % 360));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((SEPARATION * i + angle) % 360));
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees((i * angle)));
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees((SEPARATION * i - angle)));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((SEPARATION * i + angle)));
float ringScale = 1 + MathHelper.sin(((i * 10) + age + tickDelta) * 0.05F) * 0.1F;
matrices.scale(ringScale, ringScale, ringScale);
renderQuad(matrices, te, buffer, vertices, alpha, tickDelta);
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
model.render(matrices, buffer, 0, scale * ringScale, 1, 1, 1, alpha);
te.draw();
matrices.pop();
}
}

View file

@ -50,7 +50,7 @@ public class BakedModel {
textureMatrix.identity();
}
public final void render(MatrixStack matrices, VertexConsumer buffer, float scale, float r, float g, float b, float a) {
public final void render(MatrixStack matrices, VertexConsumer buffer, int light, float scale, float r, float g, float b, float a) {
scale = Math.abs(scale);
if (scale < 0.001F) {
return;
@ -62,9 +62,13 @@ public class BakedModel {
for (RenderUtil.Vertex vertex : vertices) {
Vector4f pos = vertex.position(positionmatrix);
Vector4f tex = vertex.texture(textureMatrix);
buffer.vertex(pos.x, pos.y, pos.z).texture(tex.x, tex.y).color(r, g, b, a).next();
buffer.vertex(pos.x, pos.y, pos.z).texture(tex.x, tex.y).color(r, g, b, a).light(getLightAt(pos, light)).next();
}
matrices.pop();
textureMatrix.identity();
}
protected int getLightAt(Vector4f pos, int light) {
return light;
}
}

View file

@ -0,0 +1,40 @@
package com.minelittlepony.unicopia.client.render.model;
import com.minelittlepony.unicopia.client.render.RenderUtil;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.RotationAxis;
public class FanModel extends BakedModel {
public FanModel(Sprite sprite) {
RenderUtil.Vertex[] dorito = createDorito(sprite);
MatrixStack matrices = new MatrixStack();
for (int d = 0; d < 12; d++) {
matrices.push();
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(30 * d));
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(15));
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(15 * d));
matrices.translate(2.9F, 0, 0);
for (RenderUtil.Vertex corner : dorito) {
var position = corner.position(matrices.peek().getPositionMatrix());
addVertex(position.x, position.y(), position.z(), corner.texture().x, corner.texture().y);
}
matrices.pop();
}
}
static RenderUtil.Vertex[] createDorito(Sprite sprite) {
float chunkSize = 1F;
float baseLength = 0.8F;
float uLength = sprite.getMaxU() - sprite.getMinU();
return new RenderUtil.Vertex[]{
new RenderUtil.Vertex(-chunkSize, -chunkSize * baseLength, 0, sprite.getMinU() + uLength * baseLength, sprite.getMinV()),
new RenderUtil.Vertex( chunkSize, 0, 0, sprite.getMaxU(), sprite.getMaxV()),
new RenderUtil.Vertex(-chunkSize, chunkSize * baseLength, 0, sprite.getMinU(), sprite.getMinV()),
new RenderUtil.Vertex(-chunkSize * 3, 0, 0, sprite.getMinU(), sprite.getMaxV())
};
}
}

View file

@ -0,0 +1,44 @@
package com.minelittlepony.unicopia.client.render.model;
import org.joml.Vector4f;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class VertexLightSource {
private final ClientWorld world;
private final Long2ObjectMap<Integer> lightCache = new Long2ObjectOpenHashMap<>();
public VertexLightSource(ClientWorld world) {
this.world = world;
}
public void tick() {
lightCache.clear();
}
public int getLight(Vector4f vertexPosition, int light) {
return lightCache.computeIfAbsent(getBlockPosition(vertexPosition), this::getLight);
}
@SuppressWarnings("deprecation")
private int getLight(long p) {
final BlockPos pos = BlockPos.fromLong(p);
return world.isChunkLoaded(pos) ? WorldRenderer.getLightmapCoordinates(world, pos) : 0;
}
private long getBlockPosition(Vector4f vertexPosition) {
Vec3d cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos();
return BlockPos.asLong(
MathHelper.floor(cameraPos.x + vertexPosition.x),
MathHelper.floor(cameraPos.y + vertexPosition.y),
MathHelper.floor(cameraPos.z + vertexPosition.z)
);
}
}

View file

@ -3,23 +3,16 @@ package com.minelittlepony.unicopia.client.render.shader;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.Unicopia;
import net.fabricmc.fabric.api.client.rendering.v1.CoreShaderRegistrationCallback;
import net.minecraft.client.gl.ShaderProgram;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
public final class UShaders {
@Nullable
private static Supplier<ShaderProgram> renderTypePortalSurfaceProgram = register("rendertype_portal_surface", VertexFormats.POSITION_COLOR);
public interface UShaders {
Supplier<ShaderProgram> RENDER_TYPE_PORTAL_SURFACE = register("rendertype_portal_surface", VertexFormats.POSITION_COLOR);
public static ShaderProgram getRenderTypePortalSurfaceProgram() {
return renderTypePortalSurfaceProgram.get();
}
public static void bootstrap() { }
static void bootstrap() { }
static Supplier<ShaderProgram> register(String name, VertexFormat format) {
AtomicReference<ShaderProgram> holder = new AtomicReference<>();

View file

@ -94,14 +94,14 @@ class PortalFrameBuffer implements AutoCloseable {
BufferBuilder buffer = tessellator.getBuffer();
float uScale = (float)framebuffer.viewportWidth / (float)framebuffer.textureWidth;
float vScale = (float)framebuffer.viewportHeight / (float)framebuffer.textureHeight;
RenderSystem.setShader(UShaders::getRenderTypePortalSurfaceProgram);
RenderSystem.setShader(UShaders.RENDER_TYPE_PORTAL_SURFACE);
//RenderSystem.setShader(GameRenderer::getPositionTexColorProgram);
RenderSystem._setShaderTexture(0, framebuffer.getColorAttachment());
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR);
SphereModel.DISK.scaleUV(uScale, vScale);
RenderSystem.setTextureMatrix(SphereModel.DISK.getTextureMatrix());
SphereModel.DISK.render(matrices, buffer, 2F, 1, 1, 1, 1);
SphereModel.DISK.render(matrices, buffer, 1, 2F, 1, 1, 1, 1);
tessellator.draw();
client.getTextureManager().bindTexture(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE);

View file

@ -567,7 +567,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
if (entity.isOnGround() || !force) {
BlockState steppingState = pony.asEntity().getSteppingBlockState();
if (steppingState.isIn(UTags.KICKS_UP_DUST)) {
pony.addParticle(new BlockStateParticleEffect(UParticles.DUST_CLOUD, steppingState), pony.getOrigin().down().toCenterPos(), Vec3d.ZERO);
pony.addParticle(new BlockStateParticleEffect(UParticles.DUST_CLOUD, steppingState), pony.getOrigin().toCenterPos(), Vec3d.ZERO);
} else {
Supplier<Vec3d> pos = VecHelper.sphere(pony.asWorld().getRandom(), 0.5D);
Supplier<Vec3d> vel = VecHelper.sphere(pony.asWorld().getRandom(), 0.015D);