mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-21 20:33:10 +01:00
Improve efficiency and fix some texture glitches when rendering wind and rainbow trail particles
This commit is contained in:
parent
14685d80fa
commit
ed15923f28
6 changed files with 82 additions and 19 deletions
|
@ -3,11 +3,13 @@ package com.minelittlepony.unicopia.client.particle;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.client.render.RenderUtil;
|
import com.minelittlepony.unicopia.client.render.RenderUtil;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
import net.minecraft.client.particle.Particle;
|
import net.minecraft.client.particle.Particle;
|
||||||
import net.minecraft.client.particle.ParticleTextureSheet;
|
import net.minecraft.client.particle.ParticleTextureSheet;
|
||||||
import net.minecraft.client.render.BufferBuilder;
|
import net.minecraft.client.render.BufferBuilder;
|
||||||
import net.minecraft.client.render.BufferRenderer;
|
import net.minecraft.client.render.BufferRenderer;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
import net.minecraft.client.render.Tessellator;
|
import net.minecraft.client.render.Tessellator;
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.render.VertexFormat;
|
import net.minecraft.client.render.VertexFormat;
|
||||||
|
@ -42,6 +44,7 @@ public abstract class AbstractGeometryBasedParticle extends Particle {
|
||||||
|
|
||||||
protected final void renderQuad(MatrixStack matrices, Tessellator te, RenderUtil.Vertex[] corners, float alpha, float tickDelta) {
|
protected final void renderQuad(MatrixStack matrices, Tessellator te, RenderUtil.Vertex[] corners, float alpha, float tickDelta) {
|
||||||
int light = getBrightness(tickDelta);
|
int light = getBrightness(tickDelta);
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionTexColorProgram);
|
||||||
BufferBuilder buffer = te.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
BufferBuilder buffer = te.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
||||||
for (RenderUtil.Vertex corner : corners) {
|
for (RenderUtil.Vertex corner : corners) {
|
||||||
var position = corner.position(matrices.peek().getPositionMatrix());
|
var position = corner.position(matrices.peek().getPositionMatrix());
|
||||||
|
@ -52,11 +55,16 @@ public abstract class AbstractGeometryBasedParticle extends Particle {
|
||||||
|
|
||||||
protected final void renderQuad(Tessellator te, RenderUtil.Vertex[] corners, float alpha, float tickDelta) {
|
protected final void renderQuad(Tessellator te, RenderUtil.Vertex[] corners, float alpha, float tickDelta) {
|
||||||
int light = getBrightness(tickDelta);
|
int light = getBrightness(tickDelta);
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionTexColorProgram);
|
||||||
BufferBuilder buffer = te.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
BufferBuilder buffer = te.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
||||||
|
quad(buffer, corners, alpha, tickDelta, light);
|
||||||
|
BufferRenderer.drawWithGlobalProgram(buffer.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void quad(BufferBuilder buffer, RenderUtil.Vertex[] corners, float alpha, float tickDelta, int light) {
|
||||||
for (RenderUtil.Vertex corner : corners) {
|
for (RenderUtil.Vertex corner : corners) {
|
||||||
buffer.vertex(corner.position().x, corner.position().y, corner.position().z).texture(corner.texture().x, corner.texture().y).color(red, green, blue, alpha).light(light);
|
buffer.vertex(corner.position().x, corner.position().y, corner.position().z).texture(corner.texture().x, corner.texture().y).color(red, green, blue, alpha).light(light);
|
||||||
}
|
}
|
||||||
BufferRenderer.drawWithGlobalProgram(buffer.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void renderQuad(VertexConsumer buffer, Vector3f[] corners, float alpha, float tickDelta) {
|
protected final void renderQuad(VertexConsumer buffer, Vector3f[] corners, float alpha, float tickDelta) {
|
||||||
|
|
|
@ -9,8 +9,14 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.client.render.bezier.BezierSegment;
|
import com.minelittlepony.unicopia.client.render.bezier.BezierSegment;
|
||||||
import com.minelittlepony.unicopia.client.render.bezier.Trail;
|
import com.minelittlepony.unicopia.client.render.bezier.Trail;
|
||||||
import com.minelittlepony.unicopia.particle.TargetBoundParticleEffect;
|
import com.minelittlepony.unicopia.particle.TargetBoundParticleEffect;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
import net.minecraft.client.render.BufferBuilder;
|
||||||
|
import net.minecraft.client.render.BufferRenderer;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
import net.minecraft.client.render.Tessellator;
|
import net.minecraft.client.render.Tessellator;
|
||||||
|
import net.minecraft.client.render.VertexFormat;
|
||||||
|
import net.minecraft.client.render.VertexFormats;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
@ -20,6 +26,8 @@ import net.minecraft.util.math.Vec3d;
|
||||||
public class RainbowTrailParticle extends AbstractBillboardParticle {
|
public class RainbowTrailParticle extends AbstractBillboardParticle {
|
||||||
private static final Identifier TEXTURE = Unicopia.id("textures/particles/rainboom_trail.png");
|
private static final Identifier TEXTURE = Unicopia.id("textures/particles/rainboom_trail.png");
|
||||||
|
|
||||||
|
private final BezierSegment bezier = new BezierSegment();
|
||||||
|
|
||||||
private final Trail trail;
|
private final Trail trail;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -55,18 +63,31 @@ public class RainbowTrailParticle extends AbstractBillboardParticle {
|
||||||
@Override
|
@Override
|
||||||
protected void renderQuads(Tessellator te, float x, float y, float z, float tickDelta) {
|
protected void renderQuads(Tessellator te, float x, float y, float z, float tickDelta) {
|
||||||
float alpha = this.alpha * (1 - (float)age / maxAge);
|
float alpha = this.alpha * (1 - (float)age / maxAge);
|
||||||
|
int light = getBrightness(tickDelta);
|
||||||
|
float scale = getScale(tickDelta);
|
||||||
|
|
||||||
List<Trail.Segment> segments = trail.getSegments();
|
List<Trail.Segment> segments = trail.getSegments();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
BufferBuilder buffer = null;
|
||||||
|
|
||||||
for (int i = 0; i < segments.size() - 1; i++) {
|
for (int i = 0; i < segments.size() - 1; i++) {
|
||||||
BezierSegment corners = segments.get(i).getPlane(segments.get(i + 1));
|
segments.get(i).getPlane(segments.get(i + 1), bezier);
|
||||||
float scale = getScale(tickDelta);
|
|
||||||
|
|
||||||
corners.forEachCorner(corner -> {
|
for (var corner : bezier.corners()) {
|
||||||
corner.position().mul(scale).add(x, y, z);
|
corner.position().mul(scale).add(x, y, z);
|
||||||
});
|
}
|
||||||
|
|
||||||
renderQuad(te, corners.corners(), segments.get(i).getAlpha() * alpha, tickDelta);
|
if (buffer == null) {
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionTexColorProgram);
|
||||||
|
buffer = te.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
quad(buffer, bezier.corners(), segments.get(i).getAlpha() * alpha, tickDelta, light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer != null) {
|
||||||
|
BufferRenderer.drawWithGlobalProgram(buffer.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,15 @@ import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.client.render.bezier.BezierSegment;
|
import com.minelittlepony.unicopia.client.render.bezier.BezierSegment;
|
||||||
import com.minelittlepony.unicopia.client.render.bezier.Trail;
|
import com.minelittlepony.unicopia.client.render.bezier.Trail;
|
||||||
import com.minelittlepony.unicopia.particle.TargetBoundParticleEffect;
|
import com.minelittlepony.unicopia.particle.TargetBoundParticleEffect;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.BufferBuilder;
|
||||||
|
import net.minecraft.client.render.BufferRenderer;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
import net.minecraft.client.render.Tessellator;
|
import net.minecraft.client.render.Tessellator;
|
||||||
|
import net.minecraft.client.render.VertexFormat;
|
||||||
|
import net.minecraft.client.render.VertexFormats;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
@ -19,6 +25,8 @@ import net.minecraft.util.math.Vec3d;
|
||||||
public class WindParticle extends AbstractBillboardParticle {
|
public class WindParticle extends AbstractBillboardParticle {
|
||||||
private static final Identifier TEXTURE = Unicopia.id("textures/particle/wind.png");
|
private static final Identifier TEXTURE = Unicopia.id("textures/particle/wind.png");
|
||||||
|
|
||||||
|
private final BezierSegment bezier = new BezierSegment();
|
||||||
|
|
||||||
private final Trail trail;
|
private final Trail trail;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -60,18 +68,31 @@ public class WindParticle extends AbstractBillboardParticle {
|
||||||
@Override
|
@Override
|
||||||
protected void renderQuads(Tessellator te, float x, float y, float z, float tickDelta) {
|
protected void renderQuads(Tessellator te, float x, float y, float z, float tickDelta) {
|
||||||
float alpha = this.alpha * (1 - (float)age / maxAge);
|
float alpha = this.alpha * (1 - (float)age / maxAge);
|
||||||
|
int light = getBrightness(tickDelta);
|
||||||
|
float scale = getScale(tickDelta);
|
||||||
|
|
||||||
List<Trail.Segment> segments = trail.getSegments();
|
List<Trail.Segment> segments = trail.getSegments();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
BufferBuilder buffer = null;
|
||||||
|
|
||||||
for (int i = 0; i < segments.size() - 1; i++) {
|
for (int i = 0; i < segments.size() - 1; i++) {
|
||||||
BezierSegment corners = segments.get(i).getPlane(segments.get(i + 1));
|
segments.get(i).getPlane(segments.get(i + 1), bezier);
|
||||||
float scale = getScale(tickDelta);
|
|
||||||
|
|
||||||
corners.forEachCorner(corner -> {
|
for (var corner : bezier.corners()) {
|
||||||
corner.position().mul(scale).add(x, y, z);
|
corner.position().mul(scale).add(x, y, z);
|
||||||
});
|
}
|
||||||
|
|
||||||
renderQuad(te, corners.corners(), segments.get(i).getAlpha() * alpha, tickDelta);
|
if (buffer == null) {
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionTexColorProgram);
|
||||||
|
buffer = te.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
quad(buffer, bezier.corners(), segments.get(i).getAlpha() * alpha, tickDelta, light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer != null) {
|
||||||
|
BufferRenderer.drawWithGlobalProgram(buffer.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,15 @@ public class RenderUtil {
|
||||||
this(new Vector3f(x, y, z), new Vector3f(u, v, 1));
|
this(new Vector3f(x, y, z), new Vector3f(u, v, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vertex() {
|
||||||
|
this(new Vector3f(), new Vector3f());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float x, float y, float z, float u, float v) {
|
||||||
|
position.set(x, y, z);
|
||||||
|
texture.set(u, v, 1);
|
||||||
|
}
|
||||||
|
|
||||||
public Vector4f position(Matrix4f mat) {
|
public Vector4f position(Matrix4f mat) {
|
||||||
return mat.transform(TEMP_VECTOR.set(position, 1));
|
return mat.transform(TEMP_VECTOR.set(position, 1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,16 +9,20 @@ import com.minelittlepony.unicopia.client.render.RenderUtil;
|
||||||
public record BezierSegment(
|
public record BezierSegment(
|
||||||
RenderUtil.Vertex[] corners
|
RenderUtil.Vertex[] corners
|
||||||
) {
|
) {
|
||||||
|
public BezierSegment() {
|
||||||
public BezierSegment(Vector3f from, Vector3f to, float height) {
|
|
||||||
this(new RenderUtil.Vertex[] {
|
this(new RenderUtil.Vertex[] {
|
||||||
new RenderUtil.Vertex(from.x, from.y - height/2F, from.z, 0, 0), // bottom left
|
new RenderUtil.Vertex(), new RenderUtil.Vertex(),
|
||||||
new RenderUtil.Vertex(from.x, from.y + height/2F, from.z, 1, 0), // top left
|
new RenderUtil.Vertex(), new RenderUtil.Vertex()
|
||||||
new RenderUtil.Vertex(to.x, to.y + height/2F, to.z, 1, 1), // top right
|
|
||||||
new RenderUtil.Vertex(to.x, to.y - height/2F, to.z, 0, 1) // bottom right
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void set(Vector3f from, Vector3f to, float height) {
|
||||||
|
corners[0].set(from.x, from.y - height/2F, from.z, 0, 0); // bottom left
|
||||||
|
corners[1].set(from.x, from.y + height/2F, from.z, 1, 0); // top left
|
||||||
|
corners[2].set(to.x, to.y + height/2F, to.z, 1, 1); // top right
|
||||||
|
corners[3].set(to.x, to.y - height/2F, to.z, 0, 1); // bottom right
|
||||||
|
}
|
||||||
|
|
||||||
public void forEachCorner(Consumer<RenderUtil.Vertex> transformer) {
|
public void forEachCorner(Consumer<RenderUtil.Vertex> transformer) {
|
||||||
for (var corner : corners) {
|
for (var corner : corners) {
|
||||||
transformer.accept(corner);
|
transformer.accept(corner);
|
||||||
|
|
|
@ -63,8 +63,8 @@ public class Trail {
|
||||||
return segments.indexOf(this) < segments.size() - 1 && age++ >= maxAge;
|
return segments.indexOf(this) < segments.size() - 1 && age++ >= maxAge;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BezierSegment getPlane(Segment to) {
|
public void getPlane(Segment to, BezierSegment segment) {
|
||||||
return new BezierSegment(offset, to.offset, height);
|
segment.set(offset, to.offset, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue