tutorial5-textures done
This commit is contained in:
parent
edb71eb9aa
commit
fad62b21e7
6 changed files with 286 additions and 28 deletions
95
Cargo.lock
generated
95
Cargo.lock
generated
|
@ -1,5 +1,20 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.2.0"
|
||||
|
@ -62,6 +77,20 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide 0.4.1",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
|
@ -371,6 +400,28 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.21",
|
||||
"quote 1.0.7",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
|
@ -658,6 +709,12 @@ dependencies = [
|
|||
"lzw",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.15"
|
||||
|
@ -892,6 +949,15 @@ dependencies = [
|
|||
"adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d7559a8a40d0f97e1edea3220f698f78b1c5ab67532e49f68fde3910323b722"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.6.22"
|
||||
|
@ -1096,6 +1162,12 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.4.1"
|
||||
|
@ -1208,7 +1280,7 @@ dependencies = [
|
|||
"bitflags",
|
||||
"crc32fast",
|
||||
"deflate",
|
||||
"miniz_oxide",
|
||||
"miniz_oxide 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1314,6 +1386,12 @@ version = "0.1.57"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
|
||||
[[package]]
|
||||
name = "rusttype"
|
||||
version = "0.7.9"
|
||||
|
@ -1459,6 +1537,18 @@ dependencies = [
|
|||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.21",
|
||||
"quote 1.0.7",
|
||||
"syn",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.20"
|
||||
|
@ -1487,7 +1577,7 @@ checksum = "3f3b8a87c4da944c3f27e5943289171ac71a6150a79ff6bacfff06d159dfff2f"
|
|||
dependencies = [
|
||||
"byteorder",
|
||||
"lzw",
|
||||
"miniz_oxide",
|
||||
"miniz_oxide 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1744,6 +1834,7 @@ name = "wgpu-tutorial"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"failure",
|
||||
"futures",
|
||||
"image",
|
||||
"shaderc",
|
||||
|
|
|
@ -13,3 +13,4 @@ image = "0.23.9"
|
|||
futures = "0.3.5"
|
||||
shaderc = "0.6.2"
|
||||
bytemuck = "1.4.1"
|
||||
failure = "0.1.8"
|
||||
|
|
106
src/main.rs
106
src/main.rs
|
@ -5,6 +5,8 @@ use winit::{
|
|||
window::{Window, WindowBuilder},
|
||||
};
|
||||
|
||||
mod texture;
|
||||
|
||||
fn main() {
|
||||
let event_loop = EventLoop::new();
|
||||
let window = WindowBuilder::new()
|
||||
|
@ -60,6 +62,9 @@ struct State {
|
|||
sc_desc: wgpu::SwapChainDescriptor,
|
||||
swap_chain: wgpu::SwapChain,
|
||||
|
||||
diffuse_texture: texture::Texture,
|
||||
diffuse_bind_group: wgpu::BindGroup,
|
||||
|
||||
vertex_buffer: wgpu::Buffer,
|
||||
index_buffer: wgpu::Buffer,
|
||||
num_indices: u32,
|
||||
|
@ -106,6 +111,51 @@ impl State {
|
|||
|
||||
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
|
||||
|
||||
// Load image
|
||||
let diffuse_bytes = include_bytes!("snubben.png");
|
||||
let (diffuse_texture, command) =
|
||||
texture::Texture::from_bytes(&device, diffuse_bytes, "diffuse_texture").unwrap();
|
||||
queue.submit(Some(command));
|
||||
|
||||
let texture_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("texture_bind_group_layout"),
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
component_type: wgpu::TextureComponentType::Uint,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false },
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let diffuse_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("diffuse_bind_group"),
|
||||
layout: &texture_bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(&diffuse_texture.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Compile & load shaders
|
||||
let vs_src = include_str!("shader.vert");
|
||||
let fs_src = include_str!("shader.frag");
|
||||
|
||||
|
@ -135,28 +185,30 @@ impl State {
|
|||
let vs_module = device.create_shader_module(vs_data);
|
||||
let fs_module = device.create_shader_module(fs_data);
|
||||
|
||||
// Setup buffers
|
||||
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Vertex buffer"),
|
||||
label: Some("vertex_buffer"),
|
||||
contents: bytemuck::cast_slice(&VERTICES),
|
||||
usage: wgpu::BufferUsage::VERTEX,
|
||||
});
|
||||
|
||||
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Index buffer"),
|
||||
label: Some("index_buffer"),
|
||||
contents: bytemuck::cast_slice(&INDICES),
|
||||
usage: wgpu::BufferUsage::INDEX,
|
||||
});
|
||||
let num_indices = INDICES.len() as u32;
|
||||
|
||||
// Setup render pipeline
|
||||
let render_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Render pipeline layout"),
|
||||
bind_group_layouts: &[],
|
||||
label: Some("render_pipeline_layout"),
|
||||
bind_group_layouts: &[&texture_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render pipeline"),
|
||||
label: Some("render_pipeline"),
|
||||
layout: Some(&render_pipeline_layout),
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vs_module,
|
||||
|
@ -184,9 +236,7 @@ impl State {
|
|||
depth_stencil_state: None, // TODO
|
||||
vertex_state: wgpu::VertexStateDescriptor {
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[
|
||||
Vertex::desc(),
|
||||
],
|
||||
vertex_buffers: &[Vertex::desc()],
|
||||
},
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
|
@ -201,6 +251,8 @@ impl State {
|
|||
queue,
|
||||
sc_desc,
|
||||
swap_chain,
|
||||
diffuse_texture,
|
||||
diffuse_bind_group,
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
num_indices,
|
||||
|
@ -254,6 +306,7 @@ impl State {
|
|||
});
|
||||
|
||||
render_pass.set_pipeline(&self.render_pipeline);
|
||||
render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]);
|
||||
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(0..));
|
||||
render_pass.set_index_buffer(self.index_buffer.slice(0..));
|
||||
render_pass.draw_indexed(0..self.num_indices, 0, 0..1);
|
||||
|
@ -268,7 +321,7 @@ impl State {
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
struct Vertex {
|
||||
position: [f32; 3],
|
||||
color: [f32; 3],
|
||||
tex_coords: [f32; 2],
|
||||
}
|
||||
|
||||
unsafe impl bytemuck::Pod for Vertex {}
|
||||
|
@ -288,24 +341,35 @@ impl Vertex {
|
|||
},
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
|
||||
format: wgpu::VertexFormat::Float3,
|
||||
format: wgpu::VertexFormat::Float2,
|
||||
shader_location: 1,
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const VERTICES: &[Vertex] = &[
|
||||
Vertex { position: [-0.0868241, 0.49240386, 0.0], color: [0.5, 0.0, 0.5] },
|
||||
Vertex { position: [-0.49513406, 0.06958647, 0.0], color: [0.5, 0.0, 0.5] },
|
||||
Vertex { position: [-0.21918549, -0.44939706, 0.0], color: [0.5, 0.0, 0.5] },
|
||||
Vertex { position: [0.35966998, -0.3473291, 0.0], color: [0.5, 0.0, 0.5] },
|
||||
Vertex { position: [0.44147372, 0.2347359, 0.0],color: [0.5, 0.0, 0.5] },
|
||||
Vertex {
|
||||
position: [-0.0868241, 0.49240386, 0.0],
|
||||
tex_coords: [0.4131759, 0.00759614],
|
||||
},
|
||||
Vertex {
|
||||
position: [-0.49513406, 0.06958647, 0.0],
|
||||
tex_coords: [0.0048659444, 0.43041354],
|
||||
},
|
||||
Vertex {
|
||||
position: [-0.21918549, -0.44939706, 0.0],
|
||||
tex_coords: [0.28081453, 0.949397057],
|
||||
},
|
||||
Vertex {
|
||||
position: [0.35966998, -0.3473291, 0.0],
|
||||
tex_coords: [0.85967, 0.84732911],
|
||||
},
|
||||
Vertex {
|
||||
position: [0.44147372, 0.2347359, 0.0],
|
||||
tex_coords: [0.9414737, 0.2652641],
|
||||
},
|
||||
];
|
||||
|
||||
const INDICES: &[u16] = &[
|
||||
0, 1, 4,
|
||||
1, 2, 4,
|
||||
2, 3, 4,
|
||||
];
|
||||
const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4];
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#version 450
|
||||
|
||||
layout(location=0) in vec3 v_color;
|
||||
layout(location=0) in vec2 v_tex_coords;
|
||||
layout(location=0) out vec4 f_color;
|
||||
|
||||
layout(set = 0, binding = 0) uniform texture2D t_diffuse;
|
||||
layout(set = 0, binding = 1) uniform sampler s_diffuse;
|
||||
|
||||
void main() {
|
||||
f_color = vec4(v_color, 1.0);
|
||||
f_color = texture(sampler2D(t_diffuse, s_diffuse), v_tex_coords);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#version 450
|
||||
|
||||
layout(location=0) in vec3 a_position;
|
||||
layout(location=1) in vec3 a_color;
|
||||
layout(location=1) in vec2 a_tex_coords;
|
||||
|
||||
layout(location=0) out vec3 v_color;
|
||||
layout(location=0) out vec2 v_tex_coords;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(a_position, 1.0);
|
||||
v_color = a_color;
|
||||
v_tex_coords = a_tex_coords;
|
||||
}
|
||||
|
|
99
src/texture.rs
Normal file
99
src/texture.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
use image::GenericImageView;
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
pub struct Texture {
|
||||
pub texture: wgpu::Texture,
|
||||
pub view: wgpu::TextureView,
|
||||
pub sampler: wgpu::Sampler,
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
pub fn from_bytes(
|
||||
device: &wgpu::Device,
|
||||
bytes: &[u8],
|
||||
label: &str,
|
||||
) -> Result<(Self, wgpu::CommandBuffer), failure::Error> {
|
||||
let img = image::load_from_memory(bytes)?;
|
||||
Self::from_image(device, &img, Some(label))
|
||||
}
|
||||
|
||||
pub fn from_image(
|
||||
device: &wgpu::Device,
|
||||
img: &image::DynamicImage,
|
||||
label: Option<&str>,
|
||||
) -> Result<(Self, wgpu::CommandBuffer), failure::Error> {
|
||||
let rgba = img.as_rgba8().unwrap();
|
||||
|
||||
let (width, height) = img.dimensions();
|
||||
|
||||
let size = wgpu::Extent3d {
|
||||
width,
|
||||
height,
|
||||
depth: 1,
|
||||
};
|
||||
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("texture"),
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
|
||||
});
|
||||
|
||||
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("buffer"),
|
||||
contents: &rgba,
|
||||
usage: wgpu::BufferUsage::COPY_SRC,
|
||||
});
|
||||
|
||||
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("texture_buffer_copy_encoder"),
|
||||
});
|
||||
|
||||
encoder.copy_buffer_to_texture(
|
||||
wgpu::BufferCopyView {
|
||||
buffer: &buffer,
|
||||
layout: wgpu::TextureDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: 4 * width,
|
||||
rows_per_image: height,
|
||||
},
|
||||
},
|
||||
wgpu::TextureCopyView {
|
||||
texture: &texture,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d::ZERO,
|
||||
},
|
||||
size,
|
||||
);
|
||||
|
||||
let command = encoder.finish();
|
||||
|
||||
let view = texture.create_view(&Default::default());
|
||||
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
label: Some("sampler"),
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
min_filter: wgpu::FilterMode::Nearest,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
lod_min_clamp: -100.0,
|
||||
lod_max_clamp: 100.0,
|
||||
compare: None,
|
||||
anisotropy_clamp: None,
|
||||
});
|
||||
|
||||
Ok((
|
||||
Texture {
|
||||
texture,
|
||||
view,
|
||||
sampler,
|
||||
},
|
||||
command,
|
||||
))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue