Created
December 18, 2023 18:05
-
-
Save lucasdamianjohnson/a52c38e54b0d2180328c04245ab6dd23 to your computer and use it in GitHub Desktop.
Voxel Gen Test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@group(0) @binding(0) var<storage, read_write> WORLD_DATA: array<vec2u>; | |
struct TEMPLATE_DATA_STRUCT { | |
segment_1: u32, | |
segment_2: u32, | |
segment_3: array<u32,12>, | |
segment_4: array<u32,3> | |
} | |
@group(0) @binding(1) var<storage, read_write> TEMPLATE_DATA: array<TEMPLATE_DATA_STRUCT>; | |
@group(0) @binding(2) var<uniform> processingOptions: vec3<f32>; | |
@group(0) @binding(3) var<uniform> perlinPool: array<vec4f,4096>; | |
fn generate_column(column_position: vec3<f32>) { | |
//put code here | |
let minY: f32 = 10; | |
var chunk_type: f32 = 1; | |
if(column_position.x % 2 == 1 || column_position.z % 2 == 1) { | |
chunk_type = 0; | |
} | |
let offset = vec3f(-10000,0,10000 - 64); | |
let height: f32 = 110; | |
for (var x = column_position.x; x < column_position.x + voxel_world.column_size.x; x += 1.) { | |
for (var z = column_position.z; z < column_position.z + voxel_world.column_size.z; z += 1.) { | |
for (var y = 0.; y < voxel_world.column_size.y; y += 1.) { | |
if(y > 120) { | |
continue; | |
} | |
var place_voxel : bool = false; | |
var r = perlin_noise_3d(vec3f((x + offset.x) / 20 ,(y + offset.y) / 20,(z + offset.z) / 20)) * .2; | |
if(y > 30) { | |
var n = perlin_noise_3d(vec3f((x + offset.x) / 100 ,(y + offset.y) / 100,(z + offset.z) / 100)) * (50 + height); | |
if((r > .1 && r < .8) && y <= n) { | |
place_voxel = true; | |
} | |
} | |
if(y <= 30){ | |
var n = perlin_noise_3d(vec3f((x + offset.x) / 50 ,(y + offset.y) / 100,(z + offset.z) / 200)) * 50; | |
if((r > .1 && r < .8) || y <= n) { | |
place_voxel = true; | |
} | |
} | |
if(y == 0) { | |
place_voxel = true; | |
} | |
if(place_voxel && y <= 40) { | |
set_voxel( | |
vec3(x,y,z), | |
Voxel( | |
21, | |
0, | |
Light(0,0,0,0), | |
State(0,0,0) | |
) | |
); | |
} | |
if(place_voxel && y > 40) { | |
if(perlin_noise_3d(vec3f(x,y,z)) < .5) { | |
set_voxel( | |
vec3(x,y,z), | |
Voxel( | |
21, | |
0, | |
Light(0,0,0,0), | |
State(0,0,0) | |
) | |
); | |
} else { | |
set_voxel( | |
vec3(x,y,z), | |
Voxel( | |
25, | |
0, | |
Light(0,15,0,15), | |
State(0,0,0) | |
) | |
); | |
} | |
} | |
if( y < 40 && !place_voxel) { | |
set_voxel( | |
vec3(x,y,z), | |
Voxel( | |
32, | |
0, | |
Light(0,0,0,0), | |
State(0,0,0) | |
) | |
); | |
} | |
} | |
} | |
} | |
} | |
fn index_cos(index : f32) -> f32 { | |
return cos( index * 0.017453292519943295 * 0.5); | |
} | |
fn noise_fsc(i: f32) -> f32 { | |
// using cosine lookup table | |
return ( | |
0.5 * | |
(1.0 - | |
index_cos( | |
floor(i * 360) % 720) | |
) | |
); | |
} | |
fn index_perlin_pool(index: u32) -> f32 { | |
return perlinPool[index].x; | |
} | |
fn perlin_noise_3d(position: vec3f ) -> f32 { | |
var x = position.x; | |
var y = position.y; | |
var z = position.z; | |
if (x < 0) { | |
x = -x; | |
} | |
if (y < 0) { | |
y = -y; | |
} | |
if (z < 0) { | |
z = -z; | |
} | |
var xi = u32(floor(x)); | |
var yi = u32(floor(y)); | |
var zi = u32(floor(z)); | |
var nxf: f32 = x - f32(xi); | |
var yf: f32 = y - f32(yi); | |
var zf: f32 = z - f32(zi); | |
var rxf: f32 = 0; | |
var ryf: f32 = 0; | |
var r: f32 = 0; | |
var ampl: f32 = 0.5; | |
var n1: f32 = 0; | |
var n2: f32 = 0; | |
var n3: f32 = 0; | |
let PERLIN_SIZE: u32 = 4095; | |
let PERLIN_YWRAP: u32 = 16; | |
let PERLIN_YWRAPB: u32 = 4; | |
let PERLIN_ZWRAP: u32 = 256; | |
let PERLIN_ZWRAPB: u32 = 8; | |
for (var o = 0; o < 4; o++) { | |
var xf = f32(u32(xi) + (u32(yi) << u32(PERLIN_YWRAPB)) + (u32(zi) << u32(PERLIN_ZWRAPB))); | |
rxf = noise_fsc(nxf); | |
ryf = noise_fsc(yf); | |
n1 = index_perlin_pool( | |
u32(xf) & PERLIN_SIZE | |
); | |
n1 += rxf * | |
(index_perlin_pool( | |
(u32(xf + 1)) & PERLIN_SIZE) - n1 | |
); | |
n2 = index_perlin_pool( | |
(u32(xf) + PERLIN_YWRAP) & PERLIN_SIZE | |
); | |
n2 += | |
rxf * | |
(index_perlin_pool( | |
(u32(xf) + PERLIN_YWRAP + 1) & PERLIN_SIZE) - n2 | |
); | |
n1 += ryf * (n2 - n1); | |
xf += f32(PERLIN_ZWRAP); | |
n2 = index_perlin_pool( | |
u32(xf) & PERLIN_SIZE | |
); | |
n2 += rxf * (index_perlin_pool( | |
(u32(xf + 1)) & PERLIN_SIZE) - n2 | |
); | |
n3 = index_perlin_pool( | |
(u32(xf) + PERLIN_YWRAP) & PERLIN_SIZE | |
); | |
n3 += | |
rxf * | |
(index_perlin_pool( | |
(u32(xf) + PERLIN_YWRAP + 1) & PERLIN_SIZE) - n3 | |
); | |
n2 += ryf * (n3 - n2); | |
n1 += noise_fsc(zf) * (n2 - n1); | |
r += n1 * ampl; | |
ampl *= 0.5; | |
xi <<= 1; | |
nxf *= 2; | |
yi <<= 1; | |
yf *= 2; | |
zi <<= 1; | |
zf *= 2; | |
if (nxf >= 1.0) { | |
xi++; | |
nxf -= 1; | |
} | |
if (yf >= 1.0) { | |
yi++; | |
yf -= 1; | |
} | |
if (zf >= 1.0) { | |
zi++; | |
zf -= 1; | |
} | |
} | |
return r; | |
} | |
; | |
//math | |
const directions = array<vec3<f32>, 6>( | |
vec3<f32>(1,0,0) | |
,vec3<f32>(-1,0,0) | |
,vec3<f32>(0,0,1) | |
,vec3<f32>(0,0,-1) | |
,vec3<f32>(0,1,0) | |
,vec3<f32>(0,-1,0) | |
); | |
fn get_position_from_index(index: f32, bounds: vec3<f32>) -> vec3<f32> { | |
return vec3<f32>( | |
floor(index % bounds.y), | |
floor((index / bounds.y) % bounds.x), | |
floor(index / (bounds.x * bounds.z)) | |
); | |
} | |
fn get_index_from_position(position: vec3<f32>, bounds: vec3<f32>) -> f32 { | |
return position.z + position.x * bounds.z + position.y * bounds.z * bounds.x; | |
} | |
//https://stackoverflow.com/questions/12964279/whats-the-origin-of-this-glsl-rand-one-liner | |
fn rand(co : vec2<f32>) -> f32 { | |
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453); | |
} | |
//world | |
struct VoxelWorld { | |
process_size: vec3<f32>, | |
region_size: vec3<f32>, | |
column_size: vec3<f32>, | |
chunk_size: vec3<f32> | |
} | |
const voxel_world = VoxelWorld( | |
vec3<f32>(256,128,256), | |
vec3<f32>(256,128,256), | |
vec3<f32>(16,128,16), | |
vec3<f32>(16,16,16) | |
); | |
fn get_voxel_position_from_index(index: f32) -> vec3<f32> { | |
return get_position_from_index(index,voxel_world.process_size); | |
} | |
fn get_voxel_index_from_position(position: vec3<f32>) -> f32 { | |
return get_index_from_position(position, voxel_world.process_size); | |
} | |
fn is_in_bounds(position: vec3<f32>) -> bool { | |
if(position.x < 0 || position.x > 256){ return false;} | |
if(position.y < 0 || position.y > 128){ return false;} | |
if(position.z < 0 || position.z > 256){ return false;} | |
return true; | |
} | |
//light | |
struct Light { | |
sun: u32, | |
red: u32, | |
green: u32, | |
blue: u32, | |
} | |
const light_mask: u32 = 0xf; | |
fn decode_light(data: u32) -> Light { | |
return Light( | |
light_mask & data, | |
((light_mask << 4) & data) >> 4, | |
((light_mask << 8) & data) >> 8, | |
((light_mask << 12) & data) >> 12 | |
); | |
} | |
fn encode_light(light: Light) -> u32 { | |
var data: u32 = 0; | |
data = (data & ~light_mask) | light.sun; | |
data = (data & ~(light_mask << 4)) | (light.red << 4); | |
data = (data & ~(light_mask << 8)) | (light.green << 8); | |
data = (data & ~(light_mask << 12)) | (light.blue << 12); | |
return data; | |
} | |
//state | |
const level_mask: u32 = 15; | |
const level_state_mask: u32 = 48; | |
const shape_state_mask: u32 = 65472; | |
struct State { | |
level: u32, | |
level_state: u32, | |
shape: u32, | |
} | |
fn decode_state(data: u32) -> State { | |
return State( | |
data & level_mask, | |
(data & level_state_mask) >> 4, | |
(data & shape_state_mask) >> 6 | |
); | |
} | |
fn encode_state(state: State) -> u32 { | |
var data: u32 = 0; | |
data = (data & ~level_mask) | state.level; | |
data = (data & ~level_state_mask) | (state.level_state << 4); | |
return (data & ~shape_state_mask) | (state.shape << 6); | |
} | |
//voxels | |
struct Voxel { | |
id: u32, | |
secondary_id: u32, | |
light: Light, | |
state: State | |
} | |
struct VoxelSegments { | |
id: u32, | |
light: u32, | |
state: u32, | |
secondary_id: u32, | |
} | |
const segment_mask: u32 = 0xffff; | |
fn get_voxel_segments(data: vec2u) -> VoxelSegments { | |
let raw_seg1 = data.x; | |
let raw_seg2 = data.y; | |
return VoxelSegments( | |
data.x & segment_mask, | |
(data.x & (segment_mask << 16)) >> 16, | |
data.y & segment_mask, | |
(data.y & (segment_mask << 16)) >> 16, | |
); | |
} | |
fn encode_voxel_segments(segments: VoxelSegments) -> vec2u { | |
var raw = vec2u(0,0); | |
raw.x = segments.id; | |
raw.x = (raw.x & ~(segment_mask << 16)) | (segments.light << 16); | |
raw.y = segments.state ; | |
raw.y = (raw.y & ~(segment_mask << 16)) | (segments.secondary_id << 16); | |
return raw; | |
} | |
fn voxel_to_segments(voxel: Voxel) -> VoxelSegments { | |
return VoxelSegments( | |
voxel.id, | |
encode_light(voxel.light), | |
encode_state(voxel.state), | |
voxel.secondary_id | |
); | |
} | |
fn voxel_to_raw_data(voxel: Voxel) -> vec2u { | |
return encode_voxel_segments( | |
voxel_to_segments(voxel) | |
); | |
} | |
fn decode_voxel_segments(voxel_segments: VoxelSegments) -> Voxel { | |
//state | |
let state: u32 = 0; | |
//level | |
let level: u32 = 0; | |
let level_state: u32 = 0; | |
return Voxel( | |
voxel_segments.id, | |
voxel_segments.secondary_id, | |
decode_light(voxel_segments.light), | |
decode_state(voxel_segments.state) | |
); | |
} | |
fn get_voxel(position: vec3<f32>) -> Voxel { | |
let voxel_segments = get_voxel_segments(WORLD_DATA[i32( | |
get_voxel_index_from_position(position) | |
)]); | |
return decode_voxel_segments(voxel_segments); | |
} | |
fn set_voxel(position: vec3<f32>, voxel: Voxel) { | |
let voxel_index = get_voxel_index_from_position(position); | |
WORLD_DATA[i32(voxel_index)] = voxel_to_raw_data(voxel); | |
} | |
const sun_light_proagation_amount: u32 = 2; | |
const sun_light_start: f32 = 128; | |
fn is_less_than_for_sun_add(main_voxel: Voxel,other_voxel: Voxel) -> bool { | |
return other_voxel.light.sun + sun_light_proagation_amount < main_voxel.light.sun; | |
} | |
fn is_less_than_for_sun_add_down(main_voxel: Voxel,other_voxel: Voxel) -> bool { | |
if(main_voxel.light.sun == 15) { | |
return other_voxel.light.sun < main_voxel.light.sun; | |
} | |
return other_voxel.light.sun + sun_light_proagation_amount < main_voxel.light.sun; | |
} | |
fn is_less_than_for_sun_add_up(main_voxel: Voxel,other_voxel: Voxel) -> bool { | |
if(other_voxel.light.sun == 15) { | |
return main_voxel.light.sun < other_voxel.light.sun; | |
} | |
return main_voxel.light.sun + sun_light_proagation_amount < other_voxel.light.sun; | |
} | |
fn get_minus_one_for_sun(main_voxel: Voxel,other_voxel: Voxel) -> u32 { | |
var value = main_voxel.light.sun - sun_light_proagation_amount; | |
if(value < 0) { | |
value = 0; | |
} | |
if(value < other_voxel.light.sun) { | |
value = other_voxel.light.sun; | |
} | |
return value; | |
} | |
fn get_minus_one_for_sun_under_voxel(main_voxel: Voxel,other_voxel: Voxel) -> u32 { | |
var s = main_voxel.light.sun; | |
var sn = other_voxel.light.sun; | |
if (s == 15) { | |
sn = s; | |
} | |
if (s < 15) { | |
sn = s - sun_light_proagation_amount; | |
} | |
return sn; | |
} | |
fn can_add_light(voxel:Voxel)-> bool { | |
if(voxel.light.red > 0 || voxel.light.green > 0 || voxel.light.blue > 0) {return true;} | |
if(voxel.id <= 2) { return true;} | |
return false; | |
} | |
fn run_sun_light_fill(voxel_position: vec3<f32>) { | |
var main_voxel = get_voxel(voxel_position); | |
var position : vec3<f32> = vec3(voxel_position.x,voxel_position.y ,voxel_position.z); | |
if(voxel_position.y >= sun_light_start) { | |
main_voxel.light.sun = 15; | |
set_voxel(voxel_position,main_voxel); | |
for(var y = voxel_position.y - 1; y > 0; y -= 1.) { | |
position = vec3(voxel_position.x,y,voxel_position.z); | |
var other_voxel = get_voxel(position); | |
if(can_add_light(other_voxel)) { | |
other_voxel.light.sun = get_minus_one_for_sun_under_voxel(main_voxel,other_voxel); | |
set_voxel(position,other_voxel); | |
} else { | |
break; | |
} | |
} | |
} | |
} | |
const rgb_light_proagation_amount = 1; | |
fn run_light_flood(voxel_position: vec3<f32>) -> f32 { | |
var main_voxel = get_voxel(voxel_position); | |
var position : vec3<f32> = vec3(voxel_position.x,voxel_position.y,voxel_position.z); | |
if(!can_add_light(main_voxel)) {return 0;} | |
for(var i = 0; i < 6; i++ ){ | |
var direction = directions[i]; | |
position = vec3( | |
voxel_position.x + direction.x, | |
voxel_position.y + direction.y, | |
voxel_position.z + direction.z | |
); | |
if(is_in_bounds(position)) { | |
var other_voxel = get_voxel(position); | |
if(main_voxel.light.sun + sun_light_proagation_amount < other_voxel.light.sun) { | |
var value = other_voxel.light.sun - sun_light_proagation_amount; | |
if(value < 0) { | |
value = 0; | |
} | |
if(value < main_voxel.light.sun) { | |
value = main_voxel.light.sun; | |
} | |
main_voxel.light.sun = value; | |
} | |
if(main_voxel.light.red + 2 <= other_voxel.light.red) { | |
var value = other_voxel.light.red - rgb_light_proagation_amount; | |
if(value < 0) { | |
value = 0; | |
} | |
if(value < main_voxel.light.red) { | |
value = main_voxel.light.red; | |
} | |
main_voxel.light.red = value; | |
} | |
if(main_voxel.light.green + 2 <= other_voxel.light.green) { | |
var value = other_voxel.light.green - rgb_light_proagation_amount; | |
if(value < 0) { | |
value = 0; | |
} | |
if(value < main_voxel.light.green) { | |
value = main_voxel.light.green; | |
} | |
main_voxel.light.green = value; | |
} | |
if(main_voxel.light.blue + 2 <= other_voxel.light.blue) { | |
var value = other_voxel.light.blue - rgb_light_proagation_amount; | |
if(value < 0) { | |
value = 0; | |
} | |
if(value < main_voxel.light.blue) { | |
value = main_voxel.light.blue; | |
} | |
main_voxel.light.blue = value; | |
} | |
} | |
} | |
set_voxel(voxel_position,main_voxel); | |
return 1; | |
} | |
struct CheckSetQuad { | |
p1: array<f32,9>, | |
p2: array<f32,9>, | |
p3: array<f32,9>, | |
p4: array<f32,9>, | |
} | |
struct GradientCheckSets { | |
top: CheckSetQuad, | |
bottom: CheckSetQuad, | |
west: CheckSetQuad, | |
east: CheckSetQuad, | |
north: CheckSetQuad, | |
south: CheckSetQuad | |
} | |
const GradientCheckSet = | |
GradientCheckSets( | |
//top | |
CheckSetQuad( | |
array<f32,9>(-1, 1, 0, 0, 1, -1, -1, 1, -1), | |
array<f32,9>(-1, 1, 0, 0, 1, 1, -1, 1, 1), | |
array<f32,9>(1, 1, 0, 0, 1, 1, 1, 1, 1), | |
array<f32,9>(1, 1, 0, 0, 1, -1, 1, 1, -1) | |
), | |
//bottom | |
CheckSetQuad( | |
array<f32,9>(0, -1, -1, -1, -1, 0, -1, -1, -1), | |
array<f32,9>(0, -1, -1, 1, -1, 0, 1, -1, -1), | |
array<f32,9>(0, -1, 1, 1, -1, 0, 1, -1, 1), | |
array<f32,9>(0, -1, 1, -1, -1, 0, -1, -1, 1) | |
), | |
//west | |
CheckSetQuad( | |
array<f32,9>(-1, 0, 1, -1, 1, 0, -1, 1, 1), | |
array<f32,9>(-1, 0, -1, -1, 1, 0, -1, 1, -1), | |
array<f32,9>(-1, 0, -1, -1, -1, 0, -1, -1, -1), | |
array<f32,9>(-1, 0, 1, -1, -1, 0, -1, -1, 1) | |
), | |
//east | |
CheckSetQuad( | |
array<f32,9>(1, 0, -1, 1, 1, 0, 1, 1, -1), | |
array<f32,9>(1, 0, 1, 1, 1, 0, 1, 1, 1), | |
array<f32,9>(1, 0, 1, 1, -1, 0, 1, -1, 1), | |
array<f32,9>(1, 0, -1, 1, -1, 0, 1, -1, -1) | |
), | |
//north | |
CheckSetQuad( | |
array<f32,9>(1, 0, 1, 0, 1, 1, 1, 1, 1), | |
array<f32,9>(-1, 0, 1, 0, 1, 1, -1, 1, 1), | |
array<f32,9>(-1, 0, 1, 0, -1, 1, -1, -1, 1), | |
array<f32,9>(1, 0, 1, 0, -1, 1, 1, -1, 1) | |
), | |
//south | |
CheckSetQuad( | |
array<f32,9>(-1, 0, -1, 0, 1, -1, -1, 1, -1), | |
array<f32,9>(1, 0, -1, 0, 1, -1, 1, 1, -1), | |
array<f32,9>(1, 0, -1, 0, -1, -1, 1, -1, -1), | |
array<f32,9>(-1, 0, -1, 0, -1, -1, -1, -1, -1) | |
) | |
); | |
const TEMPLATE_BUFFER_BOUNDS = vec3<f32>( | |
64, | |
128, | |
64 | |
); | |
fn get_voxel_template_index_from_position(position: vec3<f32>) -> f32 { | |
return get_index_from_position( | |
vec3( | |
position.x - processingOptions.y, | |
position.y, | |
position.z - processingOptions.z | |
), | |
TEMPLATE_BUFFER_BOUNDS | |
); | |
} | |
fn get_voxel_raw_template(position: vec3<f32>) -> TEMPLATE_DATA_STRUCT { | |
return TEMPLATE_DATA[ | |
u32(get_voxel_template_index_from_position(position)) | |
]; | |
} | |
fn set_voxel_raw_template(position: vec3<f32>, voxel: TEMPLATE_DATA_STRUCT) { | |
let voxel_index = get_voxel_template_index_from_position(position); | |
TEMPLATE_DATA[u32(voxel_index)] = voxel; | |
} | |
const two_byte_mask: u32 = 0xffff; | |
const byte_mask: u32 = 0xff; | |
const nibble_mask: u32 = 0xf; | |
fn update_voxel_raw_template(position: vec3<f32>,voxel_template: VoxelTemplate) { | |
var raw_template = get_voxel_raw_template(position); | |
raw_template.segment_1 = voxel_template.id; | |
raw_template.segment_1 = | |
(raw_template.segment_1 & ~(two_byte_mask << 16)) | (voxel_template.secondary_id << 16); | |
var face_byte: u32 = 0; | |
if(voxel_template.faces.top) { | |
face_byte |= 1 << 0; | |
} | |
if(voxel_template.faces.bottom) { | |
face_byte |= 1 << 1; | |
} | |
if(voxel_template.faces.west) { | |
face_byte |= 1 << 2; | |
} | |
if(voxel_template.faces.east) { | |
face_byte |= 1 << 3; | |
} | |
if(voxel_template.faces.north) { | |
face_byte |= 1 << 4; | |
} | |
if(voxel_template.faces.south) { | |
face_byte |= 1 << 5; | |
} | |
raw_template.segment_2 = | |
(raw_template.segment_2 & ~(byte_mask << 0)) | (face_byte << 0); | |
//enode light | |
//top | |
{ | |
raw_template.segment_3[0] = encode_light(voxel_template.light.top.p1); | |
raw_template.segment_3[0] = | |
(raw_template.segment_3[0] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.top.p2) << 16); | |
} | |
{ | |
raw_template.segment_3[1] = encode_light(voxel_template.light.top.p3); | |
raw_template.segment_3[1] = | |
(raw_template.segment_3[1] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.top.p4) << 16); | |
} | |
//bottom | |
{ | |
raw_template.segment_3[2] = encode_light(voxel_template.light.bottom.p1); | |
raw_template.segment_3[2] = | |
(raw_template.segment_3[2] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.bottom.p2) << 16); | |
} | |
{ | |
raw_template.segment_3[3] = encode_light(voxel_template.light.bottom.p3); | |
raw_template.segment_3[3] = | |
(raw_template.segment_3[3] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.bottom.p4) << 16); | |
} | |
//west | |
{ | |
raw_template.segment_3[4] = encode_light(voxel_template.light.west.p1); | |
raw_template.segment_3[4] = | |
(raw_template.segment_3[4] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.west.p2) << 16); | |
} | |
{ | |
raw_template.segment_3[5] = encode_light(voxel_template.light.west.p3); | |
raw_template.segment_3[5] = | |
(raw_template.segment_3[5] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.west.p4) << 16); | |
} | |
//east | |
{ | |
raw_template.segment_3[6] = encode_light(voxel_template.light.east.p1); | |
raw_template.segment_3[6] = | |
(raw_template.segment_3[6] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.east.p2) << 16); | |
} | |
{ | |
raw_template.segment_3[7] = encode_light(voxel_template.light.east.p3); | |
raw_template.segment_3[7] = | |
(raw_template.segment_3[7] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.east.p4) << 16); | |
} | |
//north | |
{ | |
raw_template.segment_3[8] = encode_light(voxel_template.light.north.p1); | |
raw_template.segment_3[8] = | |
(raw_template.segment_3[8] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.north.p2) << 16); | |
} | |
{ | |
raw_template.segment_3[9] = encode_light(voxel_template.light.north.p3); | |
raw_template.segment_3[9] = | |
(raw_template.segment_3[9] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.north.p4) << 16); | |
} | |
//south | |
{ | |
raw_template.segment_3[10] = encode_light(voxel_template.light.south.p1); | |
raw_template.segment_3[10] = | |
(raw_template.segment_3[10] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.south.p2) << 16); | |
} | |
{ | |
raw_template.segment_3[11] = encode_light(voxel_template.light.south.p3); | |
raw_template.segment_3[11] = | |
(raw_template.segment_3[11] & ~(two_byte_mask << 16)) | |
| (encode_light(voxel_template.light.south.p4) << 16); | |
} | |
//encode AO | |
{ | |
raw_template.segment_4[0] = encode_ao(voxel_template.ao.top); | |
raw_template.segment_4[0] = | |
(raw_template.segment_4[0] & ~(two_byte_mask << 16)) | |
| (encode_ao(voxel_template.ao.bottom) << 16); | |
} | |
{ | |
raw_template.segment_4[1] = encode_ao(voxel_template.ao.west); | |
raw_template.segment_4[1] = | |
(raw_template.segment_4[1] & ~(two_byte_mask << 16)) | |
| (encode_ao(voxel_template.ao.east) << 16); | |
} | |
{ | |
raw_template.segment_4[2] = encode_ao(voxel_template.ao.north); | |
raw_template.segment_4[2] = | |
(raw_template.segment_4[2] & ~(two_byte_mask << 16)) | |
| (encode_ao(voxel_template.ao.south) << 16); | |
} | |
set_voxel_raw_template(position,raw_template); | |
} | |
fn encode_ao(quad:AOQuad) -> u32 { | |
var data: u32 = 0; | |
data = (data & ~nibble_mask) | quad.p1; | |
data = (data & ~(nibble_mask << 4)) | (quad.p2 << 4); | |
data = (data & ~(nibble_mask << 8)) | (quad.p3 << 8); | |
data = (data & ~(nibble_mask << 12)) | (quad.p4 << 12); | |
return data; | |
} | |
fn clear_voxel_raw_template(position: vec3<f32>) { | |
var raw_template = get_voxel_raw_template(position); | |
raw_template.segment_1 = 0; | |
raw_template.segment_2 = 0; | |
for(var i = 0; i < 12; i++) { | |
raw_template.segment_3[i] = 0; | |
} | |
for(var i = 0; i < 3; i++) { | |
raw_template.segment_4[i] = 0; | |
} | |
set_voxel_raw_template(position,raw_template); | |
} | |
//light gradient | |
struct LightQuad { | |
p1: Light, | |
p2: Light, | |
p3: Light, | |
p4: Light | |
} | |
struct AOQuad { | |
p1: u32, | |
p2: u32, | |
p3: u32, | |
p4: u32 | |
} | |
//voxel template | |
struct VoxelAOTemplate { | |
top: AOQuad, | |
bottom: AOQuad, | |
west: AOQuad, | |
east: AOQuad, | |
north: AOQuad, | |
south: AOQuad | |
} | |
struct VoxelLightTemplate { | |
top: LightQuad, | |
bottom: LightQuad, | |
west: LightQuad, | |
east: LightQuad, | |
north: LightQuad, | |
south: LightQuad | |
} | |
struct VoxelExposedFacesTemplate { | |
top: bool, | |
bottom: bool, | |
west: bool, | |
east: bool, | |
north: bool, | |
south: bool | |
} | |
struct VoxelTemplate { | |
id: u32, | |
secondary_id: u32, | |
light: VoxelLightTemplate, | |
ao: VoxelAOTemplate, | |
faces: VoxelExposedFacesTemplate, | |
} | |
fn get_light_quad() -> LightQuad { | |
return LightQuad( | |
Light(0,0,0,0), | |
Light(0,0,0,0), | |
Light(0,0,0,0), | |
Light(0,0,0,0) | |
); | |
} | |
fn get_ao_quad() -> AOQuad { | |
return AOQuad( | |
1, | |
1, | |
1, | |
1, | |
); | |
} | |
fn get_voxel_light_template() -> VoxelLightTemplate { | |
return VoxelLightTemplate( | |
get_light_quad(), | |
get_light_quad(), | |
get_light_quad(), | |
get_light_quad(), | |
get_light_quad(), | |
get_light_quad(), | |
); | |
} | |
fn get_voxel_ao_template() -> VoxelAOTemplate { | |
return VoxelAOTemplate( | |
get_ao_quad(), | |
get_ao_quad(), | |
get_ao_quad(), | |
get_ao_quad(), | |
get_ao_quad(), | |
get_ao_quad() | |
); | |
} | |
fn get_voxel_exposed_faces() -> VoxelExposedFacesTemplate { | |
return VoxelExposedFacesTemplate( | |
false, | |
false, | |
false, | |
false, | |
false, | |
false | |
); | |
} | |
fn get_voxel_template() -> VoxelTemplate { | |
return VoxelTemplate( | |
0, | |
0, | |
get_voxel_light_template(), | |
get_voxel_ao_template(), | |
get_voxel_exposed_faces() | |
); | |
} | |
fn is_voxel_renerable(voxel: Voxel) -> bool { | |
if(voxel.id < 2) {return false;} | |
return true; | |
} | |
fn is_voxel_face_exposed(direction: vec3<f32>,position: vec3<f32>) -> bool { | |
var check_position = vec3<f32>( | |
direction.x + position.x, direction.y + position.y, direction.z + position.z | |
); | |
if(!is_in_bounds(check_position)){ | |
return true; | |
} | |
var other_voxel = get_voxel(check_position); | |
if(!is_voxel_renerable(other_voxel)) { | |
return true; | |
} | |
return false; | |
} | |
struct LightGradientCheckSetProcessResult { | |
ao: u32, | |
light: Light | |
} | |
fn process_voxel_light_gradient_checkset( | |
position: vec3<f32>, | |
voxel: Voxel, | |
light: Light, | |
ao: u32, | |
check_set: array<f32,9> | |
) -> LightGradientCheckSetProcessResult { | |
var result = LightGradientCheckSetProcessResult( | |
ao,Light(voxel.light.sun,voxel.light.red,voxel.light.green,voxel.light.blue) | |
); | |
for (var i = 0; i < 9; i += 3) { | |
let check_position = vec3( | |
position.x + check_set[i], | |
position.y + check_set[i + 1], | |
position.z + check_set[i + 2] | |
); | |
if(!is_in_bounds(check_position)){ | |
continue; | |
} | |
var check_voxel = get_voxel(check_position); | |
if(is_voxel_renerable(check_voxel)){ | |
result.ao += 1; | |
} | |
if(check_voxel.light.sun > result.light.sun) { | |
result.light.sun += 1; | |
} | |
if(check_voxel.light.red > result.light.red) { | |
result.light.red += 1; | |
} | |
if(check_voxel.light.green > result.light.green) { | |
result.light.green += 1; | |
} | |
if(check_voxel.light.blue > result.light.blue) { | |
result.light.blue += 1; | |
} | |
} | |
return result; | |
} | |
struct LightGradientProcessResult { | |
light: LightQuad, | |
ao: AOQuad, | |
} | |
fn process_voxel_light_gradient( | |
position: vec3<f32>, | |
direction: vec3<f32>, | |
voxel: Voxel, | |
check_set_quad: CheckSetQuad, | |
) -> LightGradientProcessResult { | |
var ao_quad = get_ao_quad(); | |
var light_quad = get_light_quad(); | |
var light_voxel = get_voxel( | |
vec3( | |
position.x + direction.x, | |
position.y + direction.y, | |
position.z + direction.z | |
) | |
); | |
if(light_voxel.light.red < voxel.light.red ) { | |
light_voxel.light.red = voxel.light.red; | |
} | |
if(light_voxel.light.green < voxel.light.green ) { | |
light_voxel.light.green = voxel.light.green; | |
} | |
if(light_voxel.light.blue < voxel.light.blue ) { | |
light_voxel.light.blue = voxel.light.blue; | |
} | |
var p1_result = process_voxel_light_gradient_checkset( | |
position,light_voxel,light_quad.p1,ao_quad.p1,check_set_quad.p1 | |
); | |
light_quad.p1 = p1_result.light; | |
ao_quad.p1 = p1_result.ao; | |
var p2_result = process_voxel_light_gradient_checkset( | |
position,light_voxel,light_quad.p2,ao_quad.p2,check_set_quad.p2 | |
); | |
light_quad.p2 = p2_result.light; | |
ao_quad.p2 = p2_result.ao; | |
var p3_result = process_voxel_light_gradient_checkset( | |
position,light_voxel,light_quad.p3,ao_quad.p3,check_set_quad.p3 | |
); | |
light_quad.p3 = p3_result.light; | |
ao_quad.p3 = p3_result.ao; | |
var p4_result = process_voxel_light_gradient_checkset( | |
position,light_voxel,light_quad.p4,ao_quad.p4,check_set_quad.p4 | |
); | |
light_quad.p4 = p4_result.light; | |
ao_quad.p4 = p4_result.ao; | |
return LightGradientProcessResult( | |
light_quad,ao_quad | |
); | |
} | |
fn process_voxel(position: vec3<f32>) -> f32 { | |
var voxel = get_voxel(position); | |
if(!is_voxel_renerable(voxel)) { | |
clear_voxel_raw_template(position); | |
return 0; | |
} | |
var voxel_template = get_voxel_template(); | |
voxel_template.id = voxel.id; | |
voxel_template.secondary_id = voxel.secondary_id; | |
//top | |
if( | |
is_voxel_face_exposed(vec3(0,1,0),position) | |
) { | |
voxel_template.faces.top = true; | |
let results = process_voxel_light_gradient( | |
position, | |
vec3(0,1,0), | |
voxel, | |
GradientCheckSet.top | |
); | |
voxel_template.light.top = results.light; | |
voxel_template.ao.top = results.ao; | |
} | |
//bottom | |
if( | |
is_voxel_face_exposed(vec3(0,-1,0),position) | |
) { | |
voxel_template.faces.bottom = true; | |
let results = process_voxel_light_gradient( | |
position, | |
vec3(0,-1,0), | |
voxel, | |
GradientCheckSet.bottom | |
); | |
voxel_template.light.bottom = results.light; | |
voxel_template.ao.bottom = results.ao; | |
} | |
//west | |
if( | |
is_voxel_face_exposed(vec3(-1,0,0),position) | |
) { | |
voxel_template.faces.west = true; | |
let results = process_voxel_light_gradient( | |
position, | |
vec3(-1,0,0), | |
voxel, | |
GradientCheckSet.west | |
); | |
voxel_template.light.west = results.light; | |
voxel_template.ao.west = results.ao; | |
} | |
//east | |
if( | |
is_voxel_face_exposed(vec3(1,0,0),position) | |
) { | |
voxel_template.faces.east = true; | |
let results = process_voxel_light_gradient( | |
position, | |
vec3(1,0,0), | |
voxel, | |
GradientCheckSet.east | |
); | |
voxel_template.light.east = results.light; | |
voxel_template.ao.east = results.ao; | |
} | |
//north | |
if( | |
is_voxel_face_exposed(vec3(0,0,1),position) | |
) { | |
voxel_template.faces.north = true; | |
let results = process_voxel_light_gradient( | |
position, | |
vec3(0,0,1), | |
voxel, | |
GradientCheckSet.north | |
); | |
voxel_template.light.north = results.light; | |
voxel_template.ao.north = results.ao; | |
} | |
//south | |
if( | |
is_voxel_face_exposed(vec3(0,0,-1),position) | |
) { | |
voxel_template.faces.south = true; | |
let results = process_voxel_light_gradient( | |
position, | |
vec3(0,0,-1), | |
voxel, | |
GradientCheckSet.south | |
); | |
voxel_template.light.south = results.light; | |
voxel_template.ao.south = results.ao; | |
} | |
update_voxel_raw_template(position,voxel_template); | |
return 1; | |
} | |
@compute @workgroup_size(1) | |
fn computeSomething( | |
@builtin(workgroup_id) workgroup_id : vec3<u32>, | |
@builtin(local_invocation_id) local_invocation_id : vec3<u32>, | |
@builtin(global_invocation_id) global_invocation_id : vec3<u32>, | |
@builtin(local_invocation_index) local_invocation_index: u32, | |
@builtin(num_workgroups) num_workgroups: vec3<u32> | |
) { | |
if(processingOptions.x == 0){ | |
let column_position = vec3<f32>( | |
f32(workgroup_id.x) * voxel_world.column_size.x, | |
f32(processingOptions.y), | |
f32(workgroup_id.y) * voxel_world.column_size.z, | |
); | |
generate_column(column_position); | |
} | |
if(processingOptions.x == 1){ | |
let voxel_position = vec3<f32>( | |
f32(workgroup_id.x), | |
f32(processingOptions.y), | |
f32(workgroup_id.y) | |
); | |
run_sun_light_fill(voxel_position); | |
} | |
if(processingOptions.x == 2){ | |
let voxel_position = vec3<f32>( | |
f32(workgroup_id.x), | |
f32(processingOptions.y), | |
f32(workgroup_id.y) | |
); | |
for(var i = 0; i < 128; i++) { | |
run_light_flood(vec3<f32>( | |
f32(workgroup_id.x), | |
f32(i), | |
f32(workgroup_id.y) | |
)); | |
} | |
} | |
if(processingOptions.x == 3){ | |
process_voxel(vec3<f32>( | |
f32(workgroup_id.x) + processingOptions.y, | |
f32(workgroup_id.z), | |
f32(workgroup_id.y) + processingOptions.z | |
)); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment