Compare commits

...

3 Commits

Author SHA1 Message Date
Benjamin Hansen ce957226d3 cargo fmt 1 month ago
Benjamin Hansen 09c1024a8f fixed non-srgb on hdr tutorial 1 month ago
Benjamin Hansen 3d27fca202 demos working 1 month ago

3
Cargo.lock generated

@ -1671,6 +1671,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]

@ -10,11 +10,13 @@ pub struct Texture {
impl Texture {
pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
#[allow(unused)]
pub fn create_depth_texture(
device: &wgpu::Device,
config: &wgpu::SurfaceConfiguration,
label: &str,
) -> Self {let size = wgpu::Extent3d {
) -> Self {
let size = wgpu::Extent3d {
width: config.width.max(1),
height: config.height.max(1),
depth_or_array_layers: 1,

@ -312,7 +312,6 @@ impl<'a> State<'a> {
desired_maximum_frame_latency: 2,
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[

@ -403,7 +403,6 @@ impl<'a> State<'a> {
desired_maximum_frame_latency: 2,
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[

@ -403,7 +403,6 @@ impl<'a> State<'a> {
desired_maximum_frame_latency: 2,
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[

@ -38,6 +38,7 @@ web-sys = { version = "0.3", features = [
"Element",
"Location",
]}
instant = { version = "0.1", features = [ "wasm-bindgen" ] }
[build-dependencies]
anyhow = "1.0"

@ -283,7 +283,6 @@ impl<'a> State<'a> {
desired_maximum_frame_latency: 2,
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[

@ -37,6 +37,7 @@ web-sys = { version = "0.3", features = [
"Element",
"Location",
]}
instant = { version = "0.1", features = [ "wasm-bindgen" ] }
[build-dependencies]
anyhow = "1.0"

@ -79,7 +79,7 @@ impl HdrPipeline {
let pipeline = create_render_pipeline(
device,
&pipeline_layout,
config.format,
config.format.add_srgb_suffix(),
None,
&[],
wgpu::PrimitiveTopology::TriangleList,

@ -295,11 +295,11 @@ impl<'a> State<'a> {
height: size.height,
present_mode: surface_caps.present_modes[0],
alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![],
// NEW!
view_formats: vec![surface_format.add_srgb_suffix()],
desired_maximum_frame_latency: 2,
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
@ -712,9 +712,10 @@ impl<'a> State<'a> {
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_texture()?;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let view = output.texture.create_view(&wgpu::TextureViewDescriptor {
format: Some(self.config.format.add_srgb_suffix()),
..Default::default()
});
let mut encoder = self
.device

@ -286,6 +286,9 @@ impl HdrLoader {
) -> anyhow::Result<texture::CubeTexture> {
let hdr_decoder = HdrDecoder::new(Cursor::new(data))?;
let meta = hdr_decoder.metadata();
#[cfg(not(target_arch = "wasm32"))]
let pixels = {
let mut pixels = vec![[0.0, 0.0, 0.0, 0.0]; meta.width as usize * meta.height as usize];
hdr_decoder.read_image_transform(
|pix| {
@ -294,6 +297,17 @@ impl HdrLoader {
},
&mut pixels[..],
)?;
pixels
};
#[cfg(target_arch = "wasm32")]
let pixels = hdr_decoder
.read_image_native()?
.into_iter()
.map(|pix| {
let rgb = pix.to_hdr();
[rgb.0[0], rgb.0[1], rgb.0[2], 1.0f32]
})
.collect::<Vec<_>>();
let src = texture::Texture::create_2d_texture(
device,

@ -284,7 +284,6 @@ impl<'a> State<'a> {
desired_maximum_frame_latency: 2,
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[

@ -222,7 +222,6 @@ impl<'a> State<'a> {
desired_maximum_frame_latency: 2,
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[

@ -288,7 +288,6 @@ impl<'a> State<'a> {
desired_maximum_frame_latency: 2,
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[

@ -158,7 +158,8 @@ pub fn start() {
let window = &window;
let mut last_time = instant::Instant::now();
event_loop.run(move |event, control_flow| {
event_loop
.run(move |event, control_flow| {
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
@ -264,7 +265,8 @@ pub fn start() {
}
_ => {}
}
}).unwrap();
})
.unwrap();
}
fn process_input(
@ -273,9 +275,7 @@ fn process_input(
control_flow: &EventLoopWindowTarget<()>,
) {
match (keycode, element_state) {
(KeyCode::Escape, ElementState::Pressed) => {
control_flow.exit()
}
(KeyCode::Escape, ElementState::Pressed) => control_flow.exit(),
_ => {}
}
}

@ -282,7 +282,6 @@ impl<'a> State<'a> {
view_formats: vec![],
};
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[

@ -1,4 +1,7 @@
use std::{path::PathBuf, process::{Command, ExitStatus}};
use std::{
path::PathBuf,
process::{Command, ExitStatus},
};
use anyhow::bail;
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};

@ -27,7 +27,12 @@ const SAFE_FRAC_PI_2: f32 = FRAC_PI_2 - 0.0001;
`std::time::Instant` panics on WASM, so we'll use the [instant crate](https://docs.rs/instant). You'll want to include it in your `Cargo.toml`:
```toml
[dependencies]
# ...
instant = "0.1"
[target.'cfg(target_arch = "wasm32")'.dependencies]
instant = { version = "0.1", features = [ "wasm-bindgen" ] }
```
</div>

@ -105,7 +105,7 @@ impl HdrPipeline {
let pipeline = create_render_pipeline(
device,
&pipeline_layout,
config.format,
config.format.add_srgb_suffix(),
None,
// We'll use some math to generate the vertex data in
// the shader, so we don't need any vertex buffers
@ -567,16 +567,27 @@ impl HdrLoader {
) -> anyhow::Result<texture::CubeTexture> {
let hdr_decoder = HdrDecoder::new(Cursor::new(data))?;
let meta = hdr_decoder.metadata();
#[cfg(not(target_arch="wasm32"))]
let pixels = {
let mut pixels = vec![[0.0, 0.0, 0.0, 0.0]; meta.width as usize * meta.height as usize];
hdr_decoder.read_image_transform(
|pix| {
// There's no Rgb32Float format, so we need
// an extra float
let rgb = pix.to_hdr();
[rgb.0[0], rgb.0[1], rgb.0[2], 1.0f32]
},
&mut pixels[..],
)?;
pixels
};
#[cfg(target_arch="wasm32")]
let pixels = hdr_decoder.read_image_native()?
.into_iter()
.map(|pix| {
let rgb = pix.to_hdr();
[rgb.0[0], rgb.0[1], rgb.0[2], 1.0f32]
})
.collect::<Vec<_>>();
let src = texture::Texture::create_2d_texture(
device,
@ -1201,6 +1212,48 @@ Here's the finished scene:
![with-reflections](./with-reflections.png)
## Output too dark on WebGPU?
WebGPU doesn't support using sRGB texture formats as the
output for a surface. We can get around this by making the
texture view used to render use the sRGB version of the
format. To do this we need to change the surface config
we use to allow view formats with sRGB.
```rust
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width: size.width,
height: size.height,
present_mode: surface_caps.present_modes[0],
alpha_mode: surface_caps.alpha_modes[0],
// NEW!
view_formats: vec![surface_format.add_srgb_suffix()],
desired_maximum_frame_latency: 2,
};
```
Then we need to create a view with sRGB enabled in
`State::render()`.
```rust
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor {
format: Some(self.config.format.add_srgb_suffix()),
..Default::default()
});
```
You may have noticed as well that in `HdrPipeline::new()`
we use `config.format.add_srgb_suffix()` when creating
the render pipeline. This is required as if we don't
the sRGB enabled `TextureView` won't work with the
render pipeline.
With that you should get the sRGB output as expected.
## Demo
<div class="warn">

Loading…
Cancel
Save