Improve rendering of field of view effects

This commit is contained in:
Sollace 2022-12-23 16:33:05 +01:00
parent 8629cba3e9
commit 0d6c265845
2 changed files with 163 additions and 61 deletions

View file

@ -0,0 +1,128 @@
package com.minelittlepony.unicopia.client.gui;
import org.joml.Matrix4f;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.render.*;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.MathHelper;
public interface GradientUtil {
static void fillVerticalGradient(MatrixStack matrices, int startX, int startY, int stopY, int endX, int endY, int colorStart, int colorStop, int colorEnd, int z) {
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.setShader(GameRenderer::getPositionColorProgram);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
fillVerticalGradient(matrices.peek().getPositionMatrix(), bufferBuilder, startX, startY, stopY, endX, endY, z, colorStart, colorStop, colorEnd);
tessellator.draw();
RenderSystem.disableBlend();
RenderSystem.enableTexture();
}
private static void fillVerticalGradient(Matrix4f matrix, BufferBuilder builder, int startX, int startY, int stopY, int endX, int endY, int z, int colorStart, int colorStop, int colorEnd) {
final float fromA = (colorStart >> 24 & 0xFF) / 255F;
final float fromR = (colorStart >> 16 & 0xFF) / 255F;
final float fromG = (colorStart >> 8 & 0xFF) / 255F;
final float fromB = (colorStart & 0xFF) / 255F;
final float stopA = (colorStop >> 24 & 0xFF) / 255F;
final float stopR = (colorStop >> 16 & 0xFF) / 255F;
final float stopG = (colorStop >> 8 & 0xFF) / 255F;
final float stopB = (colorStop & 0xFF) / 255F;
final float toA = (colorEnd >> 24 & 0xFF) / 255F;
final float toR = (colorEnd >> 16 & 0xFF) / 255F;
final float toG = (colorEnd >> 8 & 0xFF) / 255F;
final float toB = (colorEnd & 0xFF) / 255F;
builder.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR);
builder.vertex(matrix, endX, stopY, z).color(stopR, stopG, stopB, stopA).next();
builder.vertex(matrix, endX, startY, z).color(fromR, fromG, fromB, fromA).next();
builder.vertex(matrix, startX, startY, z).color(fromR, fromG, fromB, fromA).next();
builder.vertex(matrix, startX, stopY, z).color(stopR, stopG, stopB, stopA).next();
builder.vertex(matrix, startX, endY, z).color(toR, toG, toB, toA).next();
builder.vertex(matrix, endX, endY, z).color(stopR, toG, toB, toA).next();
}
static void fillRadialGradient(MatrixStack matrices, int startX, int startY, int endX, int endY, int colorStart, int colorEnd, int z, float radius) {
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.setShader(GameRenderer::getPositionColorProgram);
Tessellator tessellator = Tessellator.getInstance();
if (fillRadials(matrices.peek().getPositionMatrix(), tessellator.getBuffer(), startX, startY, endX, endY, z, colorStart, colorEnd, radius)) {
tessellator.draw();
}
RenderSystem.disableBlend();
RenderSystem.enableTexture();
}
private static boolean fillRadials(Matrix4f matrix, BufferBuilder builder, int startX, int startY, int endX, int endY, int z, int colorStart, int colorEnd, float radius) {
final float fromA = (colorStart >> 24 & 0xFF) / 255F;
final float fromR = (colorStart >> 16 & 0xFF) / 255F;
final float fromG = (colorStart >> 8 & 0xFF) / 255F;
final float fromB = (colorStart & 0xFF) / 255F;
final float toA = (colorEnd >> 24 & 0xFF) / 255F;
final float toR = (colorEnd >> 16 & 0xFF) / 255F;
final float toG = (colorEnd >> 8 & 0xFF) / 255F;
final float toB = (colorEnd & 0xFF) / 255F;
double increment = DrawableUtil.TAU / 30D;
float width = endX - startX;
float height = endY - startY;
float outerRadius = MathHelper.sqrt((width * width) + (height * height)) / 2F;
float innerRadius = outerRadius * (1 - radius);
builder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
for (double angle = 0; angle < DrawableUtil.TAU; angle += increment) {
clampedVertex(builder, matrix, innerRadius, angle + increment, z, startX, endX, startY, endY).color(toR, toG, toB, toA).next();
clampedVertex(builder, matrix, innerRadius, angle, z, startX, endX, startY, endY).color(toR, toG, toB, toA).next();
clampedVertex(builder, matrix, outerRadius, angle, z, startX, endX, startY, endY).color(fromR, fromG, fromB, fromA).next();
clampedVertex(builder, matrix, outerRadius, angle + increment, z, startX, endX, startY, endY).color(fromR, fromG, fromB, fromA).next();
}
return true;
}
static float getX(double radius, double angle) {
return (float)(radius * MathHelper.sin((float)angle));
}
static float getY(double radius, double angle) {
return (float)(radius * MathHelper.cos((float)angle));
}
private static VertexConsumer clampedVertex(BufferBuilder bufferBuilder, Matrix4f model, double radius, double angle, float z, int minX, int maxX, int minY, int maxY) {
float midX = (maxX - minX) / 2F;
float midY = (maxY - minY) / 2F;
float x = midX + getX(radius, angle);
float y = midY + getY(radius, angle);
float xPad = (maxX - minX) / 10F;
float yPad = (maxY - minY) / 20F;
if (x < minX + xPad) {
x = minX;
}
if (x > maxX - xPad) {
x = maxX;
}
if (y < minY + yPad) {
y = minY;
}
if (y > maxY - yPad) {
y = maxY;
}
return bufferBuilder.vertex(model, x, y, z);
}
}

View file

