Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a skybox #950

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions assets/cubyz/shaders/deferred_render_pass.fs
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,12 @@ vec3 applyFrontfaceFog(float fogDistance, vec3 fogColor, vec3 inColor) {
void main() {
fragColor = texture(color, texCoords);
fragColor += texture(bloomColor, texCoords);

float densityAdjustment = sqrt(dot(tanXY*(texCoords*2 - 1), tanXY*(texCoords*2 - 1)) + 1);
float dist = zFromDepth(texture(depthTexture, texCoords).r);
float fogDistance = calculateFogDistance(dist, densityAdjustment, playerPositionInteger.z + playerPositionFraction.z, normalize(direction).z, fog.density, fog.fogLower, fog.fogHigher);
fragColor.rgb = applyFrontfaceFog(fogDistance, fog.color, fragColor.rgb);

float maxColor = max(1.0, max(fragColor.r, max(fragColor.g, fragColor.b)));
fragColor.rgb = fragColor.rgb/maxColor;
}
179 changes: 179 additions & 0 deletions assets/cubyz/shaders/skybox/fragment.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#version 330

layout (location=0) out vec4 fragColor;

in vec3 pos;

#define PI 3.141592
#define iSteps 16
#define jSteps 8
#define ATMOS_SIZE 6371e3

uniform mat4 lightDir;
uniform mat4 invLightDir;
uniform float altitude;

vec2 rsi(vec3 r0, vec3 rd, float sr) {
float a = dot(rd, rd);
float b = 2.0 * dot(rd, r0);
float c = dot(r0, r0) - (sr * sr);
float d = (b*b) - 4.0*a*c;
if (d < 0.0) return vec2(1e5,-1e5);
return vec2(
(-b - sqrt(d))/(2.0*a),
(-b + sqrt(d))/(2.0*a)
);
}

vec3 atmosphere(vec3 r, vec3 r0, vec3 pSun, float iSun, float rPlanet, float rAtmos, vec3 kRlh, float kMie, float shRlh, float shMie, float g) {
pSun = normalize(pSun);
r = normalize(r);

vec2 p = rsi(r0, r, rAtmos);
if (p.x > p.y) return vec3(0,0,0);
p.y = min(p.y, rsi(r0, r, rPlanet).x);
float iStepSize = (p.y - p.x) / float(iSteps);

float iTime = 0.0;

vec3 totalRlh = vec3(0,0,0);
vec3 totalMie = vec3(0,0,0);

float iOdRlh = 0.0;
float iOdMie = 0.0;

float mu = dot(r, pSun);
float mumu = mu * mu;
float gg = g * g;
float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu);
float pMie = 3.0 / (8.0 * PI) * ((1.0 - gg) * (mumu + 1.0)) / (pow(1.0 + gg - 2.0 * mu * g, 1.5) * (2.0 + gg));

for (int i = 0; i < iSteps; i++) {

vec3 iPos = r0 + r * (iTime + iStepSize * 0.5);

float iHeight = length(iPos) - rPlanet;

float odStepRlh = exp(-iHeight / shRlh) * iStepSize;
float odStepMie = exp(-iHeight / shMie) * iStepSize;

iOdRlh += odStepRlh;
iOdMie += odStepMie;

float jStepSize = rsi(iPos, pSun, rAtmos).y / float(jSteps);

float jTime = 0.0;

float jOdRlh = 0.0;
float jOdMie = 0.0;

for (int j = 0; j < jSteps; j++) {

vec3 jPos = iPos + pSun * (jTime + jStepSize * 0.5);

float jHeight = length(jPos) - rPlanet;

jOdRlh += exp(-jHeight / shRlh) * jStepSize;
jOdMie += exp(-jHeight / shMie) * jStepSize;

jTime += jStepSize;
}

vec3 attn = exp(-(kMie * (iOdMie + jOdMie) + kRlh * (iOdRlh + jOdRlh)));

totalRlh += odStepRlh * attn;
totalMie += odStepMie * attn;

iTime += iStepSize;

}

return iSun * (pRlh * kRlh * totalRlh + pMie * kMie * totalMie);
}

