mgecumshooter/esotera
merged from silentevermore
Commit 6353b3612cd3 · mgecumshooter · 2026-10-21 17:27 +0300
Comments
No comments yet.
Diff
diff --git a/shaders/frag.glsl b/shaders/frag.glsl
--- a/shaders/frag.glsl
+++ b/shaders/frag.glsl
@@ -13,17 +13,10 @@
vec4 texel = texture(texture0, fragTexCoord) * colDiffuse * fragColor;
vec3 normal = normalize(fragNormal);
- vec3 lightDir = normalize(vec3(-0.5, 1.0, 0.5));
+ vec3 lightDir = normalize(vec3(-0.5, 1.0, -0.5));
float diffuse = max(dot(normal, lightDir), 0.0);
-
- float shade;
- if (diffuse > 0.65)
- shade = 1.0;
- else if (diffuse > 0.25)
- shade = 0.65;
- else
- shade = 0.3;
+ float shade = min(diffuse + 0.15, 1.0);
finalColor = vec4(texel.rgb * shade, texel.a);
}
diff --git a/shaders/post.glsl b/shaders/post.glsl
--- a/shaders/post.glsl
+++ b/shaders/post.glsl
@@ -7,28 +7,25 @@
uniform sampler2D texture0;
uniform sampler2D depth_tex;
+uniform sampler2D normal_tex;
+uniform float tan_half_fov;
+uniform float aspect;
out vec4 finalColor;
// dither
const mat4 bayerMatrix = mat4(
- 0.0/16.0, 12.0/16.0, 3.0/16.0, 15.0/16.0,
- 8.0/16.0, 4.0/16.0, 11.0/16.0, 7.0/16.0,
- 2.0/16.0, 14.0/16.0, 1.0/16.0, 13.0/16.0,
- 10.0/16.0, 6.0/16.0, 9.0/16.0, 5.0/16.0
+ 0.0/16.0, 12.0/16.0, 3.0/16.0, 15.0/16.0,
+ 8.0/16.0, 4.0/16.0, 11.0/16.0, 7.0/16.0,
+ 2.0/16.0, 14.0/16.0, 1.0/16.0, 13.0/16.0,
+ 10.0/16.0, 6.0/16.0, 9.0/16.0, 5.0/16.0
);
// ssao
-const vec2 OFFSETS[8] = vec2[8](
- vec2( 1.0, 0.0),
- vec2(-1.0, 0.0),
- vec2( 0.0, 1.0),
- vec2( 0.0, -1.0),
- vec2( 0.707, 0.707),
- vec2(-0.707, 0.707),
- vec2( 0.707, -0.707),
- vec2(-0.707, -0.707)
-);
+const int AO_SAMPLES = 16;
+const float AO_RADIUS = 1.5;
+const float AO_BIAS = 0.05;
+const float AO_STRENGTH = 0.6;
// pixelization + other
float pixel_size = 1.0;
@@ -47,6 +44,59 @@
return clamp(lin / fog_far, 0.0, 1.0);
}
+float view_dist(float d) {
+ float z = d * 2.0 - 1.0;
+ return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane));
+}
+
+vec3 view_pos(vec2 uv, float d) {
+ float lz = view_dist(d);
+ vec2 ndc = uv * 2.0 - 1.0;
+ return vec3(ndc * vec2(aspect, 1.0) * tan_half_fov * lz, -lz);
+}
+
+float hash(vec2 p) {
+ return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
+}
+
+float ssao(vec2 uv, float depth, vec2 texsize) {
+ vec3 P = view_pos(uv, depth);
+ vec3 N = normalize(texture(normal_tex, uv).xyz * 2.0 - 1.0);
+
+ float ang = hash(floor(uv * texsize)) * 6.2831853;
+ vec3 rvec = vec3(cos(ang), sin(ang), 0.0);
+ vec3 T = normalize(rvec - N * dot(rvec, N));
+ vec3 B = cross(N, T);
+ mat3 TBN = mat3(T, B, N);
+
+ float occ = 0.0;
+ for (int i = 0; i < AO_SAMPLES; i++) {
+ float e = (float(i) + 0.5) / float(AO_SAMPLES);
+ float phi = float(i) * 2.399963;
+ vec3 dir = vec3(cos(phi) * sqrt(e), sin(phi) * sqrt(e), sqrt(1.0 - e));
+
+ float s = fract(float(i) * 0.618034 + 0.1);
+ float scale = mix(0.1, 1.0, s * s);
+
+ vec3 sp = P + TBN * dir * (AO_RADIUS * scale);
+ if (sp.z >= -near_plane) continue;
+
+ vec2 suv = (sp.xy / (-sp.z * vec2(aspect, 1.0) * tan_half_fov)) * 0.5 + 0.5;
+ if (any(lessThan(suv, vec2(0.0))) || any(greaterThan(suv, vec2(1.0)))) continue;
+
+ float sd = texture(depth_tex, suv).r;
+ if (sd >= 0.99999) continue;
+
+ float scene_dist = view_dist(sd);
+ float sample_dist = -sp.z;
+
+ float hit = (scene_dist <= sample_dist - AO_BIAS) ? 1.0 : 0.0;
+ float range = smoothstep(0.0, 1.0, AO_RADIUS / abs(view_dist(depth) - scene_dist));
+ occ += hit * range;
+ }
+ return 1.0 - AO_STRENGTH * occ / float(AO_SAMPLES);
+}
+
void main() {
// pixelization
vec2 texsize = textureSize(texture0, 0);
@@ -59,8 +109,14 @@
pixel_uv = dist * 0.5 + vec2(0.5);
float depth = texture(depth_tex, pixel_uv).r;
+ vec3 normal = texture(normal_tex, pixel_uv).xyz * 2.0 - 1.0;
vec4 color = texture(texture0, pixel_uv) * fragColor;
+ // ssao
+ if (depth < 1) {
+ color.rgb *= ssao(pixel_uv, depth, texsize);
+ }
+
// dither
{
float lum = dot(color.rgb, vec3(0.299, 0.587, 0.114));
@@ -87,62 +143,5 @@
color.rgb *= 1.0 - diff;
color.rgb *= pow(1.0 - linearize_depth(depth), 4.0);
- if (depth < 1) {
- float strength = 1.0;
- float radius = 4.0;
- int ao_idx = 1;
-
- // ssao
- if (ao_idx == 1) {
- // simple
- vec2 px = radius / texsize;
- float ao = 0.0;
-
- float d1 = texture(depth_tex, pixel_uv + vec2( px.x, 0.0)).r;
- float d2 = texture(depth_tex, pixel_uv + vec2(-px.x, 0.0)).r;
- float d3 = texture(depth_tex, pixel_uv + vec2(0.0, px.y)).r;
- float d4 = texture(depth_tex, pixel_uv + vec2(0.0, -px.y)).r;
-
- ao += smoothstep(0.001, 0.008, depth - d1);
- ao += smoothstep(0.001, 0.008, depth - d2);
- ao += smoothstep(0.001, 0.008, depth - d3);
- ao += smoothstep(0.001, 0.008, depth - d4);
- ao *= 0.25;
-
- color.rgb *= 1.0 - ao * strength;
- } else {
- float occlusion = 0.0;
- vec2 texelSize = 1.0 / texsize;
-
- for (int i = 0; i < 8; i++) {
- vec2 sampleUV =
- pixel_uv + OFFSETS[i] * radius * texelSize;
-
- if (any(lessThan(sampleUV, vec2(0.0))) ||
- any(greaterThan(sampleUV, vec2(1.0)))) continue;
-
- float sampleDepth = texture(depth_tex, sampleUV).r;
-
- if (sampleDepth >= 0.99999) continue;
-
- float difference = depth - sampleDepth;
- float bias = max(0.0005, depth * 0.002);
-
- occlusion += smoothstep(
- bias,
- bias * 4.0,
- difference
- );
- }
-
- float ao = clamp(
- 1.0 - strength * (occlusion / 8.0),
- 0.0,
- 1.0
- );
-
- color.rgb *= ao;
- }
- }
finalColor = color;
}
diff --git a/shaders/post_vert.glsl b/shaders/post_vert.glsl
new file mode 100644
--- /dev/null
+++ b/shaders/post_vert.glsl
@@ -0,0 +1,16 @@
+#version 330
+
+in vec3 vertexPosition;
+in vec2 vertexTexCoord;
+in vec3 vertexNormal;
+in vec4 vertexColor;
+
+out vec2 fragTexCoord;
+out vec4 fragColor;
+out vec3 fragNormal;
+
+void main() {
+ fragTexCoord = vertexTexCoord;
+ fragColor = vertexColor;
+ fragNormal = vertexNormal;
+}
diff --git a/shaders/vert.glsl b/shaders/vert.glsl
--- a/shaders/vert.glsl
+++ b/shaders/vert.glsl
@@ -7,6 +7,7 @@
uniform mat4 mvp;
uniform mat4 matModel;
+uniform mat4 matView;
out vec2 fragTexCoord;
out vec4 fragColor;
@@ -16,6 +17,7 @@
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
fragNormal = mat3(transpose(inverse(matModel))) * vertexNormal;
+ // fragNormal = mat3(matView) * mat3(matModel) * vertexNormal;
gl_Position = mvp * vec4(vertexPosition, 1.0);
}
diff --git a/src/chunk/mod.rs b/src/chunk/mod.rs
--- a/src/chunk/mod.rs
+++ b/src/chunk/mod.rs
@@ -8,30 +8,27 @@
use std::fs;
// internal deps
-use crate::voxel::{ self, Voxel, VOXEL_SIZE };
use crate::util::*;
-
+use crate::voxel::{self, VOXEL_SIZE, Voxel};
// constants
pub const CHUNK_SIZE: usize = 32;
-
pub struct Chunk {
pub chunk_pos: Vector3,
- pub voxels: [Voxel; CHUNK_SIZE*CHUNK_SIZE*CHUNK_SIZE],
+ pub voxels: [Voxel; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE],
pub dirty: bool,
- pub mesh: Option<Mesh>
+ pub mesh: Option<Mesh>,
} // pending: add events stack
-
impl Chunk {
// constructor
pub fn new(pos: Vector3) -> Self {
let mut s = Self {
chunk_pos: pos,
- voxels: [Voxel::Air; CHUNK_SIZE*CHUNK_SIZE*CHUNK_SIZE],
+ voxels: [Voxel::Air; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE],
dirty: true,
- mesh: None
+ mesh: None,
};
for x in 0..CHUNK_SIZE {
for z in 0..CHUNK_SIZE {
@@ -81,237 +78,243 @@
cos_angle.acos() <= half_fov + angular_margin
}
-
+
pub fn generate_mesh(&mut self, rl: &RaylibThread) {
- let mut vertices: Vec<Vector3> = Vec::new();
- let mut normals: Vec<Vector3> = Vec::new();
- let mut indices: Vec<u16> = Vec::new();
+ let mut vertices: Vec<Vector3> = Vec::new();
+ let mut normals: Vec<Vector3> = Vec::new();
+ let mut indices: Vec<u16> = Vec::new();
+
+ let mut vertex_offset: i32 = 0;
+ for x in 0..CHUNK_SIZE {
+ for y in 0..CHUNK_SIZE {
+ for z in 0..CHUNK_SIZE {
+ if let Some(Voxel::Air) = self.get_voxel(x, y, z) {
+ continue;
+ }
+ if !self.is_exposed(x, y, z) {
+ continue;
+ }
- let mut vertex_offset: i32 = 0;
- for x in 0..CHUNK_SIZE {
- for y in 0..CHUNK_SIZE {
- for z in 0..CHUNK_SIZE {
- if let Some(Voxel::Air) = self.get_voxel(x, y, z) {
- continue;
- }
- if !self.is_exposed(x, y, z) {
- continue;
- }
-
+ // first side
+ vertices.push(Vector3::new(x as f32, y as f32, z as f32));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, -1f32));
- // first side
- vertices.push(
- Vector3::
- new(x as f32, y as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
- );
- push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, -1f32));
-
- // second side
- vertices.push(
- Vector3::
- new(x as f32, y as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
- );
- push_quad_normal(&mut normals, Vector3::new(-1f32, 0f32, 0f32));
-
- // third side
- vertices.push(
- Vector3::
- new(x as f32, y as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
- );
- push_quad_normal(&mut normals, Vector3::new(0f32, -1f32, 0f32));
+ // second side
+ vertices.push(Vector3::new(x as f32, y as f32, z as f32));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(-1f32, 0f32, 0f32));
- // fourth side
- vertices.push(
- Vector3::
- new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
- );
- push_quad_normal(&mut normals, Vector3::new(0f32, 1f32, 0f32));
+ // third side
+ vertices.push(Vector3::new(x as f32, y as f32, z as f32));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(0f32, -1f32, 0f32));
+
+ // fourth side
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(0f32, 1f32, 0f32));
- // fifth side
- vertices.push(
- Vector3::
- new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
- );
- push_quad_normal(&mut normals, Vector3::new(1f32, 0f32, 0f32));
+ // fifth side
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(1f32, 0f32, 0f32));
- // sixth side
- vertices.push(
- Vector3::
- new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
- );
- vertices.push(
- Vector3::
- new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
- );
- push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, 1f32));
+ // sixth side
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, 1f32));
-
- indices.push(0 as u16 + vertex_offset as u16);
- indices.push(1 as u16 + vertex_offset as u16);
- indices.push(2 as u16 + vertex_offset as u16);
- indices.push(2 as u16 + vertex_offset as u16);
- indices.push(1 as u16 + vertex_offset as u16);
- indices.push(3 as u16 + vertex_offset as u16);
+ indices.push(0 as u16 + vertex_offset as u16);
+ indices.push(1 as u16 + vertex_offset as u16);
+ indices.push(2 as u16 + vertex_offset as u16);
+ indices.push(2 as u16 + vertex_offset as u16);
+ indices.push(1 as u16 + vertex_offset as u16);
+ indices.push(3 as u16 + vertex_offset as u16);
- indices.push(4 as u16 + vertex_offset as u16);
- indices.push(6 as u16 + vertex_offset as u16);
- indices.push(5 as u16 + vertex_offset as u16);
- indices.push(5 as u16 + vertex_offset as u16);
- indices.push(6 as u16 + vertex_offset as u16);
- indices.push(7 as u16 + vertex_offset as u16);
-
- indices.push(8 as u16 + vertex_offset as u16);
- indices.push(9 as u16 + vertex_offset as u16);
- indices.push(10 as u16 + vertex_offset as u16);
- indices.push(10 as u16 + vertex_offset as u16);
- indices.push(9 as u16 + vertex_offset as u16);
- indices.push(11 as u16 + vertex_offset as u16);
+ indices.push(4 as u16 + vertex_offset as u16);
+ indices.push(6 as u16 + vertex_offset as u16);
+ indices.push(5 as u16 + vertex_offset as u16);
+ indices.push(5 as u16 + vertex_offset as u16);
+ indices.push(6 as u16 + vertex_offset as u16);
+ indices.push(7 as u16 + vertex_offset as u16);
- indices.push(12 as u16 + vertex_offset as u16);
- indices.push(14 as u16 + vertex_offset as u16);
- indices.push(13 as u16 + vertex_offset as u16);
- indices.push(13 as u16 + vertex_offset as u16);
- indices.push(14 as u16 + vertex_offset as u16);
- indices.push(15 as u16 + vertex_offset as u16);
+ indices.push(8 as u16 + vertex_offset as u16);
+ indices.push(9 as u16 + vertex_offset as u16);
+ indices.push(10 as u16 + vertex_offset as u16);
+ indices.push(10 as u16 + vertex_offset as u16);
+ indices.push(9 as u16 + vertex_offset as u16);
+ indices.push(11 as u16 + vertex_offset as u16);
- indices.push(16 as u16 + vertex_offset as u16);
- indices.push(17 as u16 + vertex_offset as u16);
- indices.push(18 as u16 + vertex_offset as u16);
- indices.push(18 as u16 + vertex_offset as u16);
- indices.push(17 as u16 + vertex_offset as u16);
- indices.push(19 as u16 + vertex_offset as u16);
+ indices.push(12 as u16 + vertex_offset as u16);
+ indices.push(14 as u16 + vertex_offset as u16);
+ indices.push(13 as u16 + vertex_offset as u16);
+ indices.push(13 as u16 + vertex_offset as u16);
+ indices.push(14 as u16 + vertex_offset as u16);
+ indices.push(15 as u16 + vertex_offset as u16);
- indices.push(20 as u16 + vertex_offset as u16);
- indices.push(22 as u16 + vertex_offset as u16);
- indices.push(21 as u16 + vertex_offset as u16);
- indices.push(21 as u16 + vertex_offset as u16);
- indices.push(22 as u16 + vertex_offset as u16);
- indices.push(23 as u16 + vertex_offset as u16);
+ indices.push(16 as u16 + vertex_offset as u16);
+ indices.push(17 as u16 + vertex_offset as u16);
+ indices.push(18 as u16 + vertex_offset as u16);
+ indices.push(18 as u16 + vertex_offset as u16);
+ indices.push(17 as u16 + vertex_offset as u16);
+ indices.push(19 as u16 + vertex_offset as u16);
-
-
- vertex_offset += 24;
+ indices.push(20 as u16 + vertex_offset as u16);
+ indices.push(22 as u16 + vertex_offset as u16);
+ indices.push(21 as u16 + vertex_offset as u16);
+ indices.push(21 as u16 + vertex_offset as u16);
+ indices.push(22 as u16 + vertex_offset as u16);
+ indices.push(23 as u16 + vertex_offset as u16);
- }
- }
- }
+ vertex_offset += 24;
+ }
+ }
+ }
- let vertex_count = vertices.len();
- let index_count = indices.len();
- let normals_count = normals.len();
+ let vertex_count = vertices.len();
+ let index_count = indices.len();
+ let normals_count = normals.len();
- if vertex_count == 0 {
- self.mesh = None;
- return;
- }
+ if vertex_count == 0 {
+ self.mesh = None;
+ return;
+ }
- unsafe {
- let v_size = vertex_count * std::mem::size_of::<Vector3>();
+ unsafe {
+ let v_size = vertex_count * std::mem::size_of::<Vector3>();
let i_size = index_count * std::mem::size_of::<u16>();
- let n_size = normals_count * std::mem::size_of::<Vector3>();
+ let n_size = normals_count * std::mem::size_of::<Vector3>();
let v_ptr = rlb::ffi::MemAlloc(v_size as u32) as *mut Vector3;
let i_ptr = rlb::ffi::MemAlloc(i_size as u32) as *mut u16;
- let n_ptr = rlb::ffi::MemAlloc(n_size as u32) as *mut Vector3;
+ let n_ptr = rlb::ffi::MemAlloc(n_size as u32) as *mut Vector3;
std::ptr::copy_nonoverlapping(vertices.as_ptr(), v_ptr, vertex_count);
std::ptr::copy_nonoverlapping(indices.as_ptr(), i_ptr, index_count);
- std::ptr::copy_nonoverlapping(normals.as_ptr(), n_ptr, normals_count);
+ std::ptr::copy_nonoverlapping(normals.as_ptr(), n_ptr, normals_count);
let raw_mesh = rlb::ffi::Mesh {
- vertexCount: vertex_count as i32,
- triangleCount: (index_count / 3) as i32,
- vertices: v_ptr as *mut std::ffi::c_float,
- indices: i_ptr,
- normals: n_ptr as *mut std::ffi::c_float,
- texcoords: std::ptr::null_mut(),
- texcoords2: std::ptr::null_mut(),
- colors: std::ptr::null_mut(),
- tangents: std::ptr::null_mut(),
- animVertices: std::ptr::null_mut(),
- animNormals: std::ptr::null_mut(),
- boneCount: 0,
- boneIndices: std::ptr::null_mut(),
- boneWeights: std::ptr::null_mut(),
- vaoId: 0,
- vboId: std::ptr::null_mut(),
- };
+ vertexCount: vertex_count as i32,
+ triangleCount: (index_count / 3) as i32,
+ vertices: v_ptr as *mut std::ffi::c_float,
+ indices: i_ptr,
+ normals: n_ptr as *mut std::ffi::c_float,
+ texcoords: std::ptr::null_mut(),
+ texcoords2: std::ptr::null_mut(),
+ colors: std::ptr::null_mut(),
+ tangents: std::ptr::null_mut(),
+ animVertices: std::ptr::null_mut(),
+ animNormals: std::ptr::null_mut(),
+ boneCount: 0,
+ boneIndices: std::ptr::null_mut(),
+ boneWeights: std::ptr::null_mut(),
+ vaoId: 0,
+ vboId: std::ptr::null_mut(),
+ };
- let mut mesh = Mesh::from_raw(raw_mesh);
-
- mesh.upload(false);
+ let mut mesh = Mesh::from_raw(raw_mesh);
- self.mesh = Some(mesh);
- }
-
+ mesh.upload(false);
+
+ self.mesh = Some(mesh);
+ }
}
// returns voxel by chunk coordinates
@@ -345,39 +348,44 @@
}
pub fn get_chunk_aabb(&self) -> Aabb {
- Aabb {
- min: self.chunk_pos * CHUNK_SIZE as f32,
- max: self.chunk_pos * CHUNK_SIZE as f32 + Vector3::new
- (CHUNK_SIZE as f32, CHUNK_SIZE as f32, CHUNK_SIZE as f32),
- }
+ Aabb {
+ min: self.chunk_pos * CHUNK_SIZE as f32,
+ max: self.chunk_pos * CHUNK_SIZE as f32
+ + Vector3::new(CHUNK_SIZE as f32, CHUNK_SIZE as f32, CHUNK_SIZE as f32),
+ }
}
pub fn get_voxel_global_aabb(&self, idx: usize) -> Aabb {
- Aabb {
- min: self.global_voxel_pos(idx),
- max: self.global_voxel_pos(idx) + Vector3::new
- (VOXEL_SIZE as f32, VOXEL_SIZE as f32, VOXEL_SIZE as f32),
- }
+ Aabb {
+ min: self.global_voxel_pos(idx),
+ max: self.global_voxel_pos(idx)
+ + Vector3::new(VOXEL_SIZE as f32, VOXEL_SIZE as f32, VOXEL_SIZE as f32),
+ }
}
pub fn get_voxel_pos_glb(&self, x: i32, y: i32, z: i32) -> (i32, i32, i32) {
- let chunk_x: i32;
- let chunk_y: i32;
- let chunk_z: i32;
+ let chunk_x: i32;
+ let chunk_y: i32;
+ let chunk_z: i32;
- chunk_x = (x as f32 - self.chunk_pos.x * CHUNK_SIZE as f32) as i32;
- chunk_y = (y as f32 - self.chunk_pos.y * CHUNK_SIZE as f32) as i32;
- chunk_z = (z as f32 - self.chunk_pos.z * CHUNK_SIZE as f32) as i32;
+ chunk_x = (x as f32 - self.chunk_pos.x * CHUNK_SIZE as f32) as i32;
+ chunk_y = (y as f32 - self.chunk_pos.y * CHUNK_SIZE as f32) as i32;
+ chunk_z = (z as f32 - self.chunk_pos.z * CHUNK_SIZE as f32) as i32;
- (chunk_x, chunk_y, chunk_z)
+ (chunk_x, chunk_y, chunk_z)
}
// detects, whether voxel is exoped or not
- fn is_exposed(&self, x: usize, y: usize, z: usize) -> bool { // pending: check not only current chunk,
- let directions = [ // but also surrounding chunks
- (1, 0, 0), (-1, 0, 0),
- (0, 1, 0), (0, -1, 0),
- (0, 0, 1), (0, 0, -1),
+ fn is_exposed(&self, x: usize, y: usize, z: usize) -> bool {
+ // pending: check not only current chunk,
+ let directions = [
+ // but also surrounding chunks
+ (1, 0, 0),
+ (-1, 0, 0),
+ (0, 1, 0),
+ (0, -1, 0),
+ (0, 0, 1),
+ (0, 0, -1),
];
for (dx, dy, dz) in directions.iter() {
@@ -385,8 +393,13 @@
let ny = y as isize + dy;
let nz = z as isize + dz;
- if nx < 0 || ny < 0 || nz < 0 || nx >= CHUNK_SIZE as isize ||
- ny >= CHUNK_SIZE as isize || nz >= CHUNK_SIZE as isize {
+ if nx < 0
+ || ny < 0
+ || nz < 0
+ || nx >= CHUNK_SIZE as isize
+ || ny >= CHUNK_SIZE as isize
+ || nz >= CHUNK_SIZE as isize
+ {
return true;
}
@@ -405,15 +418,18 @@
for x in 0..CHUNK_SIZE {
for y in 0..CHUNK_SIZE {
for z in 0..CHUNK_SIZE {
- if let Some(Voxel::Air) = self.get_voxel(x, y, z) { continue; }
+ if let Some(Voxel::Air) = self.get_voxel(x, y, z) {
+ continue;
+ }
if self.is_exposed(x, y, z) {
ctx.draw_cube(
- self.chunk_pos * CHUNK_SIZE as f32 + Vector3::new(x as f32, y as f32, z as f32),
- voxel::VOXEL_SIZE as f32,
- voxel::VOXEL_SIZE as f32,
- voxel::VOXEL_SIZE as f32,
- rlb::color::Color::GRAY
+ self.chunk_pos * CHUNK_SIZE as f32
+ + Vector3::new(x as f32, y as f32, z as f32),
+ voxel::VOXEL_SIZE as f32,
+ voxel::VOXEL_SIZE as f32,
+ voxel::VOXEL_SIZE as f32,
+ rlb::color::Color::GRAY,
);
}
}
@@ -423,54 +439,52 @@
}
pub fn save(&self) {
- let dir = "saves";
- let _ = fs::create_dir_all(dir);
- let path = format!("{}/chunk_{}_{}_{}.bin", dir,
- self.chunk_pos.x as i32,
- self.chunk_pos.y as i32,
- self.chunk_pos.z as i32,
- );
+ let dir = "saves";
+ let _ = fs::create_dir_all(dir);
+ let path = format!(
+ "{}/chunk_{}_{}_{}.bin",
+ dir, self.chunk_pos.x as i32, self.chunk_pos.y as i32, self.chunk_pos.z as i32,
+ );
- let mut bytes = Vec::with_capacity(self.voxels.len());
- for v in &self.voxels {
- bytes.push(match v {
- Voxel::Air => 0u8,
- Voxel::Stone => 1u8,
- });
- }
+ let mut bytes = Vec::with_capacity(self.voxels.len());
+ for v in &self.voxels {
+ bytes.push(match v {
+ Voxel::Air => 0u8,
+ Voxel::Stone => 1u8,
+ });
+ }
- let _ = fs::write(path, bytes);
+ let _ = fs::write(path, bytes);
}
pub fn load_from_disk(pos: Vector3) -> Option<Self> {
- let path = format!("saves/chunk_{}_{}_{}.bin",
- pos.x as i32, pos.y as i32, pos.z as i32,
- );
- if let Ok(bytes) = fs::read(path) {
- if bytes.len() == CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE {
- let mut voxels = [Voxel::Air; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
- for (i, &b) in bytes.iter().enumerate() {
- voxels[i] = match b {
- 1u8 => Voxel::Stone,
- _ => Voxel::Air,
- };
- }
- return Some(Self{
- chunk_pos: pos,
- voxels,
- dirty: true,
- mesh: None,
- });
- }
- }
- None
+ let path = format!(
+ "saves/chunk_{}_{}_{}.bin",
+ pos.x as i32, pos.y as i32, pos.z as i32,
+ );
+ if let Ok(bytes) = fs::read(path) {
+ if bytes.len() == CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE {
+ let mut voxels = [Voxel::Air; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+ for (i, &b) in bytes.iter().enumerate() {
+ voxels[i] = match b {
+ 1u8 => Voxel::Stone,
+ _ => Voxel::Air,
+ };
+ }
+ return Some(Self {
+ chunk_pos: pos,
+ voxels,
+ dirty: true,
+ mesh: None,
+ });
+ }
+ }
+ None
}
}
-
fn push_quad_normal(normals: &mut Vec<Vector3>, n: Vector3) {
for _ in 0..4 {
normals.push(n);
}
}
-
diff --git a/src/chunk/mod.rs.orig b/src/chunk/mod.rs.orig
new file mode 100644
--- /dev/null
+++ b/src/chunk/mod.rs.orig
@@ -0,0 +1,490 @@
+// external deps
+use super::rlb;
+use rlb::{
+ prelude::*,
+ // core::*,
+ // consts::*,
+};
+use std::fs;
+
+// internal deps
+use crate::util::*;
+use crate::voxel::{self, VOXEL_SIZE, Voxel};
+
+// constants
+pub const CHUNK_SIZE: usize = 32;
+
+pub struct Chunk {
+ pub chunk_pos: Vector3,
+ pub voxels: [Voxel; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE],
+ pub dirty: bool,
+ pub mesh: Option<Mesh>,
+} // pending: add events stack
+
+impl Chunk {
+ // constructor
+ pub fn new(pos: Vector3) -> Self {
+ let mut s = Self {
+ chunk_pos: pos,
+ voxels: [Voxel::Air; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE],
+ dirty: true,
+ mesh: None,
+ };
+ for x in 0..CHUNK_SIZE {
+ for z in 0..CHUNK_SIZE {
+ let y = (x + z).min(CHUNK_SIZE - 1);
+ let i = x + (y * CHUNK_SIZE) + (z * CHUNK_SIZE * CHUNK_SIZE);
+ s.voxels[i] = Voxel::Stone;
+ }
+ }
+ s
+ }
+
+ pub fn is_visible(&self, cam: &Camera3D) -> bool {
+ let aabb = self.get_chunk_aabb();
+ let center = Vector3::new(
+ (aabb.min.x + aabb.max.x) *0.5f32,
+ (aabb.min.y + aabb.max.y) *0.5f32,
+ (aabb.min.z + aabb.max.z) *0.5f32,
+ );
+
+ let dx = aabb.max.x - aabb.min.x;
+ let dy = aabb.max.y - aabb.min.y;
+ let dz = aabb.max.z - aabb.min.z;
+
+ let radius = (dx*dx + dy*dy + dz*dz).sqrt() * 0.5;
+
+
+ let ddx = center.x - cam.position.x;
+ let ddy = center.y - cam.position.y;
+ let ddz = center.z - cam.position.z;
+
+ let dist = (ddx*ddx + ddy*ddy + ddz*ddz).sqrt();
+
+ let fx = cam.target.x - cam.position.x;
+ let fy = cam.target.y - cam.position.y;
+ let fz = cam.target.z - cam.position.z;
+
+ let flen = (fx*fx + fy*fy + fz*fz).sqrt();
+
+ let cos_angle = (ddx*fx + ddy*fy + ddz*fz) / (dist*flen);
+
+ let half_fov = (cam.fovy.to_radians() / 2f32) * 1f32;
+ let angular_margin = (radius / dist).atan();
+
+ if dist <= CHUNK_SIZE as f32 {
+ return true;
+ }
+
+ cos_angle.acos() <= half_fov + angular_margin
+ }
+
+ pub fn generate_mesh(&mut self, rl: &RaylibThread) {
+ let mut vertices: Vec<Vector3> = Vec::new();
+ let mut normals: Vec<Vector3> = Vec::new();
+ let mut indices: Vec<u16> = Vec::new();
+
+ let mut vertex_offset: i32 = 0;
+ for x in 0..CHUNK_SIZE {
+ for y in 0..CHUNK_SIZE {
+ for z in 0..CHUNK_SIZE {
+ if let Some(Voxel::Air) = self.get_voxel(x, y, z) {
+ continue;
+ }
+ if !self.is_exposed(x, y, z) {
+ continue;
+ }
+
+ // first side
+ vertices.push(Vector3::new(x as f32, y as f32, z as f32));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, -1f32));
+
+ // second side
+ vertices.push(Vector3::new(x as f32, y as f32, z as f32));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(-1f32, 0f32, 0f32));
+
+ // third side
+ vertices.push(Vector3::new(x as f32, y as f32, z as f32));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(0f32, -1f32, 0f32));
+
+ // fourth side
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(0f32, 1f32, 0f32));
+
+ // fifth side
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(1f32, 0f32, 0f32));
+
+ // sixth side
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32 + VOXEL_SIZE as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32 + VOXEL_SIZE as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ vertices.push(Vector3::new(
+ x as f32,
+ y as f32,
+ z as f32 + VOXEL_SIZE as f32,
+ ));
+ push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, 1f32));
+
+ indices.push(0 as u16 + vertex_offset as u16);
+ indices.push(1 as u16 + vertex_offset as u16);
+ indices.push(2 as u16 + vertex_offset as u16);
+ indices.push(2 as u16 + vertex_offset as u16);
+ indices.push(1 as u16 + vertex_offset as u16);
+ indices.push(3 as u16 + vertex_offset as u16);
+
+ indices.push(4 as u16 + vertex_offset as u16);
+ indices.push(6 as u16 + vertex_offset as u16);
+ indices.push(5 as u16 + vertex_offset as u16);
+ indices.push(5 as u16 + vertex_offset as u16);
+ indices.push(6 as u16 + vertex_offset as u16);
+ indices.push(7 as u16 + vertex_offset as u16);
+
+ indices.push(8 as u16 + vertex_offset as u16);
+ indices.push(9 as u16 + vertex_offset as u16);
+ indices.push(10 as u16 + vertex_offset as u16);
+ indices.push(10 as u16 + vertex_offset as u16);
+ indices.push(9 as u16 + vertex_offset as u16);
+ indices.push(11 as u16 + vertex_offset as u16);
+
+ indices.push(12 as u16 + vertex_offset as u16);
+ indices.push(14 as u16 + vertex_offset as u16);
+ indices.push(13 as u16 + vertex_offset as u16);
+ indices.push(13 as u16 + vertex_offset as u16);
+ indices.push(14 as u16 + vertex_offset as u16);
+ indices.push(15 as u16 + vertex_offset as u16);
+
+ indices.push(16 as u16 + vertex_offset as u16);
+ indices.push(17 as u16 + vertex_offset as u16);
+ indices.push(18 as u16 + vertex_offset as u16);
+ indices.push(18 as u16 + vertex_offset as u16);
+ indices.push(17 as u16 + vertex_offset as u16);
+ indices.push(19 as u16 + vertex_offset as u16);
+
+ indices.push(20 as u16 + vertex_offset as u16);
+ indices.push(22 as u16 + vertex_offset as u16);
+ indices.push(21 as u16 + vertex_offset as u16);
+ indices.push(21 as u16 + vertex_offset as u16);
+ indices.push(22 as u16 + vertex_offset as u16);
+ indices.push(23 as u16 + vertex_offset as u16);
+
+ vertex_offset += 24;
+ }
+ }
+ }
+
+ let vertex_count = vertices.len();
+ let index_count = indices.len();
+ let normals_count = normals.len();
+
+ if vertex_count == 0 {
+ self.mesh = None;
+ return;
+ }
+
+ unsafe {
+ let v_size = vertex_count * std::mem::size_of::<Vector3>();
+ let i_size = index_count * std::mem::size_of::<u16>();
+ let n_size = normals_count * std::mem::size_of::<Vector3>();
+
+ let v_ptr = rlb::ffi::MemAlloc(v_size as u32) as *mut Vector3;
+ let i_ptr = rlb::ffi::MemAlloc(i_size as u32) as *mut u16;
+ let n_ptr = rlb::ffi::MemAlloc(n_size as u32) as *mut Vector3;
+
+ std::ptr::copy_nonoverlapping(vertices.as_ptr(), v_ptr, vertex_count);
+ std::ptr::copy_nonoverlapping(indices.as_ptr(), i_ptr, index_count);
+ std::ptr::copy_nonoverlapping(normals.as_ptr(), n_ptr, normals_count);
+
+ let raw_mesh = rlb::ffi::Mesh {
+ vertexCount: vertex_count as i32,
+ triangleCount: (index_count / 3) as i32,
+ vertices: v_ptr as *mut std::ffi::c_float,
+ indices: i_ptr,
+ normals: n_ptr as *mut std::ffi::c_float,
+ texcoords: std::ptr::null_mut(),
+ texcoords2: std::ptr::null_mut(),
+ colors: std::ptr::null_mut(),
+ tangents: std::ptr::null_mut(),
+ animVertices: std::ptr::null_mut(),
+ animNormals: std::ptr::null_mut(),
+ boneCount: 0,
+ boneIndices: std::ptr::null_mut(),
+ boneWeights: std::ptr::null_mut(),
+ vaoId: 0,
+ vboId: std::ptr::null_mut(),
+ };
+
+ let mut mesh = Mesh::from_raw(raw_mesh);
+
+ mesh.upload(false);
+
+ self.mesh = Some(mesh);
+ }
+ }
+
+ // returns voxel by chunk coordinates
+ pub fn get_voxel(&self, x: usize, y: usize, z: usize) -> Option<&Voxel> {
+ if x >= CHUNK_SIZE || y >= CHUNK_SIZE || z >= CHUNK_SIZE {
+ return None;
+ }
+ let idx = x + y * CHUNK_SIZE + z * CHUNK_SIZE * CHUNK_SIZE;
+ Some(&self.voxels[idx])
+ }
+
+ // returns voxel chunk index in chunk by chunk coordinates
+ pub fn voxel_idx(&self, x: usize, y: usize, z: usize) -> usize {
+ x + (y * CHUNK_SIZE) + (z * CHUNK_SIZE * CHUNK_SIZE)
+ }
+
+ // returns voxel chunk position by its chunk index
+ pub fn voxel_pos(&self, idx: usize) -> Vector3 {
+ assert!(idx < CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE);
+
+ let x = (idx % CHUNK_SIZE) as f32;
+ let y = ((idx / CHUNK_SIZE) % CHUNK_SIZE) as f32;
+ let z = (idx / (CHUNK_SIZE * CHUNK_SIZE)) as f32;
+
+ Vector3::new(x, y, z)
+ }
+
+ // returns global voxel position by its chunk index
+ pub fn global_voxel_pos(&self, idx: usize) -> Vector3 {
+ self.chunk_pos * CHUNK_SIZE as f32 + self.voxel_pos(idx)
+ }
+
+ pub fn get_chunk_aabb(&self) -> Aabb {
+ Aabb {
+ min: self.chunk_pos * CHUNK_SIZE as f32,
+ max: self.chunk_pos * CHUNK_SIZE as f32
+ + Vector3::new(CHUNK_SIZE as f32, CHUNK_SIZE as f32, CHUNK_SIZE as f32),
+ }
+ }
+
+ pub fn get_voxel_global_aabb(&self, idx: usize) -> Aabb {
+ Aabb {
+ min: self.global_voxel_pos(idx),
+ max: self.global_voxel_pos(idx)
+ + Vector3::new(VOXEL_SIZE as f32, VOXEL_SIZE as f32, VOXEL_SIZE as f32),
+ }
+ }
+
+ pub fn get_voxel_pos_glb(&self, x: i32, y: i32, z: i32) -> (i32, i32, i32) {
+ let chunk_x: i32;
+ let chunk_y: i32;
+ let chunk_z: i32;
+
+ chunk_x = (x as f32 - self.chunk_pos.x * CHUNK_SIZE as f32) as i32;
+ chunk_y = (y as f32 - self.chunk_pos.y * CHUNK_SIZE as f32) as i32;
+ chunk_z = (z as f32 - self.chunk_pos.z * CHUNK_SIZE as f32) as i32;
+
+ (chunk_x, chunk_y, chunk_z)
+ }
+
+ // detects, whether voxel is exoped or not
+ fn is_exposed(&self, x: usize, y: usize, z: usize) -> bool {
+ // pending: check not only current chunk,
+ let directions = [
+ // but also surrounding chunks
+ (1, 0, 0),
+ (-1, 0, 0),
+ (0, 1, 0),
+ (0, -1, 0),
+ (0, 0, 1),
+ (0, 0, -1),
+ ];
+
+ for (dx, dy, dz) in directions.iter() {
+ let nx = x as isize + dx;
+ let ny = y as isize + dy;
+ let nz = z as isize + dz;
+
+ if nx < 0
+ || ny < 0
+ || nz < 0
+ || nx >= CHUNK_SIZE as isize
+ || ny >= CHUNK_SIZE as isize
+ || nz >= CHUNK_SIZE as isize
+ {
+ return true;
+ }
+
+ if let Some(Voxel::Air) = self.get_voxel(nx as usize, ny as usize, nz as usize) {
+ return true;
+ }
+ }
+ false
+ }
+
+ // renders chunk; MUST be used inside raylib's draw function
+ pub fn draw(
+ &self,
+ ctx: &mut RaylibMode3D<'_, RaylibTextureMode<'_, RaylibDrawHandle<'_>>>,
+ ) -> &Self {
+ for x in 0..CHUNK_SIZE {
+ for y in 0..CHUNK_SIZE {
+ for z in 0..CHUNK_SIZE {
+ if let Some(Voxel::Air) = self.get_voxel(x, y, z) {
+ continue;
+ }
+
+ if self.is_exposed(x, y, z) {
+ ctx.draw_cube(
+ self.chunk_pos * CHUNK_SIZE as f32
+ + Vector3::new(x as f32, y as f32, z as f32),
+ voxel::VOXEL_SIZE as f32,
+ voxel::VOXEL_SIZE as f32,
+ voxel::VOXEL_SIZE as f32,
+ rlb::color::Color::GRAY,
+ );
+ }
+ }
+ }
+ }
+ self
+ }
+
+ pub fn save(&self) {
+ let dir = "saves";
+ let _ = fs::create_dir_all(dir);
+ let path = format!(
+ "{}/chunk_{}_{}_{}.bin",
+ dir, self.chunk_pos.x as i32, self.chunk_pos.y as i32, self.chunk_pos.z as i32,
+ );
+
+ let mut bytes = Vec::with_capacity(self.voxels.len());
+ for v in &self.voxels {
+ bytes.push(match v {
+ Voxel::Air => 0u8,
+ Voxel::Stone => 1u8,
+ });
+ }
+
+ let _ = fs::write(path, bytes);
+ }
+
+ pub fn load_from_disk(pos: Vector3) -> Option<Self> {
+ let path = format!(
+ "saves/chunk_{}_{}_{}.bin",
+ pos.x as i32, pos.y as i32, pos.z as i32,
+ );
+ if let Ok(bytes) = fs::read(path) {
+ if bytes.len() == CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE {
+ let mut voxels = [Voxel::Air; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE];
+ for (i, &b) in bytes.iter().enumerate() {
+ voxels[i] = match b {
+ 1u8 => Voxel::Stone,
+ _ => Voxel::Air,
+ };
+ }
+ return Some(Self {
+ chunk_pos: pos,
+ voxels,
+ dirty: true,
+ mesh: None,
+ });
+ }
+ }
+ None
+ }
+}
+
+fn push_quad_normal(normals: &mut Vec<Vector3>, n: Vector3) {
+ for _ in 0..4 {
+ normals.push(n);
+ }
+}
diff --git a/src/main.rs b/src/main.rs
--- a/src/main.rs
+++ b/src/main.rs
@@ -31,20 +31,37 @@
rl.set_trace_log(TraceLogLevel::LOG_WARNING);
// shader stuff
- let mut shader = rl.load_shader(&rl_thd, Some("shaders/vert.glsl"), Some("shaders/frag.glsl")).unwrap();
- let mut post_shader = rl.load_shader(&rl_thd, None, Some("shaders/post.glsl")).unwrap();
+ let mut shader = rl
+ .load_shader(
+ &rl_thd,
+ Some("shaders/vert.glsl"),
+ Some("shaders/frag.glsl"),
+ )
+ .unwrap();
+ let mut post_shader = rl
+ .load_shader(&rl_thd, None, Some("shaders/post.glsl"))
+ .unwrap();
let depth_loc = post_shader.get_shader_location("depth_tex");
+ let normal_loc = post_shader.get_shader_location("normal_tex");
+ let loc_tan = post_shader.get_shader_location("tan_half_fov");
+ let loc_asp = post_shader.get_shader_location("aspect");
- assert!(depth_loc >= 0, "Uniform depth_tex not found");
-
+ // assert!(depth_loc >= 0, "Uniform depth_tex not found: {}", depth_loc);
+ // assert!(
+ // normal_loc >= 0,
+ // "Uniform normal_tex not found: {}",
+ // normal_loc
+ // );
+
// let mut rend_tex = rl.load_render_texture
// (&rl_thd, rl.get_render_width() as u32, rl.get_render_height() as u32).unwrap();
let mut chunk_material = rl.load_material_default(&rl_thd);
- let mut rend_tex = unsafe { load_depth_tex(rl.get_render_width(), rl.get_render_height()) };
+ let (mut rend_tex, mut normal_tex_id) =
+ load_depth_tex(rl.get_render_width(), rl.get_render_height());
unsafe {
- *chunk_material.shader_mut() = shader.make_weak();
+ *chunk_material.shader_mut() = shader.make_weak();
}
// chunk_material.set_shader(&shader);
@@ -62,61 +79,68 @@
// main game loop
while !rl.window_should_close() {
- world.load_around_player(plr.get_eye_pos());
- world.update_chunks(&rl_thd);
+ world.load_around_player(plr.get_eye_pos());
+ world.update_chunks(&rl_thd);
- let active_chunks: Vec<&Chunk> = world.chunks.values().collect();
- plr.update(&rl, &active_chunks);
- plr.apply_to_camera(&mut cam);
+ let active_chunks: Vec<&Chunk> = world.chunks.values().collect();
+ plr.update(&rl, &active_chunks);
+ plr.apply_to_camera(&mut cam);
let fps = rl.get_fps();
-
- if rend_tex.width() != rl.get_render_width() || rend_tex.height() != rl.get_render_height() {
- rend_tex = unsafe { load_depth_tex(rl.get_render_width(), rl.get_render_height()) };
+
+ if rend_tex.width() != rl.get_render_width() || rend_tex.height() != rl.get_render_height()
+ {
+ unsafe { rlb::ffi::rlUnloadTexture(normal_tex_id) };
+ (rend_tex, normal_tex_id) =
+ load_depth_tex(rl.get_render_width(), rl.get_render_height());
// rend_tex = rl.load_render_texture
- // (&rl_thd, rl.get_render_width() as u32, rl.get_render_height() as u32).unwrap();
+ // (&rl_thd, rl.get_render_width() as u32, rl.get_render_height() as u32).unwrap();
}
+ post_shader.set_shader_value(loc_tan, (cam.fovy.to_radians() * 0.5).tan());
+ post_shader.set_shader_value(loc_asp, rend_tex.width() as f32 / rend_tex.height() as f32);
+
rl.draw(&rl_thd, |mut d| {
d.draw_texture_mode(&rl_thd, &mut rend_tex, |mut tx| {
tx.clear_background(Color::new(30, 30, 30, 255));
tx.draw_mode3D(cam, |mut d3, _| {
d3.draw_grid(100, 1f32);
- for chunk in world.chunks.values() {
- if !chunk.is_visible(&cam) {
- continue;
- }
- if let Some(ref mesh) = chunk.mesh {
- d3.draw_mesh(mesh,
- chunk_material.clone(),
- Matrix::translate(
- chunk.chunk_pos.x * CHUNK_SIZE as f32,
- chunk.chunk_pos.y * CHUNK_SIZE as f32,
- chunk.chunk_pos.z * CHUNK_SIZE as f32,
- )
- );
- }
- // chunk.draw(&mut shd);
- }
+ for chunk in world.chunks.values() {
+ if let Some(ref mesh) = chunk.mesh {
+ d3.draw_mesh(
+ mesh,
+ chunk_material.clone(),
+ Matrix::translate(
+ chunk.chunk_pos.x * CHUNK_SIZE as f32,
+ chunk.chunk_pos.y * CHUNK_SIZE as f32,
+ chunk.chunk_pos.z * CHUNK_SIZE as f32,
+ ),
+ );
+ }
+ // chunk.draw(&mut shd);
+ }
});
});
- post_shader.set_shader_value_texture(
- post_shader.get_shader_location("depth_tex"),
- unsafe { Texture2D::from_raw(rend_tex.depth).make_weak() }
- );
+ post_shader
+ .set_shader_value_texture(post_shader.get_shader_location("depth_tex"), unsafe {
+ Texture2D::from_raw(rend_tex.depth).make_weak()
+ });
d.draw_shader_mode(&mut post_shader, |mut shd| {
- unsafe {
- rlb::ffi::rlSetUniformSampler(
- depth_loc,
- rend_tex.depth.id
- );
- }
- shd.draw_texture_rec(&rend_tex, Rectangle{
- x: 0f32,
- y: 0f32,
- width: rend_tex.texture().width as f32,
- height: -rend_tex.texture().height as f32
- }, Vector2::zero(), Color::WHITE);
+ unsafe {
+ rlb::ffi::rlSetUniformSampler(depth_loc, rend_tex.depth.id);
+ rlb::ffi::rlSetUniformSampler(normal_loc, normal_tex_id);
+ }
+ shd.draw_texture_rec(
+ &rend_tex,
+ Rectangle {
+ x: 0f32,
+ y: 0f32,
+ width: rend_tex.texture().width as f32,
+ height: -rend_tex.texture().height as f32,
+ },
+ Vector2::zero(),
+ Color::WHITE,
+ );
});
d.draw_text(
&format!(
diff --git a/src/util/mod.rs b/src/util/mod.rs
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -1,5 +1,6 @@
use super::rlb;
use rlb::prelude::*;
+use sola_raylib::ffi::rlActiveDrawBuffers;
// use rlb::core::*;
pub struct Cube {
@@ -10,11 +11,11 @@
impl Cube {
pub fn new(params: Vector3) -> Self {
- Self {
- width: params.x,
- height: params.y,
- length: params.z,
- }
+ Self {
+ width: params.x,
+ height: params.y,
+ length: params.z,
+ }
}
}
@@ -25,68 +26,89 @@
}
impl Aabb {
- pub fn overlaps (&self, other: &Aabb) -> bool {
- self.min.x < other.max.x && self.max.x > other.min.x &&
- self.min.y < other.max.y && self.max.y > other.min.y &&
- self.min.z < other.max.z && self.max.z > other.min.z
+ pub fn overlaps(&self, other: &Aabb) -> bool {
+ self.min.x < other.max.x
+ && self.max.x > other.min.x
+ && self.min.y < other.max.y
+ && self.max.y > other.min.y
+ && self.min.z < other.max.z
+ && self.max.z > other.min.z
}
}
// had to do this ;(
-pub fn load_depth_tex(width: i32, height: i32) -> RenderTexture2D {
+pub fn load_depth_tex(width: i32, height: i32) -> (RenderTexture2D, u32) {
unsafe {
- let fbo_id = rlb::ffi::rlLoadFramebuffer();
- rlb::ffi::rlEnableFramebuffer(fbo_id);
+ let fbo_id = rlb::ffi::rlLoadFramebuffer();
+ rlb::ffi::rlEnableFramebuffer(fbo_id);
+
+ let col_tex_id = rlb::ffi::rlLoadTexture(
+ std::ptr::null(),
+ width,
+ height,
+ rlb::ffi::PixelFormat::PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 as i32,
+ 1,
+ );
- let col_tex_id = rlb::ffi::rlLoadTexture(
- std::ptr::null(),
- width,
- height,
- rlb::ffi::PixelFormat::PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 as i32,
- 1
- );
+ rlb::ffi::rlFramebufferAttach(
+ fbo_id,
+ col_tex_id,
+ rlb::ffi::rlFramebufferAttachType::RL_ATTACHMENT_COLOR_CHANNEL0 as i32,
+ rlb::ffi::rlFramebufferAttachTextureType::RL_ATTACHMENT_TEXTURE2D as i32,
+ 0,
+ );
- rlb::ffi::rlFramebufferAttach(
- fbo_id,
- col_tex_id,
- rlb::ffi::rlFramebufferAttachType::RL_ATTACHMENT_COLOR_CHANNEL0 as i32,
- rlb::ffi::rlFramebufferAttachTextureType::RL_ATTACHMENT_TEXTURE2D as i32,
- 0
- );
+ let depth_tex_id = rlb::ffi::rlLoadTextureDepth(width, height, false);
- let depth_tex_id = rlb::ffi::rlLoadTextureDepth(width, height, false);
+ rlb::ffi::rlFramebufferAttach(
+ fbo_id,
+ depth_tex_id,
+ rlb::ffi::rlFramebufferAttachType::RL_ATTACHMENT_DEPTH as i32,
+ rlb::ffi::rlFramebufferAttachTextureType::RL_ATTACHMENT_TEXTURE2D as i32,
+ 0,
+ );
- rlb::ffi::rlFramebufferAttach(
- fbo_id,
- depth_tex_id,
- rlb::ffi::rlFramebufferAttachType::RL_ATTACHMENT_DEPTH as i32,
- rlb::ffi::rlFramebufferAttachTextureType::RL_ATTACHMENT_TEXTURE2D as i32,
- 0
- );
-
- let fbo_complete = rlb::ffi::rlFramebufferComplete(fbo_id);
- rlb::ffi::rlDisableFramebuffer();
- assert!(
- fbo_complete,
- "Framebuffer incomplete!"
- );
-
- RenderTexture2D::from_raw(rlb::ffi::RenderTexture2D {
- id: fbo_id,
- texture: rlb::ffi::Texture2D {
- id: col_tex_id,
- width,
- height,
- mipmaps: 1,
- format: rlb::ffi::PixelFormat::PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 as i32,
- },
- depth: rlb::ffi::Texture2D {
- id: depth_tex_id,
- width,
- height,
- mipmaps: 1,
- format: 19,
- },
- })
+ let normal_tex_id = rlb::ffi::rlLoadTexture(
+ std::ptr::null(),
+ width,
+ height,
+ rlb::ffi::PixelFormat::PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 as i32,
+ 1,
+ );
+
+ rlb::ffi::rlFramebufferAttach(
+ fbo_id,
+ normal_tex_id,
+ rlb::ffi::rlFramebufferAttachType::RL_ATTACHMENT_COLOR_CHANNEL1 as i32,
+ rlb::ffi::rlFramebufferAttachTextureType::RL_ATTACHMENT_TEXTURE2D as i32,
+ 0,
+ );
+
+ rlb::ffi::rlActiveDrawBuffers(2);
+
+ let fbo_complete = rlb::ffi::rlFramebufferComplete(fbo_id);
+ rlb::ffi::rlDisableFramebuffer();
+ assert!(fbo_complete, "Framebuffer incomplete!");
+
+ (
+ RenderTexture2D::from_raw(rlb::ffi::RenderTexture2D {
+ id: fbo_id,
+ texture: rlb::ffi::Texture2D {
+ id: col_tex_id,
+ width,
+ height,
+ mipmaps: 1,
+ format: rlb::ffi::PixelFormat::PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 as i32,
+ },
+ depth: rlb::ffi::Texture2D {
+ id: depth_tex_id,
+ width,
+ height,
+ mipmaps: 1,
+ format: 19,
+ },
+ }),
+ normal_tex_id,
+ )
}
}