Created
July 17, 2022 09:27
-
-
Save ChristopherBiscardi/9260184e71b40035ca874d6c4781da6a to your computer and use it in GitHub Desktop.
land-vertex exploration
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
#import bevy_pbr::mesh_view_bindings | |
#import bevy_pbr::mesh_bindings | |
// NOTE: Bindings must come before functions that use them! | |
#import bevy_pbr::mesh_functions | |
#import bevy_shader_utils::simplex_noise_3d | |
#import bevy_shader_utils::simplex_noise_2d | |
struct StandardMaterial { | |
time: f32, | |
// base_color: vec4<f32>; | |
// emissive: vec4<f32>; | |
// perceptual_roughness: f32; | |
// metallic: f32; | |
// reflectance: f32; | |
// // 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options. | |
// flags: u32; | |
// alpha_cutoff: f32; | |
}; | |
@group(1) @binding(0) | |
var<uniform> material: StandardMaterial; | |
struct Vertex { | |
@location(0) position: vec3<f32>, | |
@location(1) normal: vec3<f32>, | |
#ifdef VERTEX_UVS | |
@location(2) uv: vec2<f32>, | |
#endif | |
#ifdef VERTEX_TANGENTS | |
@location(3) tangent: vec4<f32>, | |
#endif | |
#ifdef VERTEX_COLORS | |
@location(4) color: vec4<f32>, | |
#endif | |
#ifdef SKINNED | |
@location(5) joint_indices: vec4<u32>, | |
@location(6) joint_weights: vec4<f32>, | |
#endif | |
}; | |
struct VertexOutput { | |
@builtin(position) clip_position: vec4<f32>, | |
@location(0) world_position: vec4<f32>, | |
@location(1) world_normal: vec3<f32>, | |
#ifdef VERTEX_UVS | |
@location(2) uv: vec2<f32>, | |
#endif | |
#ifdef VERTEX_TANGENTS | |
@location(3) world_tangent: vec4<f32>, | |
#endif | |
#ifdef VERTEX_COLORS | |
@location(4) color: vec4<f32>, | |
#endif | |
}; | |
@vertex | |
fn vertex(vertex: Vertex) -> VertexOutput { | |
var out: VertexOutput; | |
#ifdef SKINNED | |
var model = skin_model(vertex.joint_indices, vertex.joint_weights); | |
out.world_normal = skin_normals(model, vertex.normal); | |
#else | |
var model = mesh.model; | |
out.world_normal = mesh_normal_local_to_world(vertex.normal); | |
#endif | |
out.world_position = mesh_position_local_to_world(model, vec4<f32>(vertex.position, 1.0)); | |
#ifdef VERTEX_UVS | |
out.uv = vertex.uv; | |
#endif | |
#ifdef VERTEX_TANGENTS | |
out.world_tangent = mesh_tangent_local_to_world(model, vertex.tangent); | |
#endif | |
#ifdef VERTEX_COLORS | |
out.color = vertex.color; | |
#endif | |
var noise = simplexNoise3(vertex.position); | |
// out.color = vec4<f32>(vertex.position.x, noise, vertex.position.z, 1.0); | |
out.color = vec4<f32>(vertex.uv.x, noise, vertex.uv.y, 1.0); | |
out.world_position = mesh_position_local_to_world(model, vec4<f32>(vertex.position.x, noise, vertex.position.z, 1.0)); | |
// out.world_position.x = -100.0; | |
out.clip_position = mesh_position_world_to_clip(out.world_position); | |
return out; | |
} |
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
//! Loads and renders a glTF file as a scene. | |
use bevy::{ | |
pbr::wireframe::{ | |
Wireframe, WireframeConfig, WireframePlugin, | |
}, | |
prelude::*, | |
reflect::TypeUuid, | |
render::{ | |
mesh::{ | |
Indices, PrimitiveTopology, | |
VertexAttributeValues, | |
}, | |
render_resource::{AsBindGroup, ShaderRef}, | |
}, | |
render::{ | |
render_resource::WgpuFeatures, | |
settings::WgpuSettings, | |
}, | |
}; | |
use bevy_shader_utils::ShaderUtilsPlugin; | |
use itertools::Itertools; | |
fn main() { | |
App::new() | |
.insert_resource(AmbientLight { | |
color: Color::WHITE, | |
brightness: 1.0 / 5.0f32, | |
}) | |
.insert_resource(ClearColor( | |
Color::hex("071f3c").unwrap(), | |
)) | |
.insert_resource(WgpuSettings { | |
features: WgpuFeatures::POLYGON_MODE_LINE, | |
..default() | |
}) | |
.add_plugins(DefaultPlugins) | |
.add_plugin(WireframePlugin) | |
.add_plugin(ShaderUtilsPlugin) | |
.add_plugin( | |
MaterialPlugin::<LandMaterial>::default(), | |
) | |
.add_startup_system(setup) | |
.add_system(animate_light_direction) | |
.add_system(movement) | |
.run(); | |
} | |
fn setup( | |
mut commands: Commands, | |
mut meshes: ResMut<Assets<Mesh>>, | |
mut materials: ResMut<Assets<LandMaterial>>, | |
mut standard_materials: ResMut< | |
Assets<StandardMaterial>, | |
>, | |
asset_server: Res<AssetServer>, | |
) { | |
commands | |
.spawn_bundle(Camera3dBundle { | |
transform: Transform::from_xyz(0.0, 1.5, 10.0) | |
.looking_at( | |
Vec3::new(0.0, 0.3, 0.0), | |
Vec3::Y, | |
), | |
..default() | |
}) | |
.insert(Movable); | |
const HALF_SIZE: f32 = 1.0; | |
commands.spawn_bundle(DirectionalLightBundle { | |
directional_light: DirectionalLight { | |
shadow_projection: OrthographicProjection { | |
left: -HALF_SIZE, | |
right: HALF_SIZE, | |
bottom: -HALF_SIZE, | |
top: HALF_SIZE, | |
near: -10.0 * HALF_SIZE, | |
far: 10.0 * HALF_SIZE, | |
..default() | |
}, | |
shadows_enabled: true, | |
..default() | |
}, | |
..default() | |
}); | |
// land | |
let mut land = Mesh::from(Land { | |
size: 1000.0, | |
num_vertices: 1000, | |
}); | |
if let Some(VertexAttributeValues::Float32x3( | |
positions, | |
)) = land.attribute(Mesh::ATTRIBUTE_POSITION) | |
{ | |
let colors: Vec<[f32; 4]> = positions | |
.iter() | |
.map(|[r, g, b]| { | |
[ | |
(1. - *r) / 2., | |
(1. - *g) / 2., | |
(1. - *b) / 2., | |
1., | |
] | |
}) | |
.collect(); | |
land.insert_attribute( | |
Mesh::ATTRIBUTE_COLOR, | |
colors, | |
); | |
} | |
commands | |
.spawn() | |
.insert_bundle(MaterialMeshBundle { | |
mesh: meshes.add(land), | |
transform: Transform::from_xyz(0.0, 0.5, 0.0), | |
material: materials.add(LandMaterial { | |
time: 0., | |
alpha_mode: AlphaMode::Blend, | |
}), | |
// material: standard_materials.add( | |
// StandardMaterial { | |
// base_color: Color::WHITE, | |
// ..default() | |
// }, | |
// ), | |
..default() | |
}) | |
.insert(Wireframe); | |
// ship | |
commands.spawn().insert_bundle(MaterialMeshBundle { | |
mesh: meshes | |
.add(Mesh::from(shape::Cube { size: 1.0 })), | |
transform: Transform::from_xyz(0.0, 1.5, 0.0), | |
material: standard_materials.add( | |
StandardMaterial { | |
base_color: Color::BLUE, | |
..default() | |
}, | |
), | |
..default() | |
}); | |
// commands.spawn_bundle(SceneBundle { | |
// scene: asset_server | |
// .load("craft/craft_racer.glb#Scene0"), | |
// // scene: asset_server | |
// // .load("racecar/raceCarGreen.glb/#Scene0"), | |
// ..default() | |
// }); | |
// let my_gltf = | |
// asset_server.load("craft/craft_racer.glb#Scene0"); | |
} | |
fn animate_light_direction( | |
time: Res<Time>, | |
mut query: Query< | |
&mut Transform, | |
With<DirectionalLight>, | |
>, | |
) { | |
for mut transform in &mut query { | |
transform.rotation = Quat::from_euler( | |
EulerRot::ZYX, | |
0.0, | |
time.seconds_since_startup() as f32 | |
* std::f32::consts::TAU | |
/ 10.0, | |
-std::f32::consts::FRAC_PI_4, | |
); | |
} | |
} | |
fn change_color( | |
mut materials: ResMut<Assets<LandMaterial>>, | |
time: Res<Time>, | |
) { | |
for material in materials.iter_mut() { | |
material.1.time = | |
time.seconds_since_startup() as f32; | |
} | |
} | |
/// The Material trait is very configurable, but comes with sensible defaults for all methods. | |
/// You only need to implement functions for features that need non-default behavior. See the Material api docs for details! | |
impl Material for LandMaterial { | |
// fn fragment_shader() -> ShaderRef { | |
// "shaders/custom_material.wgsl".into() | |
// } | |
fn vertex_shader() -> ShaderRef { | |
"shaders/land_vertex_shader.wgsl".into() | |
} | |
fn alpha_mode(&self) -> AlphaMode { | |
self.alpha_mode | |
} | |
} | |
// This is the struct that will be passed to your shader | |
#[derive(AsBindGroup, TypeUuid, Debug, Clone)] | |
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] | |
pub struct LandMaterial { | |
#[uniform(0)] | |
time: f32, | |
alpha_mode: AlphaMode, | |
} | |
#[derive(Debug, Copy, Clone)] | |
struct Land { | |
size: f32, | |
num_vertices: u32, | |
} | |
impl From<Land> for Mesh { | |
fn from(plane: Land) -> Self { | |
let extent = plane.size / 2.0; | |
let jump = extent / plane.num_vertices as f32; | |
let vertices = (0..=plane.num_vertices) | |
.cartesian_product(0..=plane.num_vertices) | |
.map(|(x, y)| { | |
( | |
[ | |
x as f32 * jump - 0.5 * extent, | |
0.0, | |
y as f32 * jump - 0.5 * extent, | |
], | |
[0.0, 1.0, 0.0], | |
[ | |
x as f32 | |
/ plane.num_vertices as f32, | |
y as f32 | |
/ plane.num_vertices as f32, | |
], | |
) | |
}) | |
.collect::<Vec<_>>(); | |
// let vertices = [ | |
// ( | |
// [extent, 0.0, -extent], | |
// [0.0, 1.0, 0.0], | |
// [1.0, 1.0], | |
// ), | |
// ( | |
// [extent, 0.0, extent], | |
// [0.0, 1.0, 0.0], | |
// [1.0, 0.0], | |
// ), | |
// ( | |
// [-extent, 0.0, extent], | |
// [0.0, 1.0, 0.0], | |
// [0.0, 0.0], | |
// ), | |
// ( | |
// [-extent, 0.0, -extent], | |
// [0.0, 1.0, 0.0], | |
// [0.0, 1.0], | |
// ), | |
// ]; | |
// let indices = Indices::U32(vec![0, 2, 1, 0, 3, 2]); | |
let indices = Indices::U32( | |
(0..=plane.num_vertices) | |
.cartesian_product(0..=plane.num_vertices) | |
.enumerate() | |
.filter_map(|(index, (x, y))| { | |
if y >= plane.num_vertices { | |
None | |
} else if x >= plane.num_vertices { | |
None | |
} else { | |
Some([ | |
[ | |
index as u32, | |
index as u32 + 1, | |
index as u32 | |
+ 1 | |
+ plane.num_vertices, | |
], | |
[ | |
index as u32, | |
index as u32 | |
+ plane.num_vertices | |
+ 1, | |
index as u32 | |
+ plane.num_vertices, | |
], | |
]) | |
} | |
}) | |
.flatten() | |
.flatten() | |
.collect::<Vec<_>>(), | |
); | |
dbg!(&indices.iter().take(6).collect::<Vec<_>>()); | |
let positions: Vec<_> = | |
vertices.iter().map(|(p, _, _)| *p).collect(); | |
let normals: Vec<_> = | |
vertices.iter().map(|(_, n, _)| *n).collect(); | |
let uvs: Vec<_> = | |
vertices.iter().map(|(_, _, uv)| *uv).collect(); | |
let mut mesh = | |
Mesh::new(PrimitiveTopology::TriangleList); | |
mesh.set_indices(Some(indices)); | |
mesh.insert_attribute( | |
Mesh::ATTRIBUTE_POSITION, | |
positions, | |
); | |
mesh.insert_attribute( | |
Mesh::ATTRIBUTE_NORMAL, | |
normals, | |
); | |
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs); | |
mesh | |
} | |
} | |
#[derive(Component)] | |
struct Movable; | |
fn movement( | |
input: Res<Input<KeyCode>>, | |
time: Res<Time>, | |
mut query: Query<&mut Transform, With<Movable>>, | |
) { | |
for mut transform in query.iter_mut() { | |
let mut direction = Vec3::ZERO; | |
if input.pressed(KeyCode::Up) { | |
direction.z += 1.0; | |
} | |
if input.pressed(KeyCode::Down) { | |
direction.z -= 1.0; | |
} | |
if input.pressed(KeyCode::Left) { | |
direction.x -= 1.0; | |
} | |
if input.pressed(KeyCode::Right) { | |
direction.x += 1.0; | |
} | |
transform.translation += | |
time.delta_seconds() * 2.0 * direction; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment