Add stars and a simple skybox (#1043)

* really bad and inefficient star code i think

* add stars that dont work during the day but look cool

* remove galaxy shape and replace it with a simple sphere

* add broken background

* make stars affected by fog

* make the stars additive

* remove commented code in shaders

* remove unused variables in the shader

* make the stars spin

* make stars not have bloom

* fix formatting

* temp changes

* fix formatting (still temp changes)

* switch to cubyz random numbers

* multiply star matrix in cpu instead of gpu

* changed star to be twice as big, not affect by resolution as much, and also be loaded from a texture

* remove trailing whitespaces

* remove unused constants

* simplify the code by removing a log and power

* optimizing the stars

* remove debug code

* make stars triangles instead of points

* simplify the math more

* give star ssbo unique id

* fix formatting issues

* make array multiline

* fix formatting

* remove files i accidentally added

* remove random obj file

* fix some issues

* use square distance

* fix formatting

* small change

* fix some stuff

* fix other things

* comp error

* more stuff

* fix some stuff with the stars

* test

* fix formatting

* fix more formatting

* test 2

* fixes

* changes

* changes

* fix formatting

* fixes

* remove patch
This commit is contained in:
OneAvargeCoder193 2025-04-27 14:29:19 -04:00 committed by GitHub
parent a2911710a6
commit 9181b31a6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 229 additions and 4 deletions

View File

@ -0,0 +1,14 @@
#version 430
in vec3 pos;
in flat vec3 centerPos;
in flat vec3 color;
layout (location = 0, index = 0) out vec4 fragColor;
void main() {
if (dot(pos - centerPos, pos - centerPos) > 1.0/12.0)
discard;
fragColor = vec4(color, 1);
}

View File

@ -0,0 +1,29 @@
#version 430
struct star {
vec4 vertexPositions[3];
vec3 pos;
float padding1;
vec3 color;
float padding2;
};
layout (std430, binding = 12) buffer _starBuffer {
star starData[];
};
uniform mat4 mvp;
uniform float starOpacity;
out vec3 pos;
out flat vec3 centerPos;
out flat vec3 color;
void main() {
gl_Position = mvp*vec4(starData[gl_VertexID/3].vertexPositions[gl_VertexID%3].xyz, 1);
pos = starData[gl_VertexID/3].vertexPositions[gl_VertexID%3].xyz;
centerPos = starData[gl_VertexID/3].pos;
color = starData[gl_VertexID/3].color*starOpacity;
}

BIN
assets/cubyz/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -641,7 +641,7 @@ pub const Player = struct { // MARK: Player
};
pub const World = struct { // MARK: World
const dayCycle: u63 = 12000; // Length of one in-game day in 100ms. Midnight is at DAY_CYCLE/2. Sunrise and sunset each take about 1/16 of the day. Currently set to 20 minutes
pub const dayCycle: u63 = 12000; // Length of one in-game day in 100ms. Midnight is at DAY_CYCLE/2. Sunrise and sunset each take about 1/16 of the day. Currently set to 20 minutes
conn: *Connection,
manager: *ConnectionManager,

View File

@ -14,6 +14,7 @@ const GuiComponent = gui.GuiComponent;
pub const Samples = enum(u8) {
screenbuffer_clear,
clear,
skybox,
animation,
chunk_rendering_preparation,
chunk_rendering_previous_visible,
@ -33,6 +34,7 @@ pub const Samples = enum(u8) {
const names = [_][]const u8{
"Screenbuffer clear",
"Clear",
"Skybox",
"Pre-processing Block Animations",
"Chunk Rendering Preparation",
"Chunk Rendering Previous Visible",

View File

@ -53,6 +53,17 @@ pub fn nextFloatSigned(seed: *u64) f32 {
return @as(f32, @floatFromInt(@as(i24, @bitCast(nextInt(u24, seed)))))/(1 << 23);
}
pub fn nextFloatExp(seed: *u64) f32 {
return -@log(nextFloat(seed));
}
pub fn nextFloatGauss(seed: *u64) f32 {
const a = nextFloat(seed);
const b = nextFloat(seed);
return @sqrt(-2.0*@log(a))*@cos(2.0*std.math.pi*b);
}
pub fn nextFloatVector(len: comptime_int, seed: *u64) @Vector(len, f32) {
var result: @Vector(len, f32) = undefined;
inline for(0..len) |i| {

View File

@ -72,6 +72,7 @@ pub fn init() void {
MenuBackGround.init() catch |err| {
std.log.err("Failed to initialize the Menu Background: {s}", .{@errorName(err)});
};
Skybox.init();
chunk_meshing.init();
mesh_storage.init();
reflectionCubeMap = .init();
@ -86,6 +87,7 @@ pub fn deinit() void {
Bloom.deinit();
MeshSelection.deinit();
MenuBackGround.deinit();
Skybox.deinit();
mesh_storage.deinit();
chunk_meshing.deinit();
reflectionCubeMap.deinit();
@ -134,11 +136,10 @@ pub fn render(playerPosition: Vec3d, deltaTime: f64) void {
ambient[0] = @max(0.1, world.ambientLight);
ambient[1] = @max(0.1, world.ambientLight);
ambient[2] = @max(0.1, world.ambientLight);
const skyColor = vec.xyz(world.clearColor);
game.fog.skyColor = skyColor;
game.fog.skyColor = vec.xyz(world.clearColor);
itemdrop.ItemDisplayManager.update(deltaTime);
renderWorld(world, ambient, skyColor, playerPosition);
renderWorld(world, ambient, Skybox.getSkyColor(), playerPosition);
const startTime = std.time.milliTimestamp();
mesh_storage.updateMeshes(startTime + maximumMeshTime);
} else {
@ -183,6 +184,10 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
const time: u32 = @intCast(std.time.milliTimestamp() & std.math.maxInt(u32));
gpu_performance_measuring.startQuery(.skybox);
Skybox.render();
gpu_performance_measuring.stopQuery();
gpu_performance_measuring.startQuery(.animation);
blocks.meshes.preProcessAnimationData(time);
gpu_performance_measuring.stopQuery();
@ -611,6 +616,170 @@ pub const MenuBackGround = struct {
}
};
pub const Skybox = struct {
var starShader: Shader = undefined;
var starUniforms: struct {
mvp: c_int,
starOpacity: c_int,
} = undefined;
var starVao: c_uint = undefined;
var starSsbo: graphics.SSBO = undefined;
const numStars = 10000;
fn getStarPos(seed: *u64) Vec3f {
const x: f32 = @floatCast(main.random.nextFloatGauss(seed));
const y: f32 = @floatCast(main.random.nextFloatGauss(seed));
const z: f32 = @floatCast(main.random.nextFloatGauss(seed));
const r = std.math.cbrt(main.random.nextFloat(seed))*5000.0;
return vec.normalize(Vec3f{x, y, z})*@as(Vec3f, @splat(r));
}
fn getStarColor(temperature: f32, light: f32, image: graphics.Image) Vec3f {
const rgbCol = image.getRGB(@intFromFloat(std.math.clamp(temperature/15000.0*@as(f32, @floatFromInt(image.width)), 0.0, @as(f32, @floatFromInt(image.width - 1)))), 0);
var rgb: Vec3f = @floatFromInt(Vec3i{rgbCol.r, rgbCol.g, rgbCol.b});
rgb /= @splat(255.0);
rgb *= @as(Vec3f, @splat(light));
const m = @reduce(.Max, rgb);
if(m > 1.0) {
rgb /= @as(Vec3f, @splat(m));
}
return rgb;
}
fn init() void {
const starColorImage = graphics.Image.readFromFile(main.stackAllocator, "assets/cubyz/star.png") catch |err| {
std.log.err("Failed to load star image: {s}", .{@errorName(err)});
return;
};
defer starColorImage.deinit(main.stackAllocator);
starShader = Shader.initAndGetUniforms("assets/cubyz/shaders/skybox/star.vs", "assets/cubyz/shaders/skybox/star.fs", "", &starUniforms);
starShader.bind();
var starData: [numStars*20]f32 = undefined;
const starDist = 200.0;
const off: f32 = @sqrt(3.0)/6.0;
const triVertA = Vec3f{0.5, starDist, -off};
const triVertB = Vec3f{-0.5, starDist, -off};
const triVertC = Vec3f{0.0, starDist, @sqrt(3.0)/2.0 - off};
var seed: u64 = 0;
for(0..numStars) |i| {
var pos: Vec3f = undefined;
var radius: f32 = undefined;
var temperature: f32 = undefined;
var light: f32 = 0;
while(light < 0.1) {
pos = getStarPos(&seed);
radius = @floatCast(main.random.nextFloatExp(&seed)*4 + 0.2);
temperature = @floatCast(@abs(main.random.nextFloatGauss(&seed)*3000.0 + 5000.0) + 1000.0);
// 3.6e-12 can be modified to change the brightness of the stars
light = (3.6e-12*radius*radius*temperature*temperature*temperature*temperature)/(vec.dot(pos, pos));
}
pos = vec.normalize(pos)*@as(Vec3f, @splat(starDist));
const normPos = vec.normalize(pos);
const color = getStarColor(temperature, light, starColorImage);
const latitude: f32 = @floatCast(std.math.asin(normPos[2]));
const longitude: f32 = @floatCast(std.math.atan2(-normPos[0], normPos[1]));
const mat = Mat4f.rotationZ(longitude).mul(Mat4f.rotationX(latitude));
const posA = vec.xyz(mat.mulVec(.{triVertA[0], triVertA[1], triVertA[2], 1.0}));
const posB = vec.xyz(mat.mulVec(.{triVertB[0], triVertB[1], triVertB[2], 1.0}));
const posC = vec.xyz(mat.mulVec(.{triVertC[0], triVertC[1], triVertC[2], 1.0}));
starData[i*20 ..][0..3].* = posA;
starData[i*20 + 4 ..][0..3].* = posB;
starData[i*20 + 8 ..][0..3].* = posC;
starData[i*20 + 12 ..][0..3].* = pos;
starData[i*20 + 16 ..][0..3].* = color;
}
starSsbo = graphics.SSBO.initStatic(f32, &starData);
c.glGenVertexArrays(1, &starVao);
c.glBindVertexArray(starVao);
c.glEnableVertexAttribArray(0);
}
pub fn deinit() void {
starShader.deinit();
starSsbo.deinit();
c.glDeleteVertexArrays(1, &starVao);
}
pub fn getSkyColor() Vec3f {
return game.fog.skyColor*@as(Vec3f, @splat(@reduce(.Add, game.fog.skyColor)/3.0));
}
pub fn render() void {
const viewMatrix = game.camera.viewMatrix;
const time = game.world.?.gameTime.load(.monotonic);
var starOpacity: f32 = 0;
const dayTime = @abs(@mod(time, game.World.dayCycle) -% game.World.dayCycle/2);
if(dayTime < game.World.dayCycle/4 - game.World.dayCycle/16) {
starOpacity = 1;
} else if(dayTime > game.World.dayCycle/4 + game.World.dayCycle/16) {
starOpacity = 0;
} else {
starOpacity = 1 - @as(f32, @floatFromInt(dayTime - (game.World.dayCycle/4 - game.World.dayCycle/16)))/@as(f32, @floatFromInt(game.World.dayCycle/8));
}
if(starOpacity != 0) {
c.glDisable(c.GL_CULL_FACE);
c.glDisable(c.GL_DEPTH_TEST);
c.glBlendFunc(c.GL_ONE, c.GL_ONE);
c.glEnable(c.GL_BLEND);
starShader.bind();
const starMatrix = game.projectionMatrix.mul(viewMatrix.mul(Mat4f.rotationX(@as(f32, @floatFromInt(time))/@as(f32, @floatFromInt(main.game.World.dayCycle)))));
starSsbo.bind(12);
c.glUniform1f(starUniforms.starOpacity, starOpacity);
c.glUniformMatrix4fv(starUniforms.mvp, 1, c.GL_TRUE, @ptrCast(&starMatrix));
c.glBindVertexArray(starVao);
c.glDrawArrays(c.GL_TRIANGLES, 0, numStars*3);
c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, 0);
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
c.glEnable(c.GL_CULL_FACE);
c.glEnable(c.GL_DEPTH_TEST);
}
}
};
pub const Frustum = struct { // MARK: Frustum
const Plane = struct {
pos: Vec3f,