vec3 hash( vec3 x )
{
x = vec3(
dot(x,vec3(127.1,311.7, 74.7)),
dot(x,vec3(269.5,183.3,246.1)),
dot(x,vec3(113.5,271.9,124.6))
);

return fract(sin(x)*43758.5453123);
}

vec3 voronoi_sphere( in vec3 x )
{
vec3 p = floor( x );
vec3 f = fract( x );

float sphere_radius = length(x);

float id = 0.0;
vec2 res = vec2( 100.0 );
for( int k=-1; k<=1; k++ )
for( int j=-1; j<=1; j++ )
for( int i=-1; i<=1; i++ )
{
vec3 b = vec3( float(i), float(j), float(k) );
vec3 r = vec3( b ) - f + hash( p + b );

vec3 cell_center_in_os = p + b + vec3(0.5);
float dist_between_cell_center_and_sphere_surface = abs(length(cell_center_in_os) - sphere_radius);

float max_cell_dist = 0.5;
if (dist_between_cell_center_and_sphere_surface < max_cell_dist)
{

vec3 r_in_os = x + r;
r_in_os = normalize(r_in_os) * sphere_radius;
r = r_in_os - x;

float d = dot( r, r );
if( d < res.x )
{
id = dot( p+b, vec3(1.0,57.0,113.0 ) );
res = vec2( d, res.x );
}
else if( d < res.y )
{
res.y = d;
}
}
}

return vec3( sqrt( res ), abs(id) );
}

void main() {
vec3 rayDir = normalize(pos);

vec3 sunDir = (lightDir * vec4(1, 0, 0, 1)).xyz;

vec3 color = atmosphere(
rayDir,
vec3(0,0,6372e3 + altitude),
sunDir,
22.0,
6371e3,
6471e3,
vec3(5.5e-6, 13.0e-6, 22.4e-6),
21e-6,
8e3,
1.2e3,
0.758
);

color += smoothstep(0.998, 0.999, dot(rayDir, sunDir)) * 20;

fragColor = vec4(color, 1);

float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722));
if (brightness < 0.02) {
vec3 starColor = vec3(smoothstep(0.07, 0.05, voronoi_sphere((invLightDir * vec4(rayDir, 1)).xyz * 50).x));

fragColor.rgb += (1 - 50 * brightness) * starColor;
}

fragColor.rgb = 1 - exp(-fragColor.rgb);
}
14 changes: 14 additions & 0 deletions assets/cubyz/shaders/skybox/vertex.vs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#version 330

layout (location=0) in vec3 vertexPos;

out vec3 pos;

uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

