texture: First image load
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Has been cancelled
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Has been cancelled
This commit is contained in:
parent
5b0ab19207
commit
29a4da5666
11 changed files with 220 additions and 72 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2110,6 +2110,7 @@ dependencies = [
|
||||||
"egui_winit_vulkano",
|
"egui_winit_vulkano",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"glam",
|
"glam",
|
||||||
|
"image",
|
||||||
"log",
|
"log",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"vulkano",
|
"vulkano",
|
||||||
|
|
|
@ -15,6 +15,8 @@ vulkano-shaders = "0.35"
|
||||||
vulkano-util = "0.35"
|
vulkano-util = "0.35"
|
||||||
egui_winit_vulkano = { version = "0.28" }
|
egui_winit_vulkano = { version = "0.28" }
|
||||||
|
|
||||||
|
image = { version = "0.25", features = ["png", "jpeg"] }
|
||||||
|
|
||||||
# Math
|
# Math
|
||||||
glam = { version = "0.30" }
|
glam = { version = "0.30" }
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout (location = 0) in vec3 color;
|
layout (location = 0) in vec2 tex_coords;
|
||||||
|
|
||||||
layout (location = 0) out vec4 f_color;
|
layout (location = 0) out vec4 f_color;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0) uniform sampler mySampler;
|
||||||
|
layout(set = 1, binding = 1) uniform texture2D myTexture;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
f_color = vec4(color, 1.0);
|
f_color = texture(sampler2D(myTexture, mySampler), tex_coords);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout (location = 0) in vec2 position;
|
layout (location = 0) in vec2 position;
|
||||||
layout (location = 1) in vec3 color;
|
layout (location = 1) in vec2 uv;
|
||||||
|
|
||||||
layout (location = 0) out vec3 fragColor;
|
layout (location = 0) out vec2 fragUv;
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform MVP {
|
layout (set = 0, binding = 0) uniform MVP {
|
||||||
mat4 world;
|
mat4 world;
|
||||||
|
@ -14,5 +14,5 @@ layout (set = 0, binding = 0) uniform MVP {
|
||||||
void main() {
|
void main() {
|
||||||
mat4 worldview = uniforms.view * uniforms.world;
|
mat4 worldview = uniforms.view * uniforms.world;
|
||||||
gl_Position = uniforms.projection * worldview * vec4(position, 0.0, 1.0);
|
gl_Position = uniforms.projection * worldview * vec4(position, 0.0, 1.0);
|
||||||
fragColor = color;
|
fragUv = uv;
|
||||||
}
|
}
|
||||||
|
|
BIN
res/textures/wooden-crate.jpg
Normal file
BIN
res/textures/wooden-crate.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
|
@ -1,4 +1,5 @@
|
||||||
pub mod pipelines;
|
pub mod pipelines;
|
||||||
pub mod primitives;
|
pub mod primitives;
|
||||||
pub mod render_context;
|
pub mod render_context;
|
||||||
|
pub mod texture;
|
||||||
pub mod vulkan_context;
|
pub mod vulkan_context;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use vulkano::device::Device;
|
||||||
use vulkano::format::Format;
|
use vulkano::format::Format;
|
||||||
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
||||||
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
||||||
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
use vulkano::pipeline::graphics::input_assembly::{InputAssemblyState, PrimitiveTopology};
|
||||||
use vulkano::pipeline::graphics::multisample::MultisampleState;
|
use vulkano::pipeline::graphics::multisample::MultisampleState;
|
||||||
use vulkano::pipeline::graphics::rasterization::RasterizationState;
|
use vulkano::pipeline::graphics::rasterization::RasterizationState;
|
||||||
use vulkano::pipeline::graphics::subpass::PipelineRenderingCreateInfo;
|
use vulkano::pipeline::graphics::subpass::PipelineRenderingCreateInfo;
|
||||||
|
@ -52,19 +52,42 @@ pub fn create_triangle_pipeline(
|
||||||
PipelineShaderStageCreateInfo::new(fs),
|
PipelineShaderStageCreateInfo::new(fs),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut bindings = BTreeMap::<u32, DescriptorSetLayoutBinding>::new();
|
let vertex_bindings = BTreeMap::<u32, DescriptorSetLayoutBinding>::from_iter([(
|
||||||
let mut descriptor_set_layout_binding =
|
0,
|
||||||
DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer);
|
DescriptorSetLayoutBinding {
|
||||||
descriptor_set_layout_binding.stages = ShaderStages::VERTEX;
|
stages: ShaderStages::VERTEX,
|
||||||
bindings.insert(0, descriptor_set_layout_binding);
|
..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer)
|
||||||
|
},
|
||||||
|
)]);
|
||||||
|
let fragment_bindings = BTreeMap::<u32, DescriptorSetLayoutBinding>::from_iter([
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
DescriptorSetLayoutBinding {
|
||||||
|
stages: ShaderStages::FRAGMENT,
|
||||||
|
..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::Sampler)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
DescriptorSetLayoutBinding {
|
||||||
|
stages: ShaderStages::FRAGMENT,
|
||||||
|
..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::SampledImage)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
let descriptor_set_layout = DescriptorSetLayoutCreateInfo {
|
let vertex_descriptor_set_layout = DescriptorSetLayoutCreateInfo {
|
||||||
bindings,
|
bindings: vertex_bindings,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let fragment_descriptor_set_layout = DescriptorSetLayoutCreateInfo {
|
||||||
|
bindings: fragment_bindings,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let create_info = PipelineDescriptorSetLayoutCreateInfo {
|
let create_info = PipelineDescriptorSetLayoutCreateInfo {
|
||||||
set_layouts: vec![descriptor_set_layout],
|
set_layouts: vec![vertex_descriptor_set_layout, fragment_descriptor_set_layout],
|
||||||
flags: PipelineLayoutCreateFlags::default(),
|
flags: PipelineLayoutCreateFlags::default(),
|
||||||
push_constant_ranges: vec![],
|
push_constant_ranges: vec![],
|
||||||
}
|
}
|
||||||
|
@ -83,7 +106,10 @@ pub fn create_triangle_pipeline(
|
||||||
GraphicsPipelineCreateInfo {
|
GraphicsPipelineCreateInfo {
|
||||||
stages: stages.into_iter().collect(),
|
stages: stages.into_iter().collect(),
|
||||||
vertex_input_state: Some(vertex_input_state),
|
vertex_input_state: Some(vertex_input_state),
|
||||||
input_assembly_state: Some(InputAssemblyState::default()),
|
input_assembly_state: Some(InputAssemblyState {
|
||||||
|
topology: PrimitiveTopology::TriangleStrip,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
viewport_state: Some(ViewportState::default()),
|
viewport_state: Some(ViewportState::default()),
|
||||||
rasterization_state: Some(RasterizationState::default()),
|
rasterization_state: Some(RasterizationState::default()),
|
||||||
multisample_state: Some(MultisampleState::default()),
|
multisample_state: Some(MultisampleState::default()),
|
||||||
|
|
|
@ -12,8 +12,8 @@ pub struct Vertex2D {
|
||||||
#[format(R32G32_SFLOAT)]
|
#[format(R32G32_SFLOAT)]
|
||||||
pub position: [f32; 2],
|
pub position: [f32; 2],
|
||||||
|
|
||||||
#[format(R32G32B32_SFLOAT)]
|
#[format(R32G32_SFLOAT)]
|
||||||
pub color: [f32; 3],
|
pub uv: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vertex2D {
|
impl Vertex2D {
|
||||||
|
|
113
src/core/render/texture.rs
Normal file
113
src/core/render/texture.rs
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
use std::{path::Path, sync::Arc};
|
||||||
|
|
||||||
|
use anyhow::Error;
|
||||||
|
use image::{DynamicImage, EncodableLayout};
|
||||||
|
use vulkano::{
|
||||||
|
buffer::{Buffer, BufferCreateInfo, BufferUsage},
|
||||||
|
command_buffer::{AutoCommandBufferBuilder, CopyBufferToImageInfo, PrimaryAutoCommandBuffer},
|
||||||
|
device::Device,
|
||||||
|
format::Format,
|
||||||
|
image::{
|
||||||
|
Image, ImageCreateInfo, ImageType, ImageUsage,
|
||||||
|
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||||
|
view::ImageView,
|
||||||
|
},
|
||||||
|
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Texture {
|
||||||
|
texture: Arc<ImageView>,
|
||||||
|
sampler: Arc<Sampler>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Texture {
|
||||||
|
fn new(texture: Arc<ImageView>, sampler: Arc<Sampler>) -> Self {
|
||||||
|
Self { texture, sampler }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_file(
|
||||||
|
device: &Arc<Device>,
|
||||||
|
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||||
|
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||||
|
path: &str,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let image = image::open(path)?;
|
||||||
|
Self::from_dynamic_image(device, memory_allocator, builder, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bytes(
|
||||||
|
device: &Arc<Device>,
|
||||||
|
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||||
|
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||||
|
bytes: &[u8],
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let image = image::load_from_memory(bytes)?;
|
||||||
|
Self::from_dynamic_image(device, memory_allocator, builder, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_dynamic_image(
|
||||||
|
device: &Arc<Device>,
|
||||||
|
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||||
|
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||||
|
image: DynamicImage,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let image_data = image.to_rgba8();
|
||||||
|
let image_dimensions = image_data.dimensions();
|
||||||
|
|
||||||
|
let upload_buffer = Buffer::from_iter(
|
||||||
|
memory_allocator.clone(),
|
||||||
|
BufferCreateInfo {
|
||||||
|
usage: BufferUsage::TRANSFER_SRC,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AllocationCreateInfo {
|
||||||
|
memory_type_filter: MemoryTypeFilter::PREFER_HOST
|
||||||
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
image_data.to_vec(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let image = Image::new(
|
||||||
|
memory_allocator.clone(),
|
||||||
|
ImageCreateInfo {
|
||||||
|
image_type: ImageType::Dim2d,
|
||||||
|
format: Format::R8G8B8A8_SRGB,
|
||||||
|
extent: [image_dimensions.0 as u32, image_dimensions.1 as u32, 1],
|
||||||
|
array_layers: 1,
|
||||||
|
usage: ImageUsage::TRANSFER_DST | ImageUsage::SAMPLED,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AllocationCreateInfo::default(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
builder.copy_buffer_to_image(CopyBufferToImageInfo::buffer_image(
|
||||||
|
upload_buffer,
|
||||||
|
image.clone(),
|
||||||
|
))?;
|
||||||
|
|
||||||
|
let sampler = Sampler::new(
|
||||||
|
device.clone(),
|
||||||
|
SamplerCreateInfo {
|
||||||
|
mag_filter: Filter::Linear,
|
||||||
|
min_filter: Filter::Linear,
|
||||||
|
address_mode: [SamplerAddressMode::Repeat; 3],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let image_view = ImageView::new_default(image)?;
|
||||||
|
|
||||||
|
log::trace!("Texture loaded with dimensions {:?}", image_dimensions);
|
||||||
|
|
||||||
|
Ok(Self::new(image_view, sampler))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_texture(&self) -> &Arc<ImageView> {
|
||||||
|
&self.texture
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sampler(&self) -> &Arc<Sampler> {
|
||||||
|
&self.sampler
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,67 +3,35 @@ use crate::core::render::pipelines::triangle_pipeline::create_triangle_pipeline;
|
||||||
use crate::core::render::primitives::camera::Camera;
|
use crate::core::render::primitives::camera::Camera;
|
||||||
use crate::core::render::primitives::vertex::Vertex2D;
|
use crate::core::render::primitives::vertex::Vertex2D;
|
||||||
use crate::core::render::render_context::RenderContext;
|
use crate::core::render::render_context::RenderContext;
|
||||||
|
use crate::core::render::texture::Texture;
|
||||||
use crate::core::scene::Scene;
|
use crate::core::scene::Scene;
|
||||||
use crate::core::timer::Timer;
|
use crate::core::timer::Timer;
|
||||||
use glam::{Mat4, Quat, Vec3};
|
use glam::{Mat4, Quat, Vec3};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vulkano::buffer::Subbuffer;
|
use vulkano::buffer::Subbuffer;
|
||||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer};
|
use vulkano::command_buffer::{
|
||||||
|
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer,
|
||||||
|
PrimaryCommandBufferAbstract,
|
||||||
|
};
|
||||||
use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet};
|
use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet};
|
||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
||||||
|
|
||||||
const VERTICES: [Vertex2D; 12] = [
|
const VERTICES: [Vertex2D; 4] = [
|
||||||
// Triangle en haut à gauche
|
|
||||||
Vertex2D {
|
Vertex2D {
|
||||||
position: [-0.5, -0.75],
|
position: [-0.5, -0.5],
|
||||||
color: [1.0, 0.0, 0.0],
|
uv: [0.0, 0.0],
|
||||||
},
|
},
|
||||||
Vertex2D {
|
Vertex2D {
|
||||||
position: [-0.75, -0.25],
|
position: [-0.5, 0.5],
|
||||||
color: [0.0, 1.0, 0.0],
|
uv: [0.0, 1.0],
|
||||||
},
|
},
|
||||||
Vertex2D {
|
Vertex2D {
|
||||||
position: [-0.25, -0.25],
|
position: [0.5, -0.5],
|
||||||
color: [0.0, 0.0, 1.0],
|
uv: [1.0, 0.0],
|
||||||
},
|
|
||||||
// Triangle en bas à gauche
|
|
||||||
Vertex2D {
|
|
||||||
position: [-0.5, 0.25],
|
|
||||||
color: [0.5, 0.5, 0.5],
|
|
||||||
},
|
},
|
||||||
Vertex2D {
|
Vertex2D {
|
||||||
position: [-0.75, 0.75],
|
position: [0.5, 0.5],
|
||||||
color: [0.2, 0.8, 0.2],
|
uv: [1.0, 1.0],
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [-0.25, 0.75],
|
|
||||||
color: [0.8, 0.2, 0.2],
|
|
||||||
},
|
|
||||||
// Triangle en haut à droite
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.5, -0.75],
|
|
||||||
color: [1.0, 1.0, 0.0],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.25, -0.25],
|
|
||||||
color: [0.0, 1.0, 1.0],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.75, -0.25],
|
|
||||||
color: [1.0, 0.0, 1.0],
|
|
||||||
},
|
|
||||||
// Triangle en bas à droite
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.5, 0.25],
|
|
||||||
color: [0.1, 0.5, 0.8],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.25, 0.75],
|
|
||||||
color: [0.8, 0.6, 0.1],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.75, 0.75],
|
|
||||||
color: [0.3, 0.4, 0.6],
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -71,6 +39,7 @@ pub struct MainSceneState {
|
||||||
pipeline: Arc<GraphicsPipeline>,
|
pipeline: Arc<GraphicsPipeline>,
|
||||||
vertex_buffer: Subbuffer<[Vertex2D]>,
|
vertex_buffer: Subbuffer<[Vertex2D]>,
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
|
texture: Texture,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -105,11 +74,33 @@ impl Scene for MainScene {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut uploads = AutoCommandBufferBuilder::primary(
|
||||||
|
render_context.command_buffer_allocator().clone(),
|
||||||
|
render_context.graphics_queue().queue_family_index(),
|
||||||
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let texture = Texture::from_file(
|
||||||
|
render_context.device(),
|
||||||
|
render_context.memory_allocator(),
|
||||||
|
&mut uploads,
|
||||||
|
"res/textures/wooden-crate.jpg",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let _ = uploads
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.execute(render_context.graphics_queue().clone())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.state = Some(MainSceneState {
|
self.state = Some(MainSceneState {
|
||||||
pipeline,
|
pipeline,
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
camera,
|
camera,
|
||||||
})
|
texture,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
|
@ -157,21 +148,32 @@ impl Scene for MainScene {
|
||||||
) {
|
) {
|
||||||
let state = self.state.as_ref().unwrap();
|
let state = self.state.as_ref().unwrap();
|
||||||
let vertex_count = state.vertex_buffer.len() as u32;
|
let vertex_count = state.vertex_buffer.len() as u32;
|
||||||
let instance_count = vertex_count / 3;
|
let instance_count = vertex_count / 4;
|
||||||
|
|
||||||
let layout = &state.pipeline.layout().set_layouts()[0];
|
let layouts = state.pipeline.layout().set_layouts();
|
||||||
let uniform_buffer = state
|
let uniform_buffer = state
|
||||||
.camera
|
.camera
|
||||||
.create_buffer(render_context.memory_allocator())
|
.create_buffer(render_context.memory_allocator())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let descriptor_set = DescriptorSet::new(
|
let uniform_descriptor_set = DescriptorSet::new(
|
||||||
render_context.descriptor_set_allocator().clone(),
|
render_context.descriptor_set_allocator().clone(),
|
||||||
layout.clone(),
|
layouts[0].clone(),
|
||||||
[WriteDescriptorSet::buffer(0, uniform_buffer)],
|
[WriteDescriptorSet::buffer(0, uniform_buffer)],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let texture_descriptor_set = DescriptorSet::new(
|
||||||
|
render_context.descriptor_set_allocator().clone(),
|
||||||
|
layouts[1].clone(),
|
||||||
|
[
|
||||||
|
WriteDescriptorSet::sampler(0, state.texture.get_sampler().clone()),
|
||||||
|
WriteDescriptorSet::image_view(1, state.texture.get_texture().clone()),
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
builder
|
builder
|
||||||
.bind_pipeline_graphics(state.pipeline.clone())
|
.bind_pipeline_graphics(state.pipeline.clone())
|
||||||
|
@ -180,7 +182,7 @@ impl Scene for MainScene {
|
||||||
PipelineBindPoint::Graphics,
|
PipelineBindPoint::Graphics,
|
||||||
state.pipeline.layout().clone(),
|
state.pipeline.layout().clone(),
|
||||||
0,
|
0,
|
||||||
descriptor_set,
|
vec![uniform_descriptor_set, texture_descriptor_set],
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.bind_vertex_buffers(0, state.vertex_buffer.clone())
|
.bind_vertex_buffers(0, state.vertex_buffer.clone())
|
||||||
|
|
|
@ -21,7 +21,7 @@ fn main() {
|
||||||
vec![
|
vec![
|
||||||
VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyW), AxisDirection::Normal),
|
VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyW), AxisDirection::Normal),
|
||||||
VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyS), AxisDirection::Invert),
|
VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyS), AxisDirection::Invert),
|
||||||
VirtualBinding::Axis(0, AxisDirection::Normal, 1.0),
|
VirtualBinding::Axis(0, AxisDirection::Normal, 0.0),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -29,7 +29,7 @@ fn main() {
|
||||||
vec![
|
vec![
|
||||||
VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyD), AxisDirection::Normal),
|
VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyD), AxisDirection::Normal),
|
||||||
VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyA), AxisDirection::Invert),
|
VirtualBinding::Keyboard(PhysicalKey::Code(KeyCode::KeyA), AxisDirection::Invert),
|
||||||
VirtualBinding::Axis(1, AxisDirection::Normal, 1.0),
|
VirtualBinding::Axis(1, AxisDirection::Normal, 0.0),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue