super hacky texture index
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,34 +56,31 @@ pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh {
|
|||||||
PrimitiveTopology::TriangleList,
|
PrimitiveTopology::TriangleList,
|
||||||
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
|
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
|
||||||
)
|
)
|
||||||
.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_indices(Indices::U32(indices))
|
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_1, tex)
|
||||||
.with_duplicated_vertices()
|
.with_inserted_indices(Indices::U32(indices))
|
||||||
.with_computed_flat_normals();
|
// .with_inserted_attribute(ATTRIBUTE_TEXTURE_INDEX, tex)
|
||||||
|
.with_duplicated_vertices()
|
||||||
|
.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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -55,4 +60,31 @@ fn fragment(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
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;
|
||||||
|
//}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user