@ -3,7 +3,6 @@ package com.minelittlepony.unicopia.client.gui;
import java.util.List;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.ability.AbilityDispatcher;
import com.minelittlepony.unicopia.ability.AbilitySlot;
@ -224,21 +223,21 @@ public class UHud extends DrawableHelper {
float strength = MathHelper.clamp(pulse + i, 0.3F, 1F);
int alpha1 = (int)(strength * 205) << 24 & -16777216;
int alpha1 = (int)(strength * 205);
int alpha2 = (int)(alpha1 * 0.6F);
fillGradient(matrices, 0, 0, scaledWidth, scaledHeight / 2, 0xFFFFFF | alpha1, 0xFFFFFF | alpha2);
fillGradient(matrices, 0, scaledHeight / 2, scaledWidth, scaledHeight, 0xFFFFFF | alpha2, 0xFFFFFF | alpha1);
int color = 0xFFFFFF;
if (hasEffect) {
matrices.push();
matrices.translate(scaledWidth, 0, 0);
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
fillGradient(matrices, 0, 0, scaledHeight, scaledWidth / 2, 0xFFFFFF | 0, 0xFFFFFF | alpha2);
fillGradient(matrices, 0, scaledWidth / 2, scaledHeight, scaledWidth, 0xFFFFFF | alpha2, 0xFFFFFF | 0);
matrices.pop();
GradientUtil.fillRadialGradient(matrices, 0, 0, scaledWidth, scaledHeight,
color | (alpha1 << 24),
color | (alpha2 << 24),
getZOffset(), 1);
} else {
GradientUtil.fillVerticalGradient(matrices, 0, 0, scaledHeight / 2, scaledWidth, scaledHeight,
color | (alpha1 << 24),
color | (alpha2 << 24),
color | (alpha1 << 24),
getZOffset());
}
}
@ -271,7 +270,12 @@ public class UHud extends DrawableHelper {
}
}
float exhaustion = pony.getMagicalReserves().getExhaustion().getPercentFill();
if (UItems.ALICORN_AMULET.isApplicable(client.player)) {
float radius = (float)pony.getArmour().getTicks(UItems.ALICORN_AMULET) / (5 * ItemTracker.DAYS);
renderVignette(matrices, 0x000000, radius, radius, scaledWidth, scaledHeight);
}
float exhaustion = MathHelper.clamp(pony.getMagicalReserves().getExhaustion().getPercentFill(), 0, 0.6F);
if (exhaustion > 0) {
if (exhaustion > 0.5F && (heartbeatSound == null || heartbeatSound.isDone())) {
@ -282,59 +286,29 @@ public class UHud extends DrawableHelper {
);
}
int color = 0x880000;
float rate = exhaustion > 0.5F ? 2.5F : 7F;
float radius = (1 + (float)Math.sin(client.player.age / rate)) / 2F;
radius = 0.1F + radius * 0.1F;
int alpha1 = (int)(MathHelper.clamp(exhaustion * radius * 2, 0, 1) * 205) << 24 & -16777216;
int alpha2 = 0;
int halfWidth = (int)(scaledWidth * radius);
int halfHeight = (int)(scaledHeight * radius);
fillGradient(matrices, 0, 0, scaledWidth, halfHeight, color | alpha1, color | alpha2);
fillGradient(matrices, 0, scaledHeight - halfHeight, scaledWidth, scaledHeight, color | alpha2, color | alpha1);
matrices.push();
matrices.translate(scaledWidth, 0, 0);
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
fillGradient(matrices, 0, 0, scaledHeight, halfWidth, color | alpha1, color | alpha2);
fillGradient(matrices, 0, scaledWidth - halfWidth, scaledHeight, scaledWidth, color | alpha2, color | alpha1);
matrices.pop();
}
if (UItems.ALICORN_AMULET.isApplicable(client.player)) {
int color = 0x000000;
long timer = pony.getArmour().getTicks(UItems.ALICORN_AMULET);
float radius = (float)timer / (5 * ItemTracker.DAYS);
int alpha1 = (int)(MathHelper.clamp(radius * 2, 0, 1) * 205) << 24 & -16777216;
int alpha2 = 0;
int halfWidth = (int)(scaledWidth * radius);
int halfHeight = (int)(scaledHeight * radius);
fillGradient(matrices, 0, 0, scaledWidth, halfHeight, color | alpha1, color | alpha2);
fillGradient(matrices, 0, scaledHeight - halfHeight, scaledWidth, scaledHeight, color | alpha2, color | alpha1);
matrices.push();
matrices.translate(scaledWidth, 0, 0);
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
fillGradient(matrices, 0, 0, scaledHeight, halfWidth, color | alpha1, color | alpha2);
fillGradient(matrices, 0, scaledWidth - halfWidth, scaledHeight, scaledWidth, color | alpha2, color | alpha1);
matrices.pop();
renderVignette(matrices, 0x880000, exhaustion * radius, 0.1F + radius * 0.3F, scaledWidth, scaledHeight);
}
}
private void renderVignette(MatrixStack matrices, int color, float alpha, float radius, int scaledWidth, int scaledHeight) {
if (radius <= 0) {
return;
}
color &= 0xFFFFFF;
float alpha2 = MathHelper.clamp(radius - 1, 0, 1) * 255;
float alpha1 = Math.max(alpha2, MathHelper.clamp(alpha * 2, 0, 1) * 205);
GradientUtil.fillRadialGradient(matrices, 0, 0, scaledWidth, scaledHeight,
color | (int)alpha1 << 24,
color | (int)alpha2 << 24,
getZOffset(), Math.min(1, radius));
}
public void setMessage(Text message) {
this.message = message;
this.messageTime = 60;