void main() {
gl_Position = projectionMatrix*viewMatrix*vec4(vertexPos, 1);

pos = vertexPos;
}
2 changes: 1 addition & 1 deletion src/game.zig
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,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,
Expand Down
89 changes: 89 additions & 0 deletions src/renderer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ var reflectionCubeMap: graphics.CubeMapTexture = undefined;
pub fn init() void {
deferredRenderPassShader = Shader.initAndGetUniforms("assets/cubyz/shaders/deferred_render_pass.vs", "assets/cubyz/shaders/deferred_render_pass.fs", "", &deferredUniforms);
fakeReflectionShader = Shader.initAndGetUniforms("assets/cubyz/shaders/fake_reflection.vs", "assets/cubyz/shaders/fake_reflection.fs", "", &fakeReflectionUniforms);

worldFrameBuffer.init(true, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE);
worldFrameBuffer.updateSize(Window.width, Window.height, c.GL_RGB16F);
Bloom.init();
MeshSelection.init();
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();
Expand All @@ -86,6 +88,7 @@ pub fn deinit() void {
Bloom.deinit();
MeshSelection.deinit();
MenuBackGround.deinit();
Skybox.deinit();
mesh_storage.deinit();
chunk_meshing.deinit();
reflectionCubeMap.deinit();
Expand Down Expand Up @@ -182,6 +185,8 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo

const time: u32 = @intCast(std.time.milliTimestamp() & std.math.maxInt(u32));

Skybox.render();

gpu_performance_measuring.startQuery(.animation);
blocks.meshes.preProcessAnimationData(time);
gpu_performance_measuring.stopQuery();
Expand Down Expand Up @@ -606,6 +611,90 @@ pub const MenuBackGround = struct {
}
};

pub const Skybox = struct {
var shader: Shader = undefined;
var uniforms: struct {
time: c_int,
altitude: c_int,
lightDir: c_int,
invLightDir: c_int,
viewMatrix: c_int,
projectionMatrix: c_int,
} = undefined;

var vao: c_uint = undefined;
var vbos: [2]c_uint = undefined;

fn init() void {
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/skybox/vertex.vs", "assets/cubyz/shaders/skybox/fragment.fs", "", &uniforms);
shader.bind();

const rawData = [_]f32 {
-1, -1, -1,
1, -1, -1,
1, 1, -1,
-1, 1, -1,
-1, -1, 1,
1, -1, 1,
1, 1, 1,
-1, 1, 1
};

const indices = [_]c_int {
0, 3, 1, 1, 3, 2,
5, 6, 4, 4, 6, 7,
3, 7, 2, 2, 7, 6,
1, 5, 0, 0, 5, 4,
4, 7, 0, 0, 7, 3,
1, 2, 5, 5, 2, 6,
};

c.glGenVertexArrays(1, &vao);
c.glBindVertexArray(vao);
c.glGenBuffers(2, &vbos);
c.glBindBuffer(c.GL_ARRAY_BUFFER, vbos[0]);
c.glBufferData(c.GL_ARRAY_BUFFER, @intCast(rawData.len*@sizeOf(f32)), &rawData, c.GL_STATIC_DRAW);
c.glVertexAttribPointer(0, 3, c.GL_FLOAT, c.GL_FALSE, 3*@sizeOf(f32), null);
c.glEnableVertexAttribArray(0);
c.glBindBuffer(c.GL_ELEMENT_ARRAY_BUFFER, vbos[1]);
c.glBufferData(c.GL_ELEMENT_ARRAY_BUFFER, @intCast(indices.len*@sizeOf(c_int)), &indices, c.GL_STATIC_DRAW);
}

pub fn deinit() void {
shader.deinit();
c.glDeleteVertexArrays(1, &vao);
c.glDeleteBuffers(2, &vbos);
}

pub fn render() void {
c.glDisable(c.GL_CULL_FACE);
c.glDisable(c.GL_DEPTH_TEST);

const viewMatrix = game.camera.viewMatrix;
shader.bind();

const time = @as(f32, @floatFromInt(@mod(main.game.world.?.gameTime.load(.monotonic), main.game.World.dayCycle))) / (main.game.World.dayCycle);

const lightMatrix = Mat4f.rotationY(-std.math.pi / 2.0 - time * std.math.pi * 2);

const invLightMatrix = Mat4f.rotationY(time * std.math.pi * 2 + std.math.pi / 2.0);

c.glUniform1f(uniforms.time, time);
c.glUniform1f(uniforms.altitude, @floatCast(game.Player.super.pos[2]));
c.glUniformMatrix4fv(uniforms.lightDir, 1, c.GL_TRUE, @ptrCast(&lightMatrix));
c.glUniformMatrix4fv(uniforms.invLightDir, 1, c.GL_TRUE, @ptrCast(&invLightMatrix));

c.glUniformMatrix4fv(uniforms.viewMatrix, 1, c.GL_TRUE, @ptrCast(&viewMatrix));
c.glUniformMatrix4fv(uniforms.projectionMatrix, 1, c.GL_TRUE, @ptrCast(&game.projectionMatrix));

c.glBindVertexArray(vao);
c.glDrawElements(c.GL_TRIANGLES, 36, c.GL_UNSIGNED_INT, null);

c.glEnable(c.GL_CULL_FACE);
c.glEnable(c.GL_DEPTH_TEST);
}
};

pub const Frustum = struct { // MARK: Frustum
const Plane = struct {
pos: Vec3f,
Expand Down
Loading