super hacky texture index

This commit is contained in:
2024-04-07 00:48:22 -04:00
parent 0945ee4023
commit d42f2dd65c
6 changed files with 126 additions and 50 deletions

View File

@@ -2,6 +2,8 @@ pub mod prelude {
use crate::hex_utils::HexCoord; use crate::hex_utils::HexCoord;
use bevy::math::{IVec2, UVec2}; use bevy::math::{IVec2, UVec2};
use bevy::prelude::Resource; use bevy::prelude::Resource;
use bevy::render::mesh::MeshVertexAttribute;
use bevy::render::render_resource::VertexFormat;
pub struct GenerationConfig { pub struct GenerationConfig {
pub noise_scale: f64, pub noise_scale: f64,
@@ -10,6 +12,7 @@ pub mod prelude {
pub size: UVec2, pub size: UVec2,
pub layers: Vec<GeneratorLayer>, pub layers: Vec<GeneratorLayer>,
} }
pub struct GeneratorLayer { pub struct GeneratorLayer {
pub strength: f64, pub strength: f64,
pub min_value: f64, pub min_value: f64,
@@ -22,6 +25,7 @@ pub mod prelude {
pub layers: usize, pub layers: usize,
pub first_layer_mask: bool, pub first_layer_mask: bool,
} }
pub struct Chunk { pub struct Chunk {
pub points: [f32; Chunk::SIZE * Chunk::SIZE], pub points: [f32; Chunk::SIZE * Chunk::SIZE],
pub chunk_offset: IVec2, pub chunk_offset: IVec2,
@@ -57,6 +61,9 @@ pub mod prelude {
return results; return results;
} }
} }
pub const ATTRIBUTE_TEXTURE_INDEX: MeshVertexAttribute =
MeshVertexAttribute::new("TextureIndex", 988540917, VertexFormat::Uint32);
} }
pub mod heightmap; pub mod heightmap;

View File

