|
| 1 | +package com.altnoir.mia.block.entity.renderer; |
| 2 | + |
| 3 | +import com.altnoir.mia.block.entity.AbyssSpawnerBlockEntity; |
| 4 | +import com.altnoir.mia.client.render.MiaRenderTypes; |
| 5 | +import com.mojang.blaze3d.vertex.PoseStack; |
| 6 | +import com.mojang.blaze3d.vertex.VertexConsumer; |
| 7 | +import com.mojang.math.Axis; |
| 8 | +import net.minecraft.client.renderer.LightTexture; |
| 9 | +import net.minecraft.client.renderer.MultiBufferSource; |
| 10 | +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; |
| 11 | +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; |
| 12 | +import net.minecraft.util.FastColor; |
| 13 | +import net.minecraft.util.Mth; |
| 14 | +import net.minecraft.util.RandomSource; |
| 15 | +import org.joml.Matrix4f; |
| 16 | +import org.joml.Vector3f; |
| 17 | + |
| 18 | +public class AbyssSpawnerRenderer implements BlockEntityRenderer<AbyssSpawnerBlockEntity> { |
| 19 | + private static final int SPHERE_SEGMENTS = 16; |
| 20 | + private static final int SPHERE_RINGS = 12; |
| 21 | + private static final float BASE_RADIUS = 0.25f; |
| 22 | + |
| 23 | + private static final int CORE_COLOR = FastColor.ARGB32.color(230, 80, 20, 120); |
| 24 | + private static final int OUTER_COLOR = FastColor.ARGB32.color(180, 120, 60, 180); |
| 25 | + |
| 26 | + public AbyssSpawnerRenderer(BlockEntityRendererProvider.Context context) { |
| 27 | + } |
| 28 | + |
| 29 | + @Override |
| 30 | + public void render(AbyssSpawnerBlockEntity blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) { |
| 31 | + var level = blockEntity.getLevel(); |
| 32 | + if (level == null) { |
| 33 | + return; |
| 34 | + } |
| 35 | + |
| 36 | + if (!blockEntity.hasValidPattern()) { |
| 37 | + return; |
| 38 | + } |
| 39 | + |
| 40 | + var spawner = blockEntity.getAbyssSpawner(); |
| 41 | + float time = (level.getGameTime() + partialTick) * 0.05f; |
| 42 | + |
| 43 | + poseStack.pushPose(); |
| 44 | + poseStack.translate(0.5, 0.5, 0.5); |
| 45 | + |
| 46 | + double spin = Mth.lerp(partialTick, spawner.getOSpin(), spawner.getSpin()); |
| 47 | + poseStack.mulPose(Axis.YP.rotationDegrees((float) spin)); |
| 48 | + |
| 49 | + float bob = Mth.sin(time * 0.5f) * 0.05f; |
| 50 | + poseStack.translate(0, bob, 0); |
| 51 | + |
| 52 | + float pulse = 1.0f + Mth.sin(time * 2.0f) * 0.1f; |
| 53 | + float radius = BASE_RADIUS * pulse; |
| 54 | + |
| 55 | + renderDistortedSphere(poseStack, bufferSource, radius, time, packedLight); |
| 56 | + |
| 57 | + poseStack.scale(1.3f, 1.3f, 1.3f); |
| 58 | + renderGlowingSphere(poseStack, bufferSource, radius * 0.8f, time); |
| 59 | + |
| 60 | + poseStack.popPose(); |
| 61 | + } |
| 62 | + |
| 63 | + private void renderDistortedSphere(PoseStack poseStack, MultiBufferSource bufferSource, float radius, float time, int packedLight) { |
| 64 | + VertexConsumer buffer = bufferSource.getBuffer(MiaRenderTypes.ABYSS_ORB); |
| 65 | + Matrix4f matrix = poseStack.last().pose(); |
| 66 | + |
| 67 | + RandomSource random = RandomSource.create(42L); |
| 68 | + |
| 69 | + for (int ring = 0; ring < SPHERE_RINGS; ring++) { |
| 70 | + float theta1 = (float) Math.PI * ring / SPHERE_RINGS; |
| 71 | + float theta2 = (float) Math.PI * (ring + 1) / SPHERE_RINGS; |
| 72 | + |
| 73 | + for (int seg = 0; seg < SPHERE_SEGMENTS; seg++) { |
| 74 | + float phi1 = 2.0f * (float) Math.PI * seg / SPHERE_SEGMENTS; |
| 75 | + float phi2 = 2.0f * (float) Math.PI * (seg + 1) / SPHERE_SEGMENTS; |
| 76 | + |
| 77 | + float distort1 = getDistortion(theta1, phi1, time, random); |
| 78 | + float distort2 = getDistortion(theta2, phi1, time, random); |
| 79 | + float distort3 = getDistortion(theta2, phi2, time, random); |
| 80 | + float distort4 = getDistortion(theta1, phi2, time, random); |
| 81 | + |
| 82 | + Vector3f p1 = spherePoint(theta1, phi1, radius * distort1); |
| 83 | + Vector3f p2 = spherePoint(theta2, phi1, radius * distort2); |
| 84 | + Vector3f p3 = spherePoint(theta2, phi2, radius * distort3); |
| 85 | + Vector3f p4 = spherePoint(theta1, phi2, radius * distort4); |
| 86 | + |
| 87 | + float v1 = (float) ring / SPHERE_RINGS; |
| 88 | + float v2 = (float) (ring + 1) / SPHERE_RINGS; |
| 89 | + |
| 90 | + int color1 = lerpColor(CORE_COLOR, OUTER_COLOR, v1); |
| 91 | + int color2 = lerpColor(CORE_COLOR, OUTER_COLOR, v2); |
| 92 | + |
| 93 | + addVertex(buffer, matrix, p1, color1, packedLight); |
| 94 | + addVertex(buffer, matrix, p2, color2, packedLight); |
| 95 | + addVertex(buffer, matrix, p3, color2, packedLight); |
| 96 | + |
| 97 | + addVertex(buffer, matrix, p1, color1, packedLight); |
| 98 | + addVertex(buffer, matrix, p3, color2, packedLight); |
| 99 | + addVertex(buffer, matrix, p4, color1, packedLight); |
| 100 | + } |
| 101 | + } |
| 102 | + } |
| 103 | + |
| 104 | + private void renderGlowingSphere(PoseStack poseStack, MultiBufferSource bufferSource, float radius, float time) { |
| 105 | + VertexConsumer buffer = bufferSource.getBuffer(MiaRenderTypes.ABYSS_ORB_GLOW); |
| 106 | + Matrix4f matrix = poseStack.last().pose(); |
| 107 | + |
| 108 | + float glowPulse = Mth.sin(time * 3.0f) * 0.5f + 0.5f; |
| 109 | + int glowAlpha = (int) (80 + glowPulse * 100); |
| 110 | + int glowColor = FastColor.ARGB32.color(glowAlpha, 180, 80, 220); |
| 111 | + |
| 112 | + for (int ring = 0; ring < SPHERE_RINGS / 2; ring++) { |
| 113 | + float theta1 = (float) Math.PI * ring / (SPHERE_RINGS / 2); |
| 114 | + float theta2 = (float) Math.PI * (ring + 1) / (SPHERE_RINGS / 2); |
| 115 | + |
| 116 | + for (int seg = 0; seg < SPHERE_SEGMENTS / 2; seg++) { |
| 117 | + float phi1 = 2.0f * (float) Math.PI * seg / (SPHERE_SEGMENTS / 2); |
| 118 | + float phi2 = 2.0f * (float) Math.PI * (seg + 1) / (SPHERE_SEGMENTS / 2); |
| 119 | + |
| 120 | + Vector3f p1 = spherePoint(theta1, phi1, radius); |
| 121 | + Vector3f p2 = spherePoint(theta2, phi1, radius); |
| 122 | + Vector3f p3 = spherePoint(theta2, phi2, radius); |
| 123 | + Vector3f p4 = spherePoint(theta1, phi2, radius); |
| 124 | + |
| 125 | + addVertex(buffer, matrix, p1, glowColor, LightTexture.FULL_BRIGHT); |
| 126 | + addVertex(buffer, matrix, p2, glowColor, LightTexture.FULL_BRIGHT); |
| 127 | + addVertex(buffer, matrix, p3, glowColor, LightTexture.FULL_BRIGHT); |
| 128 | + |
| 129 | + addVertex(buffer, matrix, p1, glowColor, LightTexture.FULL_BRIGHT); |
| 130 | + addVertex(buffer, matrix, p3, glowColor, LightTexture.FULL_BRIGHT); |
| 131 | + addVertex(buffer, matrix, p4, glowColor, LightTexture.FULL_BRIGHT); |
| 132 | + } |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + private float getDistortion(float theta, float phi, float time, RandomSource random) { |
| 137 | + float noise = Mth.sin(theta * 5 + time) * Mth.cos(phi * 3 + time * 0.7f); |
| 138 | + float secondary = Mth.sin(theta * 8 - time * 1.3f) * Mth.sin(phi * 6 + time * 0.5f); |
| 139 | + return 1.0f + noise * 0.15f + secondary * 0.08f; |
| 140 | + } |
| 141 | + |
| 142 | + private Vector3f spherePoint(float theta, float phi, float radius) { |
| 143 | + float x = radius * Mth.sin(theta) * Mth.cos(phi); |
| 144 | + float y = radius * Mth.cos(theta); |
| 145 | + float z = radius * Mth.sin(theta) * Mth.sin(phi); |
| 146 | + return new Vector3f(x, y, z); |
| 147 | + } |
| 148 | + |
| 149 | + private void addVertex(VertexConsumer buffer, Matrix4f matrix, Vector3f pos, int color, int light) { |
| 150 | + buffer.addVertex(matrix, pos.x, pos.y, pos.z) |
| 151 | + .setColor(color) |
| 152 | + .setLight(light); |
| 153 | + } |
| 154 | + |
| 155 | + private int lerpColor(int color1, int color2, float t) { |
| 156 | + int a1 = FastColor.ARGB32.alpha(color1); |
| 157 | + int r1 = FastColor.ARGB32.red(color1); |
| 158 | + int g1 = FastColor.ARGB32.green(color1); |
| 159 | + int b1 = FastColor.ARGB32.blue(color1); |
| 160 | + |
| 161 | + int a2 = FastColor.ARGB32.alpha(color2); |
| 162 | + int r2 = FastColor.ARGB32.red(color2); |
| 163 | + int g2 = FastColor.ARGB32.green(color2); |
| 164 | + int b2 = FastColor.ARGB32.blue(color2); |
| 165 | + |
| 166 | + int a = (int) Mth.lerp(t, a1, a2); |
| 167 | + int r = (int) Mth.lerp(t, r1, r2); |
| 168 | + int g = (int) Mth.lerp(t, g1, g2); |
| 169 | + int b = (int) Mth.lerp(t, b1, b2); |
| 170 | + |
| 171 | + return FastColor.ARGB32.color(a, r, g, b); |
| 172 | + } |
| 173 | + |
| 174 | + @Override |
| 175 | + public boolean shouldRenderOffScreen(AbyssSpawnerBlockEntity blockEntity) { |
| 176 | + return true; |
| 177 | + } |
| 178 | + |
| 179 | + @Override |
| 180 | + public int getViewDistance() { |
| 181 | + return 64; |
| 182 | + } |
| 183 | +} |
0 commit comments