1
0
Fork 0

tutorial5-textures done

This commit is contained in:
Adrian Hedqvist 2020-09-12 23:50:58 +02:00
parent edb71eb9aa
commit fad62b21e7
6 changed files with 286 additions and 28 deletions

95
Cargo.lock generated
View file

@ -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",

View file

@ -13,3 +13,4 @@ image = "0.23.9"
futures = "0.3.5"
shaderc = "0.6.2"
bytemuck = "1.4.1"
failure = "0.1.8"

View file

@ -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];

View file

@ -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);
}

View file

@ -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
View 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,
))
}
}