Skip to content

Instantly share code, notes, and snippets.

@lucasdamianjohnson
Created December 18, 2023 18:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucasdamianjohnson/a52c38e54b0d2180328c04245ab6dd23 to your computer and use it in GitHub Desktop.
Save lucasdamianjohnson/a52c38e54b0d2180328c04245ab6dd23 to your computer and use it in GitHub Desktop.
Voxel Gen Test
@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