Merge branch 'master' into master

pull/427/head
sotrh 1 year ago committed by GitHub
commit f94875e2a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

733
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -14,5 +14,5 @@ members = [
]
exclude = [
"code/showcase/imgui-demo",
"code/showcase/pong",
#"code/showcase/pong",
]

@ -1,6 +1,6 @@
export RES_PATH=learn-wgpu
# (trap 'killall background' INT;
# wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/pong code/showcase/pong
wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/pong code/showcase/pong
wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial1_window code/beginner/tutorial1-window
wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial2_surface code/beginner/tutorial2-surface
wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial3_pipeline code/beginner/tutorial3-pipeline

@ -14,7 +14,7 @@ path = "src/main.rs"
[dependencies]
cfg-if = "1"
winit = "0.27"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
wgpu = "0.14"
pollster = "0.2"

@ -10,7 +10,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
winit = "0.27"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
wgpu = "0.14"
pollster = "0.2"

@ -17,16 +17,23 @@ struct State {
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
clear_color: wgpu::Color,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -75,9 +82,14 @@ impl State {
config,
clear_color,
size,
window,
}
}
fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -148,14 +160,14 @@ async fn run() {
let window = WindowBuilder::new().build(&event_loop).unwrap();
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -179,7 +191,7 @@ async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -192,7 +204,7 @@ async fn run() {
}
}
Event::MainEventsCleared => {
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -15,16 +15,23 @@ struct State {
queue: wgpu::Queue,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -69,9 +76,14 @@ impl State {
queue,
config,
size,
window,
}
}
fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -161,14 +173,14 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
// UPDATED!
match event {
@ -193,7 +205,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -208,7 +220,7 @@ pub async fn run() {
Event::RedrawEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -10,7 +10,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
winit = "0.27"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
wgpu = "0.14"
pollster = "0.2"

@ -15,16 +15,23 @@ struct State {
render_pipeline: wgpu::RenderPipeline,
challenge_render_pipeline: wgpu::RenderPipeline,
use_color: bool,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -172,9 +179,14 @@ impl State {
challenge_render_pipeline,
use_color,
size,
window,
}
}
fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -260,14 +272,14 @@ async fn run() {
let window = WindowBuilder::new().build(&event_loop).unwrap();
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -291,7 +303,7 @@ async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -306,7 +318,7 @@ async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -17,16 +17,23 @@ struct State {
size: winit::dpi::PhysicalSize<u32>,
// NEW!
render_pipeline: wgpu::RenderPipeline,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -127,9 +134,14 @@ impl State {
size,
config,
render_pipeline,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -222,14 +234,14 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -253,7 +265,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -268,7 +280,7 @@ pub async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -12,11 +12,11 @@ crate-type = ["cdylib", "rlib"]
cfg-if = "1"
winit = "0.27"
wgpu = "0.14"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
pollster = "0.2"
# NEW!
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = "0.1"

@ -78,16 +78,23 @@ struct State {
use_complex: bool,
size: winit::dpi::PhysicalSize<u32>,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -240,9 +247,14 @@ impl State {
num_challenge_indices,
use_complex,
size,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -337,14 +349,14 @@ async fn run() {
let window = WindowBuilder::new().build(&event_loop).unwrap();
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -368,7 +380,7 @@ async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -383,7 +395,7 @@ async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -74,16 +74,23 @@ struct State {
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
num_indices: u32,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -199,9 +206,14 @@ impl State {
vertex_buffer,
index_buffer,
num_indices,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -296,14 +308,14 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -327,7 +339,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -342,7 +354,7 @@ pub async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -10,8 +10,8 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
env_logger = "0.9"
bytemuck = { version = "1.12", features = [ "derive" ] }
env_logger = "0.10"
log = "0.4"
pollster = "0.2"
wgpu = "0.14"

@ -80,16 +80,23 @@ struct State {
cartoon_texture: texture::Texture,
cartoon_bind_group: wgpu::BindGroup,
is_space_pressed: bool,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -271,9 +278,14 @@ impl State {
cartoon_bind_group,
size,
is_space_pressed: false,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -364,14 +376,14 @@ async fn run() {
let window = WindowBuilder::new().build(&event_loop).unwrap();
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -395,7 +407,7 @@ async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -410,7 +422,7 @@ async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -80,16 +80,23 @@ struct State {
#[allow(dead_code)]
diffuse_texture: texture::Texture,
diffuse_bind_group: wgpu::BindGroup,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -248,9 +255,14 @@ impl State {
num_indices,
diffuse_texture,
diffuse_bind_group,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -346,14 +358,14 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -377,7 +389,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -392,7 +404,7 @@ pub async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
pollster = "0.2"
wgpu = "0.14"

@ -230,16 +230,23 @@ struct State {
camera_buffer: wgpu::Buffer,
camera_bind_group: wgpu::BindGroup,
size: winit::dpi::PhysicalSize<u32>,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -448,9 +455,14 @@ impl State {
camera_bind_group,
camera_uniform,
size,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -535,14 +547,14 @@ async fn run() {
let window = WindowBuilder::new().build(&event_loop).unwrap();
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -566,7 +578,7 @@ async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -581,7 +593,7 @@ async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -230,16 +230,23 @@ struct State {
camera_uniform: CameraUniform,
camera_buffer: wgpu::Buffer,
camera_bind_group: wgpu::BindGroup,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -447,9 +454,14 @@ impl State {
camera_buffer,
camera_bind_group,
camera_uniform,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -555,14 +567,14 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -586,7 +598,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -601,7 +613,7 @@ pub async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
pollster = "0.2"
wgpu = "0.14"

@ -284,16 +284,23 @@ struct State {
size: winit::dpi::PhysicalSize<u32>,
instances: Vec<Instance>,
instance_buffer: wgpu::Buffer,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -535,9 +542,14 @@ impl State {
size,
instances,
instance_buffer,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -636,14 +648,14 @@ async fn run() {
let window = WindowBuilder::new().build(&event_loop).unwrap();
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -667,7 +679,7 @@ async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -682,7 +694,7 @@ async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -291,16 +291,23 @@ struct State {
instances: Vec<Instance>,
#[allow(dead_code)]
instance_buffer: wgpu::Buffer,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -540,12 +547,17 @@ impl State {
camera_buffer,
camera_bind_group,
camera_uniform,
window,
// NEW!
instances,
instance_buffer,
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -653,14 +665,14 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -684,7 +696,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -699,7 +711,7 @@ pub async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
log = "0.4"
wgpu = "0.14"

@ -472,16 +472,23 @@ struct State {
#[allow(dead_code)]
instance_buffer: wgpu::Buffer,
depth_pass: DepthPass,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -732,12 +739,18 @@ impl State {
camera_buffer,
camera_bind_group,
camera_uniform,
window,
size,
instances,
instance_buffer,
depth_pass,
}
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -831,14 +844,14 @@ async fn run() {
let window = WindowBuilder::new().build(&event_loop).unwrap();
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -862,7 +875,7 @@ async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -877,7 +890,7 @@ async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -301,16 +301,23 @@ struct State {
instance_buffer: wgpu::Buffer,
// NEW!
depth_texture: texture::Texture,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -562,9 +569,14 @@ impl State {
instances,
instance_buffer,
depth_texture,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
@ -680,14 +692,14 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -711,7 +723,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -726,7 +738,7 @@ pub async fn run() {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
_ => {}
}

@ -41,7 +41,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -9,10 +9,10 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cfg-if = "1"
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
log = "0.4"
tobj = { version = "3.2", features = ["async"]}

@ -240,17 +240,24 @@ struct State {
#[allow(dead_code)]
instance_buffer: wgpu::Buffer,
depth_texture: texture::Texture,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
log::warn!("WGPU setup");
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -477,9 +484,14 @@ impl State {
instances,
instance_buffer,
depth_texture,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
@ -598,16 +610,16 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::MainEventsCleared => state.window().request_redraw(),
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -630,7 +642,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}

@ -40,7 +40,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
log = "0.4"
tobj = { version = "3.2", features = ["async"]}

@ -256,6 +256,7 @@ struct LightUniform {
}
struct State {
window: Window,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
@ -339,13 +340,19 @@ fn create_render_pipeline(
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -594,9 +601,14 @@ impl State {
light_buffer,
light_bind_group,
light_render_pipeline,
window,
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
@ -738,16 +750,16 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::MainEventsCleared => state.window().request_redraw(),
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -770,7 +782,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}

@ -40,7 +40,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
log = "0.4"
tobj = { version = "3.2", features = ["async"]}

@ -254,6 +254,7 @@ struct LightUniform {
}
struct State {
window: Window,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
@ -339,13 +340,19 @@ fn create_render_pipeline(
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -624,6 +631,7 @@ impl State {
};
Self {
window,
surface,
device,
queue,
@ -648,6 +656,10 @@ impl State {
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
@ -786,16 +798,16 @@ pub async fn run() {
}
// State::new uses async code, so we're going to wait for it to finish
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::MainEventsCleared => state.window().request_redraw(),
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -818,7 +830,7 @@ pub async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}

@ -40,7 +40,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
log = "0.4"
tobj = { version = "3.2", features = ["async"]}

@ -131,6 +131,7 @@ struct LightUniform {
}
struct State {
window: Window,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
@ -219,13 +220,19 @@ fn create_render_pipeline(
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -494,6 +501,7 @@ impl State {
};
Self {
window,
surface,
device,
queue,
@ -521,6 +529,10 @@ impl State {
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
// UPDATED!
if new_size.width > 0 && new_size.height > 0 {
@ -684,12 +696,12 @@ pub async fn run() {
.expect("Couldn't append canvas to document body.");
}
let mut state = State::new(&window).await; // NEW!
let mut state = State::new(window).await; // NEW!
let mut last_render_time = instant::Instant::now();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::MainEventsCleared => state.window().request_redraw(),
// NEW!
Event::DeviceEvent {
event: DeviceEvent::MouseMotion{ delta, },
@ -701,7 +713,7 @@ pub async fn run() {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() && !state.input(event) => {
} if window_id == state.window().id() && !state.input(event) => {
match event {
#[cfg(not(target_arch="wasm32"))]
WindowEvent::CloseRequested
@ -724,7 +736,7 @@ pub async fn run() {
}
}
// UPDATED!
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
let now = instant::Instant::now();
let dt = now - last_render_time;
last_render_time = now;

@ -40,7 +40,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = { version = "0.18", features = [ "swizzle" ] }
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
log = "0.4"
tobj = { version = "3.2", features = ["async"]}

@ -132,6 +132,7 @@ struct LightUniform {
}
struct State {
window: Window,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
@ -221,13 +222,19 @@ fn create_render_pipeline(
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -526,6 +533,7 @@ impl State {
// terrain.gen_chunk(&device, &queue, &terrain_hack_pipeline, (-(chunk_size.x as f32), 0.0, 0.0).into());
Self {
window,
surface,
device,
queue,
@ -556,6 +564,10 @@ impl State {
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
// UPDATED!
if new_size.width > 0 && new_size.height > 0 {
@ -722,13 +734,13 @@ pub async fn run() {
.expect("Couldn't append canvas to document body.");
}
let mut state = State::new(&window).await; // NEW!
window.set_visible(true);
let mut state = State::new(window).await; // NEW!
state.window().set_visible(true);
let mut last_render_time = instant::Instant::now();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::MainEventsCleared => state.window().request_redraw(),
// NEW!
Event::DeviceEvent {
event: DeviceEvent::MouseMotion{ delta, },
@ -740,7 +752,7 @@ pub async fn run() {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() && !state.input(event) => {
} if window_id == state.window().id() && !state.input(event) => {
match event {
#[cfg(not(target_arch="wasm32"))]
WindowEvent::CloseRequested
@ -763,7 +775,7 @@ pub async fn run() {
}
}
// UPDATED!
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
let now = instant::Instant::now();
let dt = now - last_render_time;
last_render_time = now;

@ -40,7 +40,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -8,7 +8,7 @@ edition = "2018"
anyhow = "1.0"
bytemuck = { version = "1.4", features = ["derive"]}
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
image = "0.24"
log = "0.4"

@ -155,16 +155,23 @@ struct State {
debug_material: model::Material,
last_mouse_pos: PhysicalPosition<f64>,
mouse_pressed: bool,
window: Window,
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -438,6 +445,7 @@ impl State {
};
Self {
window,
surface,
device,
queue,
@ -465,6 +473,10 @@ impl State {
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.projection.resize(new_size.width, new_size.height);
@ -614,16 +626,16 @@ async fn run() {
.with_title(title)
.build(&event_loop)
.unwrap();
let mut state = State::new(&window).await; // NEW!
let mut state = State::new(window).await; // NEW!
let mut last_render_time = std::time::Instant::now();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::MainEventsCleared => state.window().request_redraw(),
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
@ -646,7 +658,7 @@ async fn run() {
}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
let now = std::time::Instant::now();
let dt = now - last_render_time;
last_render_time = now;

@ -54,7 +54,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -7,9 +7,9 @@ edition = "2018"
[dependencies]
anyhow = "1.0"
thiserror = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
image = "0.24.2"
log = "0.4"

@ -80,6 +80,10 @@ impl Display {
})
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn resize(&mut self, width: u32, height: u32) {
self.config.width = width;
self.config.height = height;
@ -222,7 +226,7 @@ pub async fn run<D: Demo>() -> Result<(), Error> {
Event::Resumed => is_resumed = true,
Event::Suspended => is_resumed = false,
Event::RedrawRequested(wid) => {
if wid == display.window.id() {
if wid == display.window().id() {
let now = Instant::now();
let dt = now - last_update;
last_update = now;
@ -234,7 +238,7 @@ pub async fn run<D: Demo>() -> Result<(), Error> {
}
Event::MainEventsCleared => {
if is_focused && is_resumed && !is_redraw_requested {
display.window.request_redraw();
display.window().request_redraw();
is_redraw_requested = true;
} else {
// Freeze time while the demo is not in the foreground
@ -244,7 +248,7 @@ pub async fn run<D: Demo>() -> Result<(), Error> {
Event::WindowEvent {
event, window_id, ..
} => {
if window_id == display.window.id() {
if window_id == display.window().id() {
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::Focused(f) => is_focused = f,

@ -38,7 +38,7 @@ impl<'a> Texture<'a> {
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest,
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
compare: Some(wgpu::CompareFunction::LessEqual),
..Default::default()
@ -117,7 +117,7 @@ impl<'a> Texture<'a> {
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest,
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
compare: Some(wgpu::CompareFunction::Always),
..Default::default()

@ -7,9 +7,9 @@ edition = "2018"
[dependencies]
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
image = "0.24.2"
log = "0.4"

@ -0,0 +1,12 @@
[package]
name = "lost-window"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1"
wgpu = "0.14"
winit = "0.27"
pollster = "0.2"

@ -0,0 +1,124 @@
use std::time::{Duration, Instant};
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoop,
window::WindowBuilder,
};
async fn run() -> anyhow::Result<()> {
let event_loop = EventLoop::new();
let mut window = Some(
WindowBuilder::new()
.with_visible(false)
.build(&event_loop)?,
);
let window2 = WindowBuilder::new()
.with_visible(false)
.build(&event_loop)?;
let backends = wgpu::Backends::all();
let instance = wgpu::Instance::new(backends);
let surface = unsafe { instance.create_surface(window.as_ref().unwrap()) };
let adapter = instance
.enumerate_adapters(backends)
.filter(|a| a.is_surface_supported(&surface))
.next()
.unwrap();
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: Default::default(),
limits: Default::default(),
},
None,
)
.await?;
let inner_size = window.as_ref().unwrap().inner_size();
let mut config = wgpu::SurfaceConfiguration {
width: inner_size.width,
height: inner_size.height,
format: surface.get_supported_formats(&adapter)[0],
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
present_mode: Default::default(),
alpha_mode: wgpu::CompositeAlphaMode::Auto,
};
surface.configure(&device, &config);
let start_time = Instant::now();
window.as_ref().unwrap().set_visible(true);
window2.set_visible(true);
event_loop.run(move |ev, _, cf| {
match ev {
Event::WindowEvent { event, window_id } => {
match event {
WindowEvent::Resized(size) => {
if window.is_some() && window_id == window.as_ref().unwrap().id() {
config.width = size.width;
config.height = size.height;
surface.configure(&device, &config);
}
}
WindowEvent::CloseRequested => {
// You'll only really want to close the window while testing
cf.set_exit()
}
_ => (),
}
}
Event::RedrawRequested(_) => {
let frame = match surface.get_current_texture() {
Ok(frame) => frame,
Err(e) => {
println!("An error occurred: {:?}", e);
return;
}
};
let view = frame.texture.create_view(&Default::default());
let mut encoder = device.create_command_encoder(&Default::default());
drop(encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: Default::default(),
})],
depth_stencil_attachment: None,
}));
queue.submit([encoder.finish()]);
frame.present();
}
Event::RedrawEventsCleared => {
let current_time = Instant::now();
let dt = current_time - start_time;
// last_time = current_time;
if let Some(w) = window.as_ref() {
w.request_redraw();
}
window2.request_redraw();
println!("dt: {:?}", dt);
if dt > Duration::from_secs(5) {
// Exit the loop
cf.set_exit();
} else if dt > Duration::from_secs(2) {
// Dispose of the first window
if let Some(window) = window.take() {
drop(window);
}
}
}
_ => (),
}
});
}
fn main() -> anyhow::Result<()> {
pollster::block_on(run())
}

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
log = "0.4"
tobj = { version = "3.2", features = ["async"]}

@ -132,6 +132,7 @@ struct LightUniform {
}
struct State {
window: Window,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
@ -224,13 +225,19 @@ fn create_render_pipeline(
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -503,6 +510,7 @@ impl State {
let mouse_matrix = cgmath::Matrix4::identity();
Self {
window,
surface,
device,
queue,
@ -534,6 +542,10 @@ impl State {
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
// UPDATED!
if new_size.width > 0 && new_size.height > 0 {
@ -726,12 +738,12 @@ pub async fn run() {
.expect("Couldn't append canvas to document body.");
}
let mut state = State::new(&window).await; // NEW!
let mut state = State::new(window).await; // NEW!
let mut last_render_time = instant::Instant::now();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::MainEventsCleared => state.window().request_redraw(),
// NEW!
Event::DeviceEvent {
event: DeviceEvent::MouseMotion{ delta, },
@ -743,7 +755,7 @@ pub async fn run() {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() && !state.input(event) => {
} if window_id == state.window().id() && !state.input(event) => {
match event {
#[cfg(not(target_arch="wasm32"))]
WindowEvent::CloseRequested
@ -766,7 +778,7 @@ pub async fn run() {
}
}
// UPDATED!
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
let now = instant::Instant::now();
let dt = now - last_render_time;
last_render_time = now;

@ -40,7 +40,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -9,16 +9,16 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
env_logger = "0.9"
env_logger = "0.10"
winit = "0.27"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
pollster = "0.2"
wgpu = { version = "0.14", features = ["spirv"]}
wgpu_glyph = "0.17"
wgpu_glyph = "0.18"
rand = "0.8"
rodio = { version = "0.15", default-features = false, features = ["wav"] }
rodio = { version = "0.16", default-features = false, features = ["wav"] }
log = "0.4"
instant = "0.1"
@ -26,7 +26,7 @@ instant = "0.1"
console_error_panic_hook = "0.1.6"
console_log = "0.2.0"
getrandom = { version = "0.2", features = ["js"] }
rodio = { version = "0.15", default-features = false, features = ["wasm-bindgen", "wav"] }
rodio = { version = "0.16", default-features = false, features = ["wasm-bindgen", "wav"] }
wasm-bindgen-futures = "0.4.20"
wasm-bindgen = "0.2.76"
web-sys = { version = "0.3.53", features = [
@ -41,4 +41,4 @@ anyhow = "1.0"
fs_extra = "1.2"
glob = "0.3"
rayon = "1.4"
naga = { version = "0.9", features = ["glsl-in", "spv-out", "wgsl-out"]}
naga = { version = "0.10", features = ["glsl-in", "spv-out", "wgsl-out"]}

@ -41,7 +41,13 @@ impl Render {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),

@ -10,9 +10,9 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
cfg-if = "1"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
env_logger = "0.9"
env_logger = "0.10"
pollster = "0.2"
log = "0.4"
rayon = "1.4" # NEW!

@ -131,6 +131,7 @@ struct LightUniform {
}
struct State {
window: Window,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
@ -218,13 +219,19 @@ fn create_render_pipeline(
}
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -506,6 +513,7 @@ impl State {
};
Self {
window,
surface,
device,
queue,
@ -532,6 +540,10 @@ impl State {
}
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.projection.resize(new_size.width, new_size.height);
@ -692,12 +704,12 @@ pub async fn run() {
.expect("Couldn't append canvas to document body.");
}
let mut state = State::new(&window).await; // NEW!
let mut state = State::new(window).await; // NEW!
let mut last_render_time = instant::Instant::now();
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::MainEventsCleared => window.request_redraw(),
Event::MainEventsCleared => state.window().request_redraw(),
// NEW!
Event::DeviceEvent {
event: DeviceEvent::MouseMotion{ delta, },
@ -709,7 +721,7 @@ pub async fn run() {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() && !state.input(event) => {
} if window_id == state.window().id() && !state.input(event) => {
match event {
#[cfg(not(target_arch="wasm32"))]
WindowEvent::CloseRequested
@ -731,7 +743,7 @@ pub async fn run() {
_ => {}
}
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
let now = instant::Instant::now();
let dt = now - last_render_time;
last_render_time = now;

@ -40,7 +40,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual),
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
});

@ -6,9 +6,11 @@ module.exports = {
'vuepress-plugin-code-copy': true,
'@vuepress/back-to-top': true,
'seo': {
url: (_, $site, path) => ($site.themeConfig.domain || '') + path,
},
},
themeConfig: {
domain: '/learn-wgpu',
author: {
name: 'Benjamin Hansen',
twitter: 'https://twitter.com/sotrh760',

@ -9,7 +9,7 @@ For the beginner stuff, we're going to keep things very simple, we'll add things
```toml
[dependencies]
winit = "0.27"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
wgpu = "0.14"
```
@ -83,7 +83,7 @@ If you only want to support desktops, that's all you have to do! In the next tut
If I go through this tutorial about WebGPU and never talk about using it on the web, then I'd hardly call this tutorial complete. Fortunately getting a wgpu application running in a browser is not too difficult once you get things set up.
Let's start with the changes we need to make to are `Cargo.toml`:
Let's start with the changes we need to make to our `Cargo.toml`:
```toml
[lib]

@ -13,14 +13,19 @@ struct State {
queue: wgpu::Queue,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
window: Window,
}
impl State {
// Creating some of the wgpu types requires async code
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
todo!()
}
pub fn window(&self) -> &Window {
&self.window
}
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
todo!()
}
@ -47,13 +52,19 @@ The code for this is pretty straightforward, but let's break it down a bit.
```rust
impl State {
// ...
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
let size = window.inner_size();
// The instance is a handle to our GPU
// Backends::all => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
// # Safety
//
// The surface needs to live as long as the window that created it.
// State owns the window so this should be safe.
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance.request_adapter(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -152,7 +163,7 @@ Here we are defining a config for our surface. This will define how the surface
The `usage` field describes how `SurfaceTexture`s will be used. `RENDER_ATTACHMENT` specifies that the textures will be used to write to the screen (we'll talk about more `TextureUsages`s later).
The `format` defines how `SurfaceTexture`s will be stored on the gpu. Different displays prefer different formats. We use `surface.get_preferred_format(&adapter)` to figure out the best format to use based on the display you're using.
The `format` defines how `SurfaceTexture`s will be stored on the gpu. `surface.get_supported_formats(&adapter)` returns a `Vec` of the formats that are supported by that surface. While a surface may support many formats, it usually has a format that it prefers, in which case it places that format first in the returned `Vec`. We use the format in the first position (`[0]`) to get the best format to use for that particular surface.
`width` and `height` are the width and the height in pixels of a `SurfaceTexture`. This should usually be the width and the height of the window.
@ -181,6 +192,7 @@ Now that we've configured our surface properly we can add these new fields at th
// ...
Self {
window,
surface,
device,
queue,
@ -196,7 +208,7 @@ Since our `State::new()` method is async we need to change `run()` to be async a
pub async fn run() {
// Window setup...
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
// Event loop...
}
@ -230,7 +242,7 @@ If we try to build WASM now it will fail because `wasm-bindgen` doesn't support
[dependencies]
cfg-if = "1"
winit = "0.27"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
wgpu = "0.14"
pollster = "0.2"
@ -271,7 +283,7 @@ We call this method in `run()` in the event loop for the following events.
match event {
// ...
} if window_id == window.id() => if !state.input(event) {
} if window_id == state.window().id() => if !state.input(event) {
match event {
// ...
@ -310,7 +322,7 @@ event_loop.run(move |event, _, control_flow| {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => if !state.input(event) { // UPDATED!
} if window_id == state.window().id() => if !state.input(event) { // UPDATED!
match event {
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
@ -417,7 +429,7 @@ We need to update the event loop again to call this method. We'll also call `upd
event_loop.run(move |event, _, control_flow| {
match event {
// ...
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
state.update();
match state.render() {
Ok(_) => {}
@ -432,7 +444,7 @@ event_loop.run(move |event, _, control_flow| {
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
state.window().request_redraw();
}
// ...
}

@ -70,13 +70,13 @@ To import the extension trait, put this line somewhere near the top of `lib.rs`.
use wgpu::util::DeviceExt;
```
You'll note that we're using [bytemuck](https://docs.rs/bytemuck/1.2.0/bytemuck/) to cast our `VERTICES` as a `&[u8]`. The `create_buffer_init()` method expects a `&[u8]`, and `bytemuck::cast_slice` does that for us. Add the following to your `Cargo.toml`.
You'll note that we're using [bytemuck](https://docs.rs/bytemuck/latest/bytemuck/) to cast our `VERTICES` as a `&[u8]`. The `create_buffer_init()` method expects a `&[u8]`, and `bytemuck::cast_slice` does that for us. Add the following to your `Cargo.toml`.
```toml
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
```
We're also going to need to implement two traits to get `bytemuck` to work. These are [bytemuck::Pod](https://docs.rs/bytemuck/1.3.0/bytemuck/trait.Pod.html) and [bytemuck::Zeroable](https://docs.rs/bytemuck/1.3.0/bytemuck/trait.Zeroable.html). `Pod` indicates that our `Vertex` is "Plain Old Data", and thus can be interpreted as a `&[u8]`. `Zeroable` indicates that we can use `std::mem::zeroed()`. We can modify our `Vertex` struct to derive these methods.
We're also going to need to implement two traits to get `bytemuck` to work. These are [bytemuck::Pod](https://docs.rs/bytemuck/latest/bytemuck/trait.Pod.html) and [bytemuck::Zeroable](https://docs.rs/bytemuck/latest/bytemuck/trait.Zeroable.html). `Pod` indicates that our `Vertex` is "Plain Old Data", and thus can be interpreted as a `&[u8]`. `Zeroable` indicates that we can use `std::mem::zeroed()`. We can modify our `Vertex` struct to derive these methods.
```rust
#[repr(C)]

@ -439,11 +439,11 @@ For convenience, let's pull our texture code into its own module. We'll first ne
image = "0.23"
cgmath = "0.18"
winit = "0.27"
env_logger = "0.9"
env_logger = "0.10"
log = "0.4"
pollster = "0.2"
wgpu = "0.14"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
anyhow = "1.0" # NEW!
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 33 KiB

@ -64,7 +64,7 @@ struct State {
// ...
}
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
// let diffuse_bind_group ...
let camera = Camera {
@ -203,7 +203,7 @@ struct State {
camera_bind_group: wgpu::BindGroup,
}
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
// ...
Self {
// ...
@ -375,7 +375,7 @@ struct State {
}
// ...
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
// ...
let camera_controller = CameraController::new(0.2);
// ...

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 30 KiB

@ -98,7 +98,7 @@ Now we can create the actual instances.
```rust
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
// ...
let instances = (0..NUM_INSTANCES_PER_ROW).flat_map(|z| {
(0..NUM_INSTANCES_PER_ROW).map(move |x| {

@ -54,7 +54,7 @@ impl Texture {
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
compare: Some(wgpu::CompareFunction::LessEqual), // 5.
lod_min_clamp: -100.0,
lod_min_clamp: 0.0,
lod_max_clamp: 100.0,
..Default::default()
}
@ -93,7 +93,7 @@ let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescrip
});
```
1. The `depth_compare` function tells us when to discard a new pixel. Using `LESS` means pixels will be drawn front to back. The other possible values for a [CompareFunction](https://docs.rs/wgpu/latest/wgpu/enum.CompareFunction.html) that you can use:
1. The `depth_compare` function tells us when to discard a new pixel. Using `LESS` means pixels will be drawn front to back. Here are the other possible values for a [CompareFunction](https://docs.rs/wgpu/latest/wgpu/enum.CompareFunction.html) that you can use:
```rust
#[repr(C)]
@ -117,9 +117,20 @@ pub enum CompareFunction {
Don't forget to store the `depth_texture` in `State`.
```rust
Self {
// ...
depth_texture,
struct State {
// ...
depth_texture: Texture,
// ...
}
async fn new(window: Window) -> Self {
// ...
Self {
// ...
depth_texture,
// ...
}
}
```

@ -114,7 +114,6 @@ impl Material {
}
```
Now we can use the texture in the fragment shader.
```wgsl
@ -366,12 +365,12 @@ Next, we'll construct the `tangent_matrix` and then transform the vertex's light
```wgsl
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>;
@location(0) tex_coords: vec2<f32>;
@builtin(position) clip_position: vec4<f32>,
@location(0) tex_coords: vec2<f32>,
// UPDATED!
@location(1) tangent_position: vec3<f32>;
@location(2) tangent_light_position: vec3<f32>;
@location(3) tangent_view_position: vec3<f32>;
@location(1) tangent_position: vec3<f32>,
@location(2) tangent_light_position: vec3<f32>,
@location(3) tangent_view_position: vec3<f32>,
};
@vertex
@ -441,7 +440,7 @@ pub fn from_image(
img: &image::DynamicImage,
label: Option<&str>,
is_normal_map: bool, // NEW!
) -> Result<(Self, wgpu::CommandBuffer), failure::Error> {
) -> Result<Self> {
// ...
let texture = device.create_texture(&wgpu::TextureDescriptor {
label,
@ -460,7 +459,11 @@ pub fn from_image(
// ...
Ok((Self { texture, view, sampler }, cmd_buffer))
Ok(Self {
texture,
view,
sampler,
})
}
```

@ -294,7 +294,7 @@ We need to update `new()` as well.
```rust
impl State {
async fn new(window: &Window) -> Self {
async fn new(window: Window) -> Self {
// ...
// UPDATED!
@ -384,7 +384,7 @@ fn main() {
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() && !state.input(event) => {
} if window_id == state.window().id() && !state.input(event) => {
match event {
#[cfg(not(target_arch="wasm32"))]
WindowEvent::CloseRequested
@ -437,14 +437,14 @@ We still need to calculate `dt`. Let's do that in the `main` function.
```rust
fn main() {
// ...
let mut state = State::new(&window).await;
let mut state = State::new(window).await;
let mut last_render_time = instant::Instant::now(); // NEW!
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
// ...
// UPDATED!
Event::RedrawRequested(window_id) if window_id == window.id() => {
Event::RedrawRequested(window_id) if window_id == state.window().id() => {
let now = instant::Instant::now();
let dt = now - last_render_time;
last_render_time = now;

@ -262,10 +262,10 @@ In order for wasm-pack to work properly I first needed to add some dependencies:
```toml[dependencies]
cfg-if = "1"
env_logger = "0.9"
env_logger = "0.10"
winit = "0.27"
anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
bytemuck = { version = "1.12", features = [ "derive" ] }
cgmath = "0.18"
pollster = "0.2"
wgpu = { version = "0.14", features = ["spirv"]}

@ -8,11 +8,11 @@
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "./build-wasm.sh && vuepress dev docs",
"build": "./build-wasm.sh && vuepress build docs",
"dev": "NODE_OPTIONS=--openssl-legacy-provider; ./build-wasm.sh && vuepress dev docs",
"build": "NODE_OPTIONS=--openssl-legacy-provider; ./build-wasm.sh && vuepress build docs",
"deploy": "sh deploy.sh",
"just-build": "vuepress build docs",
"just-dev": "vuepress dev docs"
"just-build": "NODE_OPTIONS=--openssl-legacy-provider; vuepress build docs",
"just-dev": "NODE_OPTIONS=--openssl-legacy-provider; vuepress dev docs"
},
"author": "",
"license": "ISC",
@ -22,6 +22,5 @@
"vuepress-plugin-code-copy": "^1.0.6",
"vuepress-plugin-seo": "^0.1.4",
"vuepress-theme-thindark": "^1.0.1"
},
"dependencies": {}
}
}

20342
yarn.lock

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save