@@ -11,6 +11,8 @@ use bevy::{
}, },
}; };
use std::vec::Vec; use std::vec::Vec;
use bevy::render::mesh::MeshVertexAttribute;
use bevy::render::render_resource::VertexFormat;
const HEX_CORNERS: [Vec3; 6] = [ const HEX_CORNERS: [Vec3; 6] = [
Vec3::new(0., 0., OUTER_RADIUS), Vec3::new(0., 0., OUTER_RADIUS),
@@ -21,11 +23,13 @@ const HEX_CORNERS: [Vec3; 6] = [
Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS), Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
]; ];
pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh { pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh {
let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6; let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6;
let mut verts = Vec::with_capacity(vertex_count); let mut verts = Vec::with_capacity(vertex_count);
let mut uvs = Vec::with_capacity(vertex_count); let mut uvs = Vec::with_capacity(vertex_count);
let mut indices = Vec::with_capacity(vertex_count); let mut indices = Vec::with_capacity(vertex_count);
let mut tex = Vec::with_capacity(vertex_count);
for z in 0..Chunk::SIZE { for z in 0..Chunk::SIZE {
for x in 0..Chunk::SIZE { for x in 0..Chunk::SIZE {
@@ -42,7 +46,8 @@ pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh {
&mut verts, &mut verts,
&mut uvs, &mut uvs,
&mut indices, &mut indices,
((x + z * Chunk::SIZE) % 32) as u32, &mut tex,
(height % 7.) as u32,
); );
} }
} }
@@ -53,32 +58,29 @@ pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh {
) )
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, verts) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, verts)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs) .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_1, tex)
.with_inserted_indices(Indices::U32(indices)) .with_inserted_indices(Indices::U32(indices))
// .with_inserted_attribute(ATTRIBUTE_TEXTURE_INDEX, tex)
.with_duplicated_vertices() .with_duplicated_vertices()
.with_computed_flat_normals(); .with_computed_flat_normals();
return mesh; return mesh;
} }
//TODO: figure out texture index
fn create_tile( fn create_tile(
pos: Vec3, pos: Vec3,
neighbors: &[Option<f32>; 6], neighbors: &[Option<f32>; 6],
verts: &mut Vec<Vec3>, verts: &mut Vec<Vec3>,
uvs: &mut Vec<Vec2>, uvs: &mut Vec<Vec2>,
indices: &mut Vec<u32>, indices: &mut Vec<u32>,
tex: &mut Vec<Vec2>,
texture_index: u32, texture_index: u32,
) { ) {
let tex_x = texture_index % 11;
let tex_y = texture_index / 11;
let x_min = tex_x as f32 / 11.;
let y_min = tex_y as f32 / 8.;
const TX_UNIT: Vec2 = Vec2::new(1. / 11., 1. / 8.);
let uv_offset = Vec2::splat(0.5); let uv_offset = Vec2::splat(0.5);
let idx = verts.len() as u32; let idx = verts.len() as u32;
uvs.push(uv_offset); uvs.push(uv_offset);
verts.push(pos); verts.push(pos);
tex.push(Vec2::splat(texture_index as f32));
for i in 0..6 { for i in 0..6 {
let p = pos + HEX_CORNERS[i]; let p = pos + HEX_CORNERS[i];
verts.push(p); verts.push(p);
@@ -87,6 +89,7 @@ fn create_tile(
indices.push(idx); indices.push(idx);
indices.push(idx + 1 + i as u32); indices.push(idx + 1 + i as u32);
indices.push(idx + 1 + ((i as u32 + 1) % 6)); indices.push(idx + 1 + ((i as u32 + 1) % 6));
tex.push(Vec2::splat(texture_index as f32));
} }
for i in 0..neighbors.len() { for i in 0..neighbors.len() {
@@ -94,7 +97,7 @@ fn create_tile(
match cur_n { match cur_n {
Some(n_height) => { Some(n_height) => {
if n_height < pos.y { if n_height < pos.y {
create_tile_wall(pos, i, n_height, verts, uvs, indices, Vec2::ZERO, Vec2::ONE); create_tile_wall(pos, i, n_height, verts, uvs, indices, tex, texture_index);
} }
} }
_ => {} _ => {}
@@ -109,8 +112,8 @@ fn create_tile_wall(
verts: &mut Vec<Vec3>, verts: &mut Vec<Vec3>,
uvs: &mut Vec<Vec2>, uvs: &mut Vec<Vec2>,
indices: &mut Vec<u32>, indices: &mut Vec<u32>,
tx_min: Vec2, tex: &mut Vec<Vec2>,
tx_max: Vec2, texture_index: u32,
) { ) {
let p1 = HEX_CORNERS[(dir) % 6] + pos; let p1 = HEX_CORNERS[(dir) % 6] + pos;
let p2 = HEX_CORNERS[(dir + 1) % 6] + pos; let p2 = HEX_CORNERS[(dir + 1) % 6] + pos;
@@ -132,9 +135,13 @@ fn create_tile_wall(
indices.push(idx + 2); indices.push(idx + 2);
indices.push(idx + 3); indices.push(idx + 3);
//TODO: scale texture based on height tex.push(Vec2::splat(texture_index as f32));
uvs.push(tx_min); tex.push(Vec2::splat(texture_index as f32));
uvs.push(Vec2::new(tx_max.x, tx_min.y)); tex.push(Vec2::splat(texture_index as f32));
uvs.push(Vec2::new(tx_min.x, tx_max.y)); tex.push(Vec2::splat(texture_index as f32));
uvs.push(tx_max);
uvs.push(Vec2::ZERO);
uvs.push(Vec2::new(1., 0.));
uvs.push(Vec2::new(0., pos.y - height));
uvs.push(Vec2::new(1., pos.y - height));
} }

View File

@@ -2,6 +2,8 @@
pbr_fragment::pbr_input_from_standard_material, pbr_fragment::pbr_input_from_standard_material,
pbr_functions::alpha_discard, pbr_functions::alpha_discard,
} }
#import bevy_pbr::mesh_functions::{mesh_position_local_to_world,get_model_matrix,mesh_normal_local_to_world}
#import bevy_pbr::view_transformations::position_world_to_clip;
#ifdef PREPASS_PIPELINE #ifdef PREPASS_PIPELINE
#import bevy_pbr::{ #import bevy_pbr::{
@@ -15,19 +17,19 @@
} }
#endif #endif
struct ChunkMaterial {
array_texture: texture_2d_array<f32>,
array_texture_sampler: sampler,
}
@group(2) @binding(100)
var<uniform> chunk_material: ChunkMaterial;
@group(2) @binding(100) var array_texture: texture_2d_array<f32>;
@group(2) @binding(101) var array_texture_sampler: sampler;
@fragment @fragment
fn fragment( fn fragment(
in: VertexOutput, in: VertexOutput,
@builtin(front_facing) is_front: bool, @builtin(front_facing) is_front: bool,
) -> FragmentOutput { ) -> FragmentOutput {
// var vin : VertexOutput;
// vin.position = in.position;
// vin.world_position = in.world_position;
// vin.world_normal = in.world_normal;
// vin.uv = in.uv;
// generate a PbrInput struct from the StandardMaterial bindings // generate a PbrInput struct from the StandardMaterial bindings
var pbr_input = pbr_input_from_standard_material(in, is_front); var pbr_input = pbr_input_from_standard_material(in, is_front);
@@ -41,10 +43,13 @@ fn fragment(
#else #else
var out: FragmentOutput; var out: FragmentOutput;
// apply lighting // apply lighting
out.color = apply_pbr_lighting(pbr_input);
let layer = i32(in.world_position.x) & 0x7; let layer = u32(in.uv_b.x);
out.color = textureSample(chunk_material.array_texture, chunk_material.array_texture_sampler, in.uv, layer); out.color = textureSample(array_texture, array_texture_sampler, in.uv, layer);
out.color *= apply_pbr_lighting(pbr_input);
// apply in-shader post processing (fog, alpha-premultiply, and also tonemapping, debanding if the camera is non-hdr) // apply in-shader post processing (fog, alpha-premultiply, and also tonemapping, debanding if the camera is non-hdr)
// note this does not include fullscreen postprocessing effects like bloom. // note this does not include fullscreen postprocessing effects like bloom.
@@ -56,3 +61,30 @@ fn fragment(
return out; return out;
} }
//struct Vertex {
// @builtin(instance_index) instance_index: u32,
// @location(0) position: vec3<f32>,
// @location(1) uv: vec2<f32>,
// @location(2) normal: vec3<f32>,
// @location(3) texture_index: u32,
//};
//
//struct VOut {
// @builtin(position) position: vec4<f32>,
// @location(0) world_position: vec4<f32>,
// @location(1) world_normal: vec3<f32>,
// @location(2) uv: vec2<f32>,
//// @location(7) @interpolate(flat) texture_index: u32,
//};
//
//@vertex
//fn vertex(vertex: Vertex) -> VOut {
// var out: VOut;
// out.world_position = mesh_position_local_to_world(get_model_matrix(vertex.instance_index), vec4<f32>(vertex.position, 1.0));
// out.position = position_world_to_clip(out.world_position.xyz);
//// out.texture_index = vertex.texture_index;
// out.uv = vertex.uv;
// out.world_normal = mesh_normal_local_to_world(vertex.normal, vertex.instance_index);
// return out;
//}

View File

@@ -1,6 +1,8 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::texture::{ImageAddressMode, ImageFilterMode, ImageSamplerDescriptor};
use bevy::window::PresentMode; use bevy::window::PresentMode;
use bevy_inspector_egui::quick::WorldInspectorPlugin; use bevy_inspector_egui::quick::WorldInspectorPlugin;
mod phos; mod phos;
mod prelude; mod prelude;
@@ -19,6 +21,13 @@ fn main() {
..default() ..default()
}), }),
..default() ..default()
}).set(ImagePlugin {
default_sampler: ImageSamplerDescriptor {
address_mode_u: ImageAddressMode::Repeat,
address_mode_v: ImageAddressMode::Repeat,
mag_filter: ImageFilterMode::Nearest,
..default()
}
}), }),
WorldInspectorPlugin::new(), WorldInspectorPlugin::new(),
PhosGamePlugin, PhosGamePlugin,

