mirror of
https://github.com/JonasunderscoreJones/nicer-skies.git
synced 2025-10-22 19:29:18 +02:00
new: nebulas and improve stars
This commit is contained in:
parent
3bd84f2af6
commit
498d17818d
11 changed files with 449 additions and 70 deletions
|
@ -7,3 +7,6 @@ For setup instructions please see the [fabric wiki page](https://fabricmc.net/wi
|
|||
## License
|
||||
|
||||
This template is available under the CC0 license. Feel free to learn from it and incorporate it in your own projects.
|
||||
|
||||
## thanks
|
||||
thanks to mr grlockengspiel for sqrt() tip
|
|
@ -0,0 +1,97 @@
|
|||
package codes.ztereohype.example;
|
||||
|
||||
import codes.ztereohype.example.sky.Star;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.levelgen.synth.ImprovedNoise;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public class StarUpdateBenchmark {
|
||||
public ArrayList<Star> starList = new ArrayList<>();
|
||||
public BufferBuilder starBufferBuilder = Tesselator.getInstance().getBuilder();
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
starBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
RandomSource randomSource = RandomSource.create(123L);
|
||||
ImprovedNoise noise = new ImprovedNoise(randomSource);
|
||||
starList.clear();
|
||||
|
||||
for (int i = 0; i < 1700; ++i) {
|
||||
// -1..1
|
||||
float randX = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
float randY = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
float randZ = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
|
||||
float twinkleSpeed = 0.03f + randomSource.nextFloat() * 0.04f;
|
||||
|
||||
double[] starDerivatives = new double[] {0,0,0};
|
||||
float starValue = (float) noise.noiseWithDerivative(randX*3, randY*3, randZ*3, starDerivatives) * 0.5f + 0.5f;
|
||||
|
||||
float maxDerivative = (float) Math.max(Math.abs(starDerivatives[0]), Math.max(Math.abs(starDerivatives[1]), Math.abs(starDerivatives[2]))); //kinda normal distr around 1?
|
||||
float temperature = maxDerivative * 8000;
|
||||
|
||||
// 0.15..0.25 ???
|
||||
float starRadius = 0.15F + randomSource.nextFloat() * 0.15F;
|
||||
starRadius *= starValue;
|
||||
|
||||
float squaredDistance = randX * randX + randY * randY + randZ * randZ;
|
||||
|
||||
if (squaredDistance < 1.0 && squaredDistance > 0.01 && starRadius > 0.13) {
|
||||
starList.add(new Star(randX, randY, randZ, starRadius, temperature, twinkleSpeed));
|
||||
} else --i;
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(iterations = 1)
|
||||
@Measurement(iterations = 15, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@Benchmark
|
||||
public void updateStars1() {
|
||||
starBufferBuilder.clear();
|
||||
for (Star star : starList) {
|
||||
star.tick(134);
|
||||
star.setVertices(starBufferBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(iterations = 1)
|
||||
@Measurement(iterations = 15, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@Benchmark
|
||||
public void updateStars2() {
|
||||
starBufferBuilder.clear();
|
||||
starList.stream().parallel().forEach(star -> star.tick(134));
|
||||
for (Star star : starList) {
|
||||
star.setVertices(starBufferBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(iterations = 1)
|
||||
@Measurement(iterations = 15, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@Benchmark
|
||||
public void updateStars3() {
|
||||
starBufferBuilder.clear();
|
||||
for (Star star : starList) {
|
||||
star.tick(134);
|
||||
// star.setVerticesTwo(starBufferBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@Warmup(iterations = 1)
|
||||
@Measurement(iterations = 15, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@Benchmark
|
||||
public void updateStars4() {
|
||||
starBufferBuilder.clear();
|
||||
starList.stream().parallel().forEach(star -> star.tick(134));
|
||||
for (Star star : starList) {
|
||||
// star.setVerticesTwo(starBufferBuilder);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(LightTexture.class)
|
||||
public class MixinLightTexutre {
|
||||
public abstract class MixinLightTexutre {
|
||||
@Inject(
|
||||
method = "updateLightTexture",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/math/Vector3f;clamp(FF)V", shift = At.Shift.BEFORE, ordinal = 2),
|
||||
|
|
|
@ -1,29 +1,110 @@
|
|||
package codes.ztereohype.example.mixin;
|
||||
|
||||
import codes.ztereohype.example.sky.StarManager;
|
||||
import com.mojang.blaze3d.vertex.VertexBuffer;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public class MixinStarRendering {
|
||||
public abstract class MixinStarRendering {
|
||||
@Shadow private VertexBuffer starBuffer;
|
||||
@Shadow private int ticks;
|
||||
@Shadow private ClientLevel level;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "createStars", cancellable = true)
|
||||
private void generateStars(CallbackInfo ci) {
|
||||
StarManager.generateStarList();
|
||||
StarManager.generateSky();
|
||||
starBuffer = new VertexBuffer();
|
||||
StarManager.updateStars(0, starBuffer);
|
||||
StarManager.updateStars(ticks, starBuffer);
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "tick")
|
||||
private void tickStars(CallbackInfo ci) {
|
||||
if (this.level.getStarBrightness(0) < 0.0F) return;
|
||||
StarManager.updateStars(ticks, starBuffer);
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
method = "renderSky",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/VertexBuffer;drawWithShader(Lcom/mojang/math/Matrix4f;Lcom/mojang/math/Matrix4f;Lnet/minecraft/client/renderer/ShaderInstance;)V", ordinal = 1),
|
||||
index = 2
|
||||
)
|
||||
private ShaderInstance injectStarColour(ShaderInstance shaderInstance) {
|
||||
return GameRenderer.getPositionColorShader();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "renderSky",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;disableTexture()V", ordinal = 2, shift = At.Shift.AFTER),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void drawNebulas(PoseStack poseStack, Matrix4f projectionMatrix, float partialTick, Camera camera, boolean bl, Runnable skyFogSetup, CallbackInfo ci, FogType fogType, Vec3 vec3, float f, float g, float h, BufferBuilder bufferBuilder, ShaderInstance shaderInstance, float[] fs, float i, Matrix4f matrix4f2, float k, int r, int s, int m, float t, float o, float p, float q) {
|
||||
Matrix4f matrix = matrix4f2;
|
||||
// matrix.multiply(projectionMatrix);
|
||||
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
RenderSystem.setShaderTexture(0, StarManager.skyTexture.getId());
|
||||
|
||||
BufferBuilder leBufferBuilder = Tesselator.getInstance().getBuilder();
|
||||
leBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
|
||||
|
||||
// +z face
|
||||
leBufferBuilder.vertex(matrix, -1F, -1F, 1F).uv(0.25f, 0.25f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, -1F, 1F, 1F).uv(0.25f, 0.5f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, 1F, 1F).uv(0.5f, 0.5f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, -1F, 1F).uv(0.5f, 0.25f).endVertex();
|
||||
|
||||
// -z face
|
||||
leBufferBuilder.vertex(matrix, -1F, -1F, -1F).uv(0.75f, 0.25f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, -1F, -1F).uv(1f, 0.25f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, 1F, -1F).uv(1f, 0.5f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, -1F, 1F, -1F).uv(0.75f, 0.5f).endVertex();
|
||||
|
||||
// bottom face
|
||||
leBufferBuilder.vertex(matrix, -1F, -1F, -1F).uv(0.5f, 0.5f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, -1F, -1F, 1F).uv(0.5f, 0.75f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, -1F, 1F).uv(0.75f, 0.75f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, -1F, -1F).uv(0.75f, 0.5f).endVertex();
|
||||
|
||||
// leBufferBuilder.vertex(matrix, -1F, -1F, -1F).uv(0f, 0f).endVertex();
|
||||
// leBufferBuilder.vertex(matrix, -1F, -1F, 1F).uv(0f, 1f).endVertex();
|
||||
// leBufferBuilder.vertex(matrix, 1F, -1F, 1F).uv(1f, 1f).endVertex();
|
||||
// leBufferBuilder.vertex(matrix, 1F, -1F, -1F).uv(1f, 0f).endVertex();
|
||||
|
||||
// top face
|
||||
leBufferBuilder.vertex(matrix, -1F, 1F, -1F).uv(0.5f, 0f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, 1F, -1F).uv(0.75f, 0f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, 1F, 1F).uv(0.75f, 0.25f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, -1F, 1F, 1F).uv(0.5f, 0.25f).endVertex();
|
||||
|
||||
// +x face
|
||||
leBufferBuilder.vertex(matrix, 1F, -1F, -1F).uv(0.5f, 0.25f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, -1F, 1F).uv(0.75f, 0.25f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, 1F, 1F).uv(0.75f, 0.5f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, 1F, 1F, -1F).uv(0.5f, 0.5f).endVertex();
|
||||
|
||||
// -x face
|
||||
leBufferBuilder.vertex(matrix, -1F, -1F, -1F).uv(0f, 0.25f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, -1F, 1F, -1F).uv(0f, 0.5f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, -1F, 1F, 1F).uv(0.25f, 0.5f).endVertex();
|
||||
leBufferBuilder.vertex(matrix, -1F, -1F, 1F).uv(0.25f, 0.25f).endVertex();
|
||||
|
||||
BufferUploader.drawWithShader(leBufferBuilder.end());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package codes.ztereohype.example.mixin;
|
||||
package codes.ztereohype.example.mixin.debug;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
|
@ -1,4 +1,4 @@
|
|||
package codes.ztereohype.example.mixin;
|
||||
package codes.ztereohype.example.mixin.debug;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
@ -1,4 +1,4 @@
|
|||
package codes.ztereohype.example.mixin;
|
||||
package codes.ztereohype.example.mixin.debug;
|
||||
|
||||
import codes.ztereohype.example.ExampleMod;
|
||||
import codes.ztereohype.example.sky.StarManager;
|
||||
|
@ -15,13 +15,12 @@ public class MixinKeyboardHandler {
|
|||
@Inject(at = @At("HEAD"), method = "keyPress")
|
||||
private void printKey(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) {
|
||||
if (key == 92) {
|
||||
StarManager.generateStarList();
|
||||
long time = System.currentTimeMillis();
|
||||
if (time - cooldown > 200) {
|
||||
StarManager.generateSky();
|
||||
ExampleMod.toggle = !ExampleMod.toggle;
|
||||
cooldown = time;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,67 +8,147 @@ public class Star {
|
|||
private final float yCoord;
|
||||
private final float zCoord;
|
||||
|
||||
private final float sinPolarAngle;
|
||||
private final float cosPolarAngle;
|
||||
private final float longitudeSin;
|
||||
private final float longitudeCos;
|
||||
|
||||
private final float projSin;
|
||||
private final float projCos;
|
||||
private final float latitudeSin;
|
||||
private final float latitudeCos;
|
||||
|
||||
private final float twinkleSpeed;
|
||||
private final float minRadius;
|
||||
private final float maxRadius;
|
||||
|
||||
private final int r;
|
||||
private final int g;
|
||||
private final int b;
|
||||
|
||||
private float currentAngle;
|
||||
private float currentRadius;
|
||||
|
||||
public Star(float randX, float randY, float randZ, float radius, float twinkleSpeed) {
|
||||
public Star(float randX, float randY, float randZ, float size, float temperature, float twinkleSpeed) {
|
||||
this.r = getRedFromKelvin(temperature);
|
||||
this.g = getGreenFromKelvin(temperature);
|
||||
this.b = getBlueFromKelvin(temperature);
|
||||
|
||||
float invsqrtDistance = Mth.fastInvSqrt(randX * randX + randY * randY + randZ * randZ);
|
||||
this.xCoord = randX * invsqrtDistance * 100.0F;
|
||||
this.yCoord = randY * invsqrtDistance * 100.0F;
|
||||
this.zCoord = randZ * invsqrtDistance * 100.0F;
|
||||
|
||||
double polarAngle = Math.atan2(randX, randZ);
|
||||
this.sinPolarAngle = (float) Math.sin(polarAngle);
|
||||
this.cosPolarAngle = (float) Math.cos(polarAngle);
|
||||
this.longitudeSin = (float) Math.sin(polarAngle);
|
||||
this.longitudeCos = (float) Math.cos(polarAngle);
|
||||
|
||||
// magic projection fuckery??
|
||||
double proj = Math.atan2(Math.sqrt(randX * randX + randZ * randZ), randY);
|
||||
this.projSin = (float) Math.sin(proj);
|
||||
this.projCos = (float) Math.cos(proj);
|
||||
this.latitudeSin = (float) Math.sin(proj);
|
||||
this.latitudeCos = (float) Math.cos(proj);
|
||||
|
||||
this.twinkleSpeed = twinkleSpeed;
|
||||
this.minRadius = radius - 0.15f;
|
||||
this.maxRadius = radius + 0.15f;
|
||||
this.currentRadius = radius;
|
||||
this.currentAngle = twinkleSpeed; //just so they dont all start straight
|
||||
this.minRadius = size - 0.13f;
|
||||
this.maxRadius = size + 0.13f;
|
||||
this.currentRadius = size;
|
||||
this.currentAngle = (float) ((twinkleSpeed - 0.03) * 157); // random angle from 0 to 2π
|
||||
}
|
||||
|
||||
public void tick(int ticks) {
|
||||
currentAngle += 0.07f * twinkleSpeed;
|
||||
currentRadius = Mth.lerp(Mth.sin(ticks * twinkleSpeed) * 0.5f + 0.5f, minRadius, maxRadius);
|
||||
currentRadius = Mth.lerp(Mth.sin(ticks * twinkleSpeed), minRadius, maxRadius);
|
||||
}
|
||||
|
||||
//return 4*3 coords for 4 vertices
|
||||
// public void setVertices(BufferBuilder bufferBuilder) {
|
||||
// float cosRot = Mth.cos(currentAngle);
|
||||
// float sinRot = Mth.sin(currentAngle);
|
||||
//
|
||||
// for (int v = 0; v < 4; ++v) {
|
||||
// // shift the vector to the 4 corners:
|
||||
// // vec 0, 1 --> -rad; vec 2, 3 --> +rad
|
||||
// float xShift = ((v & 2) - 1) * currentRadius;
|
||||
// // vec 1, 2 --> +rad; vec 3, 0 --> -rad
|
||||
// float yShift = (((v + 1) & 2) - 1) * currentRadius;
|
||||
//
|
||||
// float unprojectedVerticalOffset = xShift * cosRot - yShift * sinRot;
|
||||
// float unprojectedHorizontalOffset = yShift * cosRot + xShift * sinRot;
|
||||
// float latitudeCorrectedUnprojectedVerticalOffset = -unprojectedVerticalOffset * latitudeCos; // max negative +2pi, max positive -2pi
|
||||
//
|
||||
// float yOffset = unprojectedVerticalOffset * latitudeSin; // at ±pi should be max, squished at poles
|
||||
// float xOffset = latitudeCorrectedUnprojectedVerticalOffset * longitudeSin - unprojectedHorizontalOffset * longitudeCos;
|
||||
// float zOffset = unprojectedHorizontalOffset * longitudeSin + latitudeCorrectedUnprojectedVerticalOffset * longitudeCos;
|
||||
//
|
||||
// bufferBuilder.vertex(xCoord + xOffset, yCoord + yOffset, zCoord + zOffset)
|
||||
// .color(r, g, b, 255)
|
||||
// .endVertex();
|
||||
// }
|
||||
// }
|
||||
|
||||
public void setVertices(BufferBuilder bufferBuilder) {
|
||||
float cosRot = Mth.cos(currentAngle);
|
||||
float sinRot = Mth.sin(currentAngle);
|
||||
float horizontalVertexDistance = currentRadius * Mth.cos(currentAngle);
|
||||
float verticalVertexDistance = currentRadius * Mth.sin(currentAngle);
|
||||
|
||||
for (int v = 0; v < 4; ++v) {
|
||||
// shift the vector to the 4 corners:
|
||||
// vec 0, 1 --> -rad; vec 2, 3 --> +rad
|
||||
float xShift = ((v & 2) - 1) * currentRadius;
|
||||
// vec 1, 2 --> +rad; vec 3, 0 --> -rad
|
||||
float yShift = (((v + 1) & 2) - 1) * currentRadius;
|
||||
float firstVertexDistance = -horizontalVertexDistance + verticalVertexDistance;
|
||||
float secondVertexDistance = -horizontalVertexDistance - verticalVertexDistance;
|
||||
float thirdVertexDistance = horizontalVertexDistance - verticalVertexDistance;
|
||||
float fourthVertexDistance = horizontalVertexDistance + verticalVertexDistance;
|
||||
|
||||
// magic projection fuckery to turn the shift into an offset applying rotation and polar bs
|
||||
float aa = xShift * cosRot - yShift * sinRot;
|
||||
float ab = yShift * cosRot + xShift * sinRot;
|
||||
float ae = -aa * projCos;
|
||||
float yOffset = aa * projSin;
|
||||
float xOffset = ae * sinPolarAngle - ab * cosPolarAngle;
|
||||
float zOffset = ab * sinPolarAngle + ae * cosPolarAngle;
|
||||
float ae1 = thirdVertexDistance * latitudeCos;
|
||||
float ae2 = fourthVertexDistance * latitudeCos;
|
||||
float ae3 = firstVertexDistance * latitudeCos;
|
||||
float ae4 = secondVertexDistance * latitudeCos;
|
||||
|
||||
bufferBuilder.vertex(xCoord + xOffset, yCoord + yOffset, zCoord + zOffset).endVertex();
|
||||
bufferBuilder.vertex(xCoord + ae1 * longitudeSin - secondVertexDistance * longitudeCos, yCoord + firstVertexDistance * latitudeSin, zCoord + secondVertexDistance * longitudeSin + ae1 * longitudeCos)
|
||||
.color(r, g, b, 255)
|
||||
.endVertex();
|
||||
bufferBuilder.vertex(xCoord + ae2 * longitudeSin - thirdVertexDistance * longitudeCos, yCoord + secondVertexDistance * latitudeSin, zCoord + thirdVertexDistance * longitudeSin + ae2 * longitudeCos)
|
||||
.color(r, g, b, 255)
|
||||
.endVertex();
|
||||
bufferBuilder.vertex(xCoord + ae3 * longitudeSin - fourthVertexDistance * longitudeCos, yCoord + thirdVertexDistance * latitudeSin, zCoord + fourthVertexDistance * longitudeSin + ae3 * longitudeCos)
|
||||
.color(r, g, b, 255)
|
||||
.endVertex();
|
||||
bufferBuilder.vertex(xCoord + ae4 * longitudeSin - firstVertexDistance * longitudeCos, yCoord + fourthVertexDistance * latitudeSin, zCoord + firstVertexDistance * longitudeSin + ae4 * longitudeCos)
|
||||
.color(r, g, b, 255)
|
||||
.endVertex();
|
||||
}
|
||||
|
||||
// source: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
|
||||
public static int getRedFromKelvin(double kelvins) {
|
||||
kelvins /= 100;
|
||||
|
||||
if (kelvins <= 66) {
|
||||
return 255;
|
||||
|
||||
} else {
|
||||
double red = 329.698727446D * Math.pow(kelvins - 60, -0.1332047592D);
|
||||
return Mth.clamp((int)red, 0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getGreenFromKelvin(double kelvins) {
|
||||
kelvins /= 100;
|
||||
|
||||
double green;
|
||||
if (kelvins <= 66) {
|
||||
green = 99.4708025861D * Math.log(kelvins) - 161.1195681661D;
|
||||
|
||||
} else {
|
||||
green = 288.1221695283D * Math.pow(kelvins - 60, -0.0755148492D);
|
||||
}
|
||||
|
||||
return Mth.clamp((int)green, 0, 255);
|
||||
}
|
||||
|
||||
public static int getBlueFromKelvin(double kelvins) {
|
||||
kelvins /= 100;
|
||||
|
||||
if (kelvins >= 66) {
|
||||
return 255;
|
||||
|
||||
} else if (kelvins <= 19){
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
double blue = 138.5177312231D * Math.log(kelvins - 60) - 305.0447927307D;
|
||||
// double blue = 138.5177312231D * Math.log(kelvins - 60) - 205.0447927307D;
|
||||
return Mth.clamp((int)blue, 0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +1,173 @@
|
|||
package codes.ztereohype.example.sky;
|
||||
|
||||
import codes.ztereohype.example.ExampleMod;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import net.minecraft.util.FastColor;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.levelgen.synth.ImprovedNoise;
|
||||
import net.minecraft.world.level.levelgen.synth.PerlinNoise;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
//todo: redo all of the star rendering to be able to use the same vertex buffer object with a uniform or with the posestack
|
||||
public class StarManager {
|
||||
private static final BufferBuilder starBufferBuilder = Tesselator.getInstance().getBuilder();
|
||||
|
||||
private static final int STAR_ATTEMPTS = 1500;
|
||||
private static final int STARS = 1500;
|
||||
private static final int NEBULAS_RESOLUTION = 256;
|
||||
private static final float SCALING_FACTOR = 1f;
|
||||
public static ArrayList<Star> starList = new ArrayList<>();
|
||||
|
||||
//todo: add a noise for patterns and star size
|
||||
public static void generateStarList() {
|
||||
// ez optimisation: use less vram by using only height 3 (requires pain uv mapping)
|
||||
public static final DynamicTexture skyTexture = new DynamicTexture(NEBULAS_RESOLUTION * 4, NEBULAS_RESOLUTION * 4, false);
|
||||
|
||||
public static void generateNebulaTextures(RandomSource randomSource) {
|
||||
PerlinNoise perlinNoise = PerlinNoise.create(randomSource, IntStream.of(1, 2, 3, 4, 5));
|
||||
ImprovedNoise distortionNoise = new ImprovedNoise(randomSource);
|
||||
|
||||
// top face
|
||||
NativeImage skyNativeTex = skyTexture.getPixels();
|
||||
for (int texY = 0; texY < NEBULAS_RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < NEBULAS_RESOLUTION; texX++) {
|
||||
float x = (texX / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
float y = 1;
|
||||
float z = (texY / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + 2 * NEBULAS_RESOLUTION, texY, getFunnyColour(x, y, z, perlinNoise, distortionNoise));
|
||||
}
|
||||
}
|
||||
|
||||
// bottom face
|
||||
for (int texY = 0; texY < NEBULAS_RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < NEBULAS_RESOLUTION; texX++) {
|
||||
float x = (texX / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
float y = -1;
|
||||
float z = (texY / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + 2 * NEBULAS_RESOLUTION, texY + 2 * NEBULAS_RESOLUTION, getFunnyColour(x, y, z, perlinNoise, distortionNoise));
|
||||
}
|
||||
}
|
||||
|
||||
// -x face
|
||||
for (int texY = 0; texY < NEBULAS_RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < NEBULAS_RESOLUTION; texX++) {
|
||||
float x = -1;
|
||||
float y = (texY / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
float z = (texX / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX, texY + NEBULAS_RESOLUTION, getFunnyColour(x, y, z, perlinNoise, distortionNoise));
|
||||
}
|
||||
}
|
||||
|
||||
// +x face
|
||||
for (int texY = 0; texY < NEBULAS_RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < NEBULAS_RESOLUTION; texX++) {
|
||||
float x = 1;
|
||||
float y = (texY / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
float z = (texX / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + 2 * NEBULAS_RESOLUTION, texY + NEBULAS_RESOLUTION, getFunnyColour(x, y, z, perlinNoise, distortionNoise));
|
||||
}
|
||||
}
|
||||
|
||||
// +z face
|
||||
for (int texY = 0; texY < NEBULAS_RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < NEBULAS_RESOLUTION; texX++) {
|
||||
float x = (texX / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
float y = (texY / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
float z = 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + NEBULAS_RESOLUTION, texY + NEBULAS_RESOLUTION, getFunnyColour(x, y, z, perlinNoise, distortionNoise));
|
||||
}
|
||||
}
|
||||
|
||||
// -z face
|
||||
for (int texY = 0; texY < NEBULAS_RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < NEBULAS_RESOLUTION; texX++) {
|
||||
float x = (texX / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
float y = (texY / (float) NEBULAS_RESOLUTION) * 2 - 1;
|
||||
float z = -1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + 3 * NEBULAS_RESOLUTION, texY + NEBULAS_RESOLUTION, getFunnyColour(x, y, z, perlinNoise, distortionNoise));
|
||||
}
|
||||
}
|
||||
|
||||
skyTexture.upload();
|
||||
}
|
||||
|
||||
public static int getFunnyColour(float x, float y, float z, PerlinNoise noise, ImprovedNoise distortionNoise) {
|
||||
float invDistance = Mth.fastInvSqrt(x * x + y * y + z * z);
|
||||
|
||||
//divide by distance to get projection on sphere (shorten the vector)
|
||||
x *= invDistance;
|
||||
y *= invDistance;
|
||||
z *= invDistance;
|
||||
|
||||
float offset = (float) noise.getValue(x * SCALING_FACTOR * 3, y * SCALING_FACTOR * 3, z * SCALING_FACTOR * 3);
|
||||
|
||||
x += offset/6f;
|
||||
y += offset/6f;
|
||||
z += offset/6f;
|
||||
|
||||
// 0..1
|
||||
double noiseValue = noise.getValue(x * SCALING_FACTOR, y * SCALING_FACTOR, z * SCALING_FACTOR) * 0.5 + 0.5;
|
||||
// float temperature = (float) (Math.max(Math.max(derivates[0], derivates[1]), derivates[2]) * 2500 + 3500);
|
||||
|
||||
|
||||
|
||||
int alpha = Mth.clamp((int) (noiseValue * 255) - 128, 0, 128);
|
||||
|
||||
// 0..1
|
||||
double colourLerp = (alpha/128.0)*2;
|
||||
|
||||
int red = (int) (Mth.lerp(colourLerp, 1.0, 0.2) * 255);
|
||||
int green = (int) (Mth.lerp(colourLerp, 0.7, 0.7) * 255);
|
||||
int blue = (int) (Mth.lerp(colourLerp, 0.2, 0.9) * 255);
|
||||
|
||||
return FastColor.ARGB32.color(alpha, red, green, blue);
|
||||
// Star.getBlueFromKelvin(noiseLerp*7000),
|
||||
// Star.getGreenFromKelvin(noiseLerp*7000),
|
||||
// Star.getRedFromKelvin(noiseLerp*7000));
|
||||
// blue, green, red);
|
||||
}
|
||||
|
||||
public static void generateSky() {
|
||||
RandomSource randomSource = RandomSource.create(123L);
|
||||
|
||||
generateNebulaTextures(randomSource);
|
||||
|
||||
ImprovedNoise noise = new ImprovedNoise(randomSource);
|
||||
|
||||
starList.clear();
|
||||
|
||||
for (int i = 0; i < STAR_ATTEMPTS; ++i) {
|
||||
// -1..1
|
||||
for (int i = 0; i < STARS; ++i) {
|
||||
float randX = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
float randY = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
float randZ = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
|
||||
// 0.15..0.25 ???
|
||||
float starRadius = 0.15F + randomSource.nextFloat() * 0.1F;
|
||||
float twinkleSpeed = 0.03f + randomSource.nextFloat() * 0.04f;
|
||||
|
||||
double squaredDistance = randX * randX + randY * randY + randZ * randZ;
|
||||
if (squaredDistance < 1.0 && squaredDistance > 0.01) {
|
||||
starList.add(new Star(randX, randY, randZ, starRadius, 0.03f + randomSource.nextFloat() * 0.04f));
|
||||
}
|
||||
float temperature = (randomSource.nextFloat() * 10f + 10f) * 600;
|
||||
|
||||
float starRadius = 0.20F + randomSource.nextFloat() * 0.15F;
|
||||
float starValue = (float) noise.noise(randX*2.5f, randY*2.5f, randZ*2.5f) * 0.55f + 0.45f;
|
||||
starRadius *= starValue;
|
||||
|
||||
float squaredDistance = randX * randX + randY * randY + randZ * randZ;
|
||||
|
||||
if (squaredDistance < 1.0 && squaredDistance > 0.01 && starRadius > 0.13) {
|
||||
starList.add(new Star(randX, randY, randZ, starRadius, temperature, twinkleSpeed));
|
||||
} else --i;
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateStars(int ticks, VertexBuffer starBuffer) {
|
||||
if (!ExampleMod.toggle) return;
|
||||
starBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
|
||||
|
||||
starBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
for (Star star : starList) {
|
||||
star.tick(ticks);
|
||||
|
@ -48,3 +179,4 @@ public class StarManager {
|
|||
VertexBuffer.unbind();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [],
|
||||
"client": [
|
||||
"MixinKeyboardHandler",
|
||||
"debug.MixinKeyboardHandler",
|
||||
"MixinStarRendering",
|
||||
"LightTextureInvoker",
|
||||
"MixinDebug",
|
||||
"debug.LightTextureInvoker",
|
||||
"debug.MixinDebug",
|
||||
"MixinLightTexutre"
|
||||
],
|
||||
"server": [],
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
package codes.ztereohype.example;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PerformanceTest {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue