saving for posterity

pull/397/head
Ben Hansen 2 years ago
parent 7c2bfa02bf
commit 0303c307b6

2
.gitignore vendored

@ -12,4 +12,4 @@ output/
secrets.txt
tree.txt
Chunk*.json
Chunk*

@ -159,6 +159,7 @@ struct State {
// NEW!
terrain: terrain::Terrain,
terrain_pipeline: terrain::TerrainPipeline,
terrain_hack_pipeline: terrain::TerrainHackPipeline,
}
fn create_render_pipeline(
@ -507,12 +508,21 @@ impl State {
config.format,
Some(texture::Texture::DEPTH_FORMAT),
);
let terrain_hack_pipeline = terrain::TerrainHackPipeline::new(
&device,
chunk_size,
min_max_height,
&camera_bind_group_layout,
&light_bind_group_layout,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
);
let mut terrain = terrain::Terrain::new(chunk_size, min_max_height);
terrain.gen_chunk(&device, &queue, &terrain_pipeline, cgmath::Vector3::zero());
terrain.gen_chunk(&device, &queue, &terrain_pipeline, (0.0, 0.0, -(chunk_size.y as f32)).into());
terrain.gen_chunk(&device, &queue, &terrain_pipeline, (-(chunk_size.x as f32), 0.0, -(chunk_size.y as f32)).into());
terrain.gen_chunk(&device, &queue, &terrain_pipeline, (-(chunk_size.x as f32), 0.0, 0.0).into());
terrain.gen_chunk(&device, &queue, &terrain_hack_pipeline, cgmath::Vector3::zero());
// terrain.gen_chunk(&device, &queue, &terrain_hack_pipeline, (0.0, 0.0, -(chunk_size.y as f32)).into());
// terrain.gen_chunk(&device, &queue, &terrain_hack_pipeline, (-(chunk_size.x as f32), 0.0, -(chunk_size.y as f32)).into());
// terrain.gen_chunk(&device, &queue, &terrain_hack_pipeline, (-(chunk_size.x as f32), 0.0, 0.0).into());
Self {
surface,
@ -541,6 +551,7 @@ impl State {
// NEW!
terrain,
terrain_pipeline,
terrain_hack_pipeline,
}
}
@ -663,7 +674,7 @@ impl State {
// &self.light_bind_group,
// );
self.terrain_pipeline.render(&mut render_pass, &self.terrain, &self.camera_bind_group, &self.light_bind_group);
self.terrain_hack_pipeline.render(&mut render_pass, &self.terrain, &self.camera_bind_group, &self.light_bind_group);
}
self.queue.submit(iter::once(encoder.finish()));
output.present();
@ -687,6 +698,7 @@ pub async fn run() {
let title = env!("CARGO_PKG_NAME");
let window = winit::window::WindowBuilder::new()
.with_title(title)
.with_visible(false)
.build(&event_loop)
.unwrap();
@ -710,6 +722,7 @@ pub async fn run() {
}
let mut state = State::new(&window).await; // NEW!
window.set_visible(true);
let mut last_render_time = instant::Instant::now();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;

@ -1,6 +1,5 @@
use std::mem::size_of_val;
use crate::{create_render_pipeline, model};
#[repr(C)]
@ -30,12 +29,10 @@ impl Terrain {
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
pipeline: &TerrainPipeline,
pipeline: &impl GenerateChunk,
position: cgmath::Vector3<f32>,
) {
let corner = position.xz().cast().unwrap();
println!("position: {:?}", position);
println!("corner: {:?}", corner);
let mut index = None;
for (i, chunk) in self.chunks.iter().enumerate() {
if chunk.corner == corner {
@ -53,6 +50,16 @@ pub struct Chunk {
mesh: model::Mesh,
}
pub trait GenerateChunk {
fn gen_chunk(
&self,
device: &wgpu::Device,
queue: &wgpu::Queue,
corner: cgmath::Vector2<i32>,
existing_chunk: Option<Chunk>,
) -> Chunk;
}
pub struct TerrainPipeline {
chunk_size: cgmath::Vector2<u32>,
min_max_height: cgmath::Vector2<f32>,
@ -160,6 +167,26 @@ impl TerrainPipeline {
}
}
pub fn render<'a, 'b>(
&'a self,
render_pass: &'b mut wgpu::RenderPass<'a>,
terrain: &'a Terrain,
camera_bind_group: &'a wgpu::BindGroup,
light_bind_group: &'a wgpu::BindGroup,
) {
render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_bind_group(0, camera_bind_group, &[]);
render_pass.set_bind_group(1, light_bind_group, &[]);
for chunk in &terrain.chunks {
render_pass
.set_index_buffer(chunk.mesh.index_buffer.slice(..), chunk.mesh.index_format);
render_pass.set_vertex_buffer(0, chunk.mesh.vertex_buffer.slice(..));
render_pass.draw_indexed(0..chunk.mesh.num_elements, 0, 0..1);
}
}
}
impl GenerateChunk for TerrainPipeline {
fn gen_chunk(
&self,
device: &wgpu::Device,
@ -261,6 +288,128 @@ impl TerrainPipeline {
chunk
}
}
pub struct TerrainHackPipeline {
texture_size: u32,
gen_layout: wgpu::BindGroupLayout,
gen_pipeline: wgpu::RenderPipeline,
render_pipeline: wgpu::RenderPipeline,
chunk_size: cgmath::Vector2<u32>,
min_max_height: cgmath::Vector2<f32>,
}
impl TerrainHackPipeline {
pub fn new(
device: &wgpu::Device,
chunk_size: cgmath::Vector2<u32>,
min_max_height: cgmath::Vector2<f32>,
camera_layout: &wgpu::BindGroupLayout,
light_layout: &wgpu::BindGroupLayout,
color_format: wgpu::TextureFormat,
depth_format: Option<wgpu::TextureFormat>,
) -> Self {
// Given that the vertices in the chunk are 2 vec3s, num_indices should = num_vertices
let texture_size = 512;
let gen_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("HackTerrainPipeline::BindGroupLayout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("HackTerrainPipeline::PipelineLayout"),
bind_group_layouts: &[&gen_layout],
push_constant_ranges: &[],
});
let shader = device.create_shader_module(wgpu::include_wgsl!("terrain.wgsl"));
let gen_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("HackTerrainPipeline::GenPipeline"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "gen_terrain_vertex",
buffers: &[],
},
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
cull_mode: None,
..Default::default()
},
depth_stencil: None,
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "gen_terrain_fragment",
targets: &[
Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::R32Uint,
blend: None,
write_mask: wgpu::ColorWrites::ALL,
}),
Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::R32Uint,
blend: None,
write_mask: wgpu::ColorWrites::ALL,
}),
],
}),
multiview: None,
});
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("TerrainPipeline::Render::PipelineLayout"),
bind_group_layouts: &[camera_layout, light_layout],
push_constant_ranges: &[],
});
let render_pipeline = create_render_pipeline(
device,
&render_pipeline_layout,
color_format,
depth_format,
&[wgpu::VertexBufferLayout {
array_stride: 24,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
format: wgpu::VertexFormat::Float32x3,
offset: 0,
shader_location: 0,
},
wgpu::VertexAttribute {
format: wgpu::VertexFormat::Float32x3,
offset: 12,
shader_location: 1,
},
],
}],
&shader,
);
Self {
chunk_size,
min_max_height,
texture_size,
gen_layout,
gen_pipeline,
render_pipeline,
}
}
pub fn render<'a, 'b>(
&'a self,
@ -279,29 +428,234 @@ impl TerrainPipeline {
render_pass.draw_indexed(0..chunk.mesh.num_elements, 0, 0..1);
}
}
fn create_work_texture(&self, device: &wgpu::Device, index: bool) -> wgpu::Texture {
device.create_texture(&wgpu::TextureDescriptor {
label: Some(if index {
"Index Texture"
} else {
"Vertex Texture"
}),
size: wgpu::Extent3d {
width: self.texture_size,
height: self.texture_size,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::R32Uint,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
})
}
}
impl GenerateChunk for TerrainHackPipeline {
fn gen_chunk(
&self,
device: &wgpu::Device,
queue: &wgpu::Queue,
corner: cgmath::Vector2<i32>,
existing_chunk: Option<Chunk>,
) -> Chunk {
let chunk = if let Some(mut chunk) = existing_chunk {
chunk.corner = corner;
chunk
} else {
let chunk_name = format!("Chunk {:?}", corner);
let num_vertices = (self.chunk_size.x + 1) * (self.chunk_size.y + 1);
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some(&format!("{}: Vertices", chunk_name)),
size: (num_vertices * 8 * std::mem::size_of::<f32>() as u32) as _,
usage: wgpu::BufferUsages::COPY_DST
| wgpu::BufferUsages::VERTEX
| wgpu::BufferUsages::MAP_READ,
mapped_at_creation: false,
});
let num_elements = self.chunk_size.x * self.chunk_size.y * 6;
let index_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some(&format!("{}: Indices", chunk_name)),
size: (num_elements * std::mem::size_of::<u32>() as u32) as _,
usage: wgpu::BufferUsages::COPY_DST
| wgpu::BufferUsages::INDEX
| wgpu::BufferUsages::MAP_READ,
mapped_at_creation: false,
});
Chunk {
corner,
mesh: model::Mesh {
name: chunk_name,
vertex_buffer,
index_buffer,
num_elements,
material: 0,
index_format: wgpu::IndexFormat::Uint32,
},
}
};
let vertex_texture = self.create_work_texture(device, false);
let vertex_view = vertex_texture.create_view(&wgpu::TextureViewDescriptor {
label: Some("HackTerrainPipeline: vertex_view"),
..Default::default()
});
let index_texture = self.create_work_texture(device, true);
let index_view = index_texture.create_view(&wgpu::TextureViewDescriptor {
label: Some("HackTerrainPipeline: index_view"),
..Default::default()
});
pub struct HackTerrainPipeline {
texture_dim: cgmath::Vector2<u32>,
vertex_texture: wgpu::Texture,
index_texture: wgpu::Texture,
gen_layout: wgpu::BindGroupLayout,
gen_pipeline: wgpu::RenderPipeline,
render_pipeline: wgpu::RenderPipeline,
let data = GenData::new(
self.texture_size,
0,
self.chunk_size,
corner,
self.min_max_height,
);
println!("gen data: {:?}", data);
let gen_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("HackTerrainPipeline: GenData"),
size: size_of_val(&data) as _,
usage: wgpu::BufferUsages::UNIFORM
| wgpu::BufferUsages::MAP_READ
| wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
queue.write_buffer(&gen_buffer, 0, bytemuck::bytes_of(&data));
let gen_uniforms = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("HackTerrainPipeline: gen_uniforms"),
layout: &self.gen_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: gen_buffer.as_entire_binding(),
}],
});
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("HackTerrainPipeline: encoder"),
});
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("HackTerrainPipeline: pass"),
color_attachments: &[
Some(wgpu::RenderPassColorAttachment {
view: &vertex_view,
resolve_target: None,
ops: wgpu::Operations::default(),
}),
Some(wgpu::RenderPassColorAttachment {
view: &index_view,
resolve_target: None,
ops: wgpu::Operations::default(),
}),
],
depth_stencil_attachment: None,
});
pass.set_pipeline(&self.gen_pipeline);
pass.set_bind_group(0, &gen_uniforms, &[]);
pass.draw(0..6, 0..1);
drop(pass);
encoder.copy_texture_to_buffer(
wgpu::ImageCopyTexture {
texture: &vertex_texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
},
wgpu::ImageCopyBuffer {
buffer: &chunk.mesh.vertex_buffer,
layout: wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: std::num::NonZeroU32::new(std::mem::size_of::<u32>() as u32 * self.texture_size),
rows_per_image: std::num::NonZeroU32::new(self.texture_size),
},
},
wgpu::Extent3d {
width: self.texture_size,
height: self.texture_size,
depth_or_array_layers: 1,
},
);
encoder.copy_texture_to_buffer(
wgpu::ImageCopyTexture {
texture: &index_texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
},
wgpu::ImageCopyBuffer {
buffer: &chunk.mesh.index_buffer,
layout: wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: std::num::NonZeroU32::new(std::mem::size_of::<u32>() as u32 * self.texture_size),
rows_per_image: std::num::NonZeroU32::new(self.texture_size),
},
},
wgpu::Extent3d {
width: self.texture_size,
height: self.texture_size,
depth_or_array_layers: 1,
},
);
queue.submit(std::iter::once(encoder.finish()));
{
device.poll(wgpu::Maintain::Wait);
let bs = chunk.mesh.index_buffer.slice(..);
let (tx, rx) = std::sync::mpsc::channel();
bs.map_async(wgpu::MapMode::Read, move |result| {
tx.send(result).unwrap();
});
device.poll(wgpu::Maintain::Wait);
rx.recv().unwrap().unwrap();
let data = bs.get_mapped_range();
let indices: &[u32] = bytemuck::cast_slice(&data);
let mut f = std::fs::File::create(format!("Chunk ({}, {}) Indices.txt", chunk.corner.x, chunk.corner.y)).unwrap();
use std::io::Write;
for quad in indices.chunks(6) {
writeln!(f, "{:?}", quad);
}
drop(f);
let img = image::ImageBuffer::<image::Rgba<u8>, _>::from_raw(self.texture_size, self.texture_size, data).unwrap();
img.save(format!("Chunk ({}, {}) Vertex Data.png", chunk.corner.x, chunk.corner.y)).unwrap();
}
chunk.mesh.index_buffer.unmap();
chunk
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
struct GenData {
chunk_size: [u32; 2],
chunk_corner: [i32; 2],
min_max_height: [f32; 2],
texture_size: u32,
_pad0: u32,
start_index: u32,
_pad1: u32,
}
impl HackTerrainPipeline {
impl GenData {
pub fn new(
device: &wgpu::Device,
texture_size: u32,
start_index: u32,
chunk_size: cgmath::Vector2<u32>,
camera_layout: &wgpu::BindGroupLayout,
light_layout: &wgpu::BindGroupLayout,
color_format: wgpu::TextureFormat,
depth_format: Option<wgpu::TextureFormat>,
chunk_corner: cgmath::Vector2<i32>,
min_max_height: cgmath::Vector2<f32>,
) -> Self {
let num_indices = chunk_size.x * chunk_size.y * 6;
todo!();
Self {
texture_size,
_pad0: 0,
start_index,
_pad1: 0,
chunk_size: chunk_size.into(),
chunk_corner: chunk_corner.into(),
min_max_height: min_max_height.into(),
}
}
}
}

@ -9,25 +9,24 @@
fn permute3(x: vec3<f32>) -> vec3<f32> { return (((x * 34.) + 1.) * x) % vec3<f32>(289.); }
fn snoise2(v: vec2<f32>) -> f32 {
let C = vec4<f32>(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
var i: vec2<f32> = floor(v + dot(v, C.yy));
let x0 = v - i + dot(i, C.xx);
// I flipped the condition here from > to < as it fixed some artifacting I was observing
var i1: vec2<f32> = select(vec2<f32>(1., 0.), vec2<f32>(0., 1.), (x0.x < x0.y));
var x12: vec4<f32> = x0.xyxy + C.xxzz - vec4<f32>(i1, 0., 0.);
i = i % vec2<f32>(289.);
let p = permute3(permute3(i.y + vec3<f32>(0., i1.y, 1.)) + i.x + vec3<f32>(0., i1.x, 1.));
var m: vec3<f32> = max(0.5 -
vec3<f32>(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), vec3<f32>(0.));
m = m * m;
m = m * m;
let x = 2. * fract(p * C.www) - 1.;
let h = abs(x) - 0.5;
let ox = floor(x + 0.5);
let a0 = x - ox;
m = m * (1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h));
let g = vec3<f32>(a0.x * x0.x + h.x * x0.y, a0.yz * x12.xz + h.yz * x12.yw);
return 130. * dot(m, g);
let C = vec4<f32>(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
var i: vec2<f32> = floor(v + dot(v, C.yy));
let x0 = v - i + dot(i, C.xx);
// I flipped the condition here from > to < as it fixed some artifacting I was observing
var i1: vec2<f32> = select(vec2<f32>(1., 0.), vec2<f32>(0., 1.), (x0.x < x0.y));
var x12: vec4<f32> = x0.xyxy + C.xxzz - vec4<f32>(i1, 0., 0.);
i = i % vec2<f32>(289.);
let p = permute3(permute3(i.y + vec3<f32>(0., i1.y, 1.)) + i.x + vec3<f32>(0., i1.x, 1.));
var m: vec3<f32> = max(0.5 - vec3<f32>(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), vec3<f32>(0.));
m = m * m;
m = m * m;
let x = 2. * fract(p * C.www) - 1.;
let h = abs(x) - 0.5;
let ox = floor(x + 0.5);
let a0 = x - ox;
m = m * (1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h));
let g = vec3<f32>(a0.x * x0.x + h.x * x0.y, a0.yz * x12.xz + h.yz * x12.yw);
return 130. * dot(m, g);
}
@ -40,7 +39,7 @@ fn fbm(p: vec2<f32>) -> f32 {
let cs = vec2<f32>(cos(0.5), sin(0.5));
let rot = mat2x2<f32>(cs.x, cs.y, -cs.y, cs.x);
for (var i=0u; i<NUM_OCTAVES; i=i+1u) {
for (var i = 0u; i < NUM_OCTAVES; i = i + 1u) {
v = v + a * snoise2(x);
x = rot * x * 2.0 + shift;
a = a * 0.5;
@ -72,21 +71,21 @@ struct IndexBuffer {
@group(0) @binding(1) var<storage, read_write> vertices: VertexBuffer;
@group(0) @binding(2) var<storage, read_write> indices: IndexBuffer;
fn terrain_point(p: vec2<f32>) -> vec3<f32> {
fn terrain_point(p: vec2<f32>, min_max_height: vec2<f32>) -> vec3<f32> {
return vec3<f32>(
p.x,
mix(chunk_data.min_max_height.x,chunk_data.min_max_height.y, fbm(p)),
mix(min_max_height.x, min_max_height.y, fbm(p)),
p.y,
);
}
fn terrain_vertex(p: vec2<f32>) -> Vertex {
let v = terrain_point(p);
fn terrain_vertex(p: vec2<f32>, min_max_height: vec2<f32>) -> Vertex {
let v = terrain_point(p, min_max_height);
let tpx = terrain_point(p + vec2<f32>(0.1, 0.0)) - v;
let tpz = terrain_point(p + vec2<f32>(0.0, 0.1)) - v;
let tnx = terrain_point(p + vec2<f32>(-0.1, 0.0)) - v;
let tnz = terrain_point(p + vec2<f32>(0.0, -0.1)) - v;
let tpx = terrain_point(p + vec2<f32>(0.1, 0.0), min_max_height) - v;
let tpz = terrain_point(p + vec2<f32>(0.0, 0.1), min_max_height) - v;
let tnx = terrain_point(p + vec2<f32>(-0.1, 0.0), min_max_height) - v;
let tnz = terrain_point(p + vec2<f32>(0.0, -0.1), min_max_height) - v;
let pn = normalize(cross(tpz, tpx));
let nn = normalize(cross(tnz, tnx));
@ -96,11 +95,11 @@ fn terrain_vertex(p: vec2<f32>) -> Vertex {
return Vertex(v, n);
}
fn index_to_p(vert_index: u32): vec2<f32> {
fn index_to_p(vert_index: u32, chunk_size: vec2<u32>, chunk_corner: vec2<i32>) -> vec2<f32> {
return vec2(
f32(vert_index) % f32(chunk_data.chunk_size.x + 1u),
f32(vert_index / (chunk_data.chunk_size.x + 1u)),
) + vec2(chunk_data.chunk_corner);
f32(vert_index) % f32(chunk_size.x + 1u),
f32(vert_index / (chunk_size.x + 1u)),
) + vec2<f32>(chunk_corner);
}
@compute @workgroup_size(64)
@ -110,9 +109,9 @@ fn gen_terrain_compute(
// Create vert_component
let vert_index = gid.x;
let p = index_to_p(vert_index);
let p = index_to_p(vert_index, chunk_data.chunk_size, chunk_data.chunk_corner);
vertices.data[vert_index] = terrain_vertex(p);
vertices.data[vert_index] = terrain_vertex(p, chunk_data.min_max_height);
// Create indices
let start_index = gid.x * 6u; // using TriangleList
@ -136,26 +135,38 @@ fn gen_terrain_compute(
// Terrain Gen (Fragment Shader)
// ============================
@group(0) @binding(1) var<uniform> texture_dim: vec2<u32>;
struct GenData {
chunk_size: vec2<u32>,
chunk_corner: vec2<i32>,
min_max_height: vec2<f32>,
texture_size: u32,
start_index: u32,
}
@group(0)
@binding(0)
var<uniform> gen_data: GenData;
struct GenVertexOutput {
@location(0)
index: u32,
@builtin(position): position,
@builtin(position)
position: vec4<f32>,
@location(1)
uv: vec2<f32>,
};
@vert_component
fn gen_terrain_vertex(@builtin(vert_index): vindex): GenVertexOutput {
let u = f32(((index + 2u) / 3u) % 2u);
let v = f32(((index + 1u) / 3u) % 2u);
@vertex
fn gen_terrain_vertex(@builtin(vertex_index) vindex: u32) -> GenVertexOutput {
let u = f32(((vindex + 2u) / 3u) % 2u);
let v = f32(((vindex + 1u) / 3u) % 2u);
let uv = vec2<f32>(u, v);
let position = vec4<f32>(-1.0 + uv * 2.0, 0.0, 1.0);
// TODO: maybe replace this with u32(dot(uv, vec2(f32(gen_data.texture_dim.x))))
// let index = u32(f32(gen_data.texture_dim.x) * (uv.x + uv.y))
let index = u32(uv.x * f32(gen_data.texture_dim.x) + uv.y * f32(gen_data.texture_dim.x));
let index = u32(uv.x * f32(gen_data.texture_size) + uv.y * f32(gen_data.texture_size)) + gen_data.start_index;
return GenVertexOutput(index, position);
return GenVertexOutput(index, position, uv);
}
@ -165,38 +176,50 @@ struct GenFragmentOutput {
}
@fragment
fn gen_terrain_fragment(in: GenVertexOutput): u32 {
let vert_index = floor(in.index / 6.);
let comp_index = in.index % 6;
fn gen_terrain_fragment(in: GenVertexOutput) -> GenFragmentOutput {
let i = u32(in.uv.x * f32(gen_data.texture_size) + in.uv.y * f32(gen_data.texture_size * gen_data.texture_size)) + gen_data.start_index;
let vert_index = u32(floor(f32(i) / 6.));
let comp_index = i % 6u;
let p = index_to_p(vert_index);
let v = terrain_vertex(p);
let p = index_to_p(vert_index, gen_data.chunk_size, gen_data.chunk_corner);
let v = terrain_vertex(p, gen_data.min_max_height);
var vert_component = 0.;
var vert_component: f32 = 0.;
switch comp_index {
case 0 { vert_component = v.position.x }
case 1 { vert_component = v.position.y }
case 2 { vert_component = v.position.z }
case 3 { vert_component = v.normal.x }
case 4 { vert_component = v.normal.y }
case 5 { vert_component = v.normal.z }
case 0u: { vert_component = v.position.x; }
case 1u: { vert_component = v.position.y; }
case 2u: { vert_component = v.position.z; }
case 3u: { vert_component = v.normal.x; }
case 4u: { vert_component = v.normal.y; }
case 5u: { vert_component = v.normal.z; }
default: {}
}
let v00 = vert_index + gid.x / chunk_data.chunk_size.x;
let v00 = vert_index + vert_index / gen_data.chunk_size.x;
let v10 = v00 + 1u;
let v01 = v00 + chunk_data.chunk_size.x + 1u;
let v01 = v00 + gen_data.chunk_size.x + 1u;
let v11 = v01 + 1u;
var index = 0u;
switch comp_index {
case 0, 3 { index = v00; }
case 2, 4 { index = v11; }
case 1 { index = v01; }
case 5 { index = v10; }
case 0u, 3u: { index = v00; }
case 2u, 4u: { index = v11; }
case 1u: { index = v01; }
case 5u: { index = v10; }
default: {}
}
return GenFragmentOutput(bitcast<u32>(vert_component), index);
index = in.index;
// index = gen_data.start_index;
// indices.data[start_index] = v00;
// indices.data[start_index + 1u] = v01;
// indices.data[start_index + 2u] = v11;
// indices.data[start_index + 3u] = v00;
// indices.data[start_index + 4u] = v11;
// indices.data[start_index + 5u] = v10;
let vert_component = bitcast<u32>(vert_component);
return GenFragmentOutput(vert_component, index);
}
// ============================
@ -223,13 +246,13 @@ struct VertexOutput {
@location(1) world_pos: vec3<f32>,
}
@vert_component
@vertex
fn vs_main(
vert_component: Vertex,
vertex: Vertex,
) -> VertexOutput {
let clip_position = camera.view_proj * vec4<f32>(vert_component.position, 1.);
let normal = vert_component.normal;
return VertexOutput(clip_position, normal, vert_component.position);
let clip_position = camera.view_proj * vec4<f32>(vertex.position, 1.);
let normal = vertex.normal;
return VertexOutput(clip_position, normal, vertex.position);
}
@group(2) @binding(0)
@ -244,7 +267,7 @@ var s_normal: sampler;
fn color23(p: vec2<f32>) -> vec3<f32> {
return vec3<f32>(
snoise2(p) * 0.5 + 0.5,
snoise2(p + vec2<f32>(23., 32.,)) * 0.5 + 0.5,
snoise2(p + vec2<f32>(23., 32.)) * 0.5 + 0.5,
snoise2(p + vec2<f32>(-43., 3.)) * 0.5 + 0.5,
);
}

Loading…
Cancel
Save