View File

@@ -1,6 +1,5 @@
use bevy::asset::LoadState; use bevy::asset::LoadState;
use bevy::pbr::{ExtendedMaterial, MaterialExtension}; use bevy::pbr::{ExtendedMaterial};
use bevy::render::render_resource::{AsBindGroup, ShaderRef};
use bevy::{pbr::CascadeShadowConfig, prelude::*}; use bevy::{pbr::CascadeShadowConfig, prelude::*};
use camera_system::PhosCameraPlugin; use camera_system::PhosCameraPlugin;
use iyes_perf_ui::prelude::*; use iyes_perf_ui::prelude::*;
@@ -8,7 +7,6 @@ use world_generation::hex_utils::{offset_to_world, HexCoord};
use world_generation::{ use world_generation::{
heightmap::generate_heightmap, mesh_generator::generate_chunk_mesh, prelude::*, heightmap::generate_heightmap, mesh_generator::generate_chunk_mesh, prelude::*,
}; };
use crate::prelude::*; use crate::prelude::*;
pub struct PhosGamePlugin; pub struct PhosGamePlugin;
@@ -82,6 +80,7 @@ fn check_texture(
let array_layers = 7; let array_layers = 7;
image.reinterpret_stacked_2d_as_array(array_layers); image.reinterpret_stacked_2d_as_array(array_layers);
atlas.is_loaded = true; atlas.is_loaded = true;
map.ready = true; map.ready = true;
map.regenerate = true; map.regenerate = true;
@@ -175,7 +174,7 @@ fn create_map(mut commands: Commands) {
border_size: 64., border_size: 64.,
size: UVec2::splat(1024 / Chunk::SIZE as u32), size: UVec2::splat(1024 / Chunk::SIZE as u32),
}, },
2, 4,
); );
commands.insert_resource(heightmap); commands.insert_resource(heightmap);
@@ -218,15 +217,3 @@ fn spawn_map(
} }
} }
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
struct ChunkMaterial {
#[texture(100, dimension = "2d_array")]
#[sampler(101)]
array_texture: Handle<Image>,
}
impl MaterialExtension for ChunkMaterial {
fn fragment_shader() -> ShaderRef {
"shaders/world/chunk.wgsl".into()
}
}

View File

@@ -1,5 +1,9 @@
use bevy::asset::Handle; use bevy::asset::{Asset, Handle};
use bevy::prelude::{Component, Image, Resource}; use bevy::pbr::{MaterialExtension, MaterialExtensionKey, MaterialExtensionPipeline, MaterialPipeline, MaterialPipelineKey};
use bevy::prelude::{Component, Image, Mesh, Resource, TypePath};
use bevy::render::mesh::{Indices, MeshVertexBufferLayout};
use bevy::render::render_resource::{AsBindGroup, RenderPipelineDescriptor, ShaderRef, SpecializedMeshPipelineError};
use world_generation::prelude::ATTRIBUTE_TEXTURE_INDEX;
#[derive(Resource)] #[derive(Resource)]
pub struct ChunkAtlas { pub struct ChunkAtlas {
@@ -15,3 +19,33 @@ pub struct PhosMap {
#[derive(Component)] #[derive(Component)]
pub struct PhosChunk; pub struct PhosChunk;
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
pub struct ChunkMaterial {
#[texture(100, dimension = "2d_array")]
#[sampler(101)]
pub array_texture: Handle<Image>,
}
impl MaterialExtension for ChunkMaterial {
fn fragment_shader() -> ShaderRef {
"shaders/world/chunk.wgsl".into()
}
// fn specialize(
// _pipeline: &MaterialExtensionPipeline,
// descriptor: &mut RenderPipelineDescriptor,
// layout: &MeshVertexBufferLayout,
// _key: MaterialExtensionKey<Self>,
// ) -> Result<(), SpecializedMeshPipelineError> {
// let vertex_layout = layout.get_layout(&[
// Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
// Mesh::ATTRIBUTE_UV_0.at_shader_location(1),
// Mesh::ATTRIBUTE_NORMAL.at_shader_location(2),
// ATTRIBUTE_TEXTURE_INDEX.at_shader_location(3),
// ])?;
// descriptor.vertex.buffers = vec![vertex_layout];
// Ok(())
// }
}