Skip to content

Commit

Permalink
add mipmaps and fix color preview
Browse files Browse the repository at this point in the history
  • Loading branch information
Kl4rry committed Jan 27, 2024
1 parent dd2ce05 commit 361132b
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,8 @@ impl App {
.id(egui::Id::new("resize window"))
.collapsible(false)
.resizable(false)
.pivot(egui::Align2::CENTER_CENTER)
.default_pos(self.size / 2.0)
.open(&mut open)
.show(ctx, |ui| {
egui::Grid::new("resize grid").show(ui, |ui| {
Expand Down Expand Up @@ -946,6 +948,8 @@ impl App {
.id(egui::Id::new("crop window"))
.collapsible(false)
.resizable(false)
.pivot(egui::Align2::CENTER_CENTER)
.default_pos(self.size / 2.0)
.show(ctx, |ui| {
egui::Grid::new("crop grid").show(ui, |ui| {
ui.with_layout(egui::Layout::right_to_left(egui::Align::RIGHT), |ui| {
Expand Down
2 changes: 2 additions & 0 deletions src/app/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ impl App {
.id(egui::Id::new("color window"))
.collapsible(false)
.resizable(false)
.pivot(egui::Align2::CENTER_CENTER)
.default_pos(self.size / 2.0)
.open(&mut open)
.show(ctx, |ui| {
egui::Grid::new("color grid").show(ui, |ui| {
Expand Down
2 changes: 2 additions & 0 deletions src/app/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ impl App {
.id(egui::Id::new("help window"))
.collapsible(false)
.resizable(false)
.pivot(egui::Align2::CENTER_CENTER)
.default_pos(self.size / 2.0)
.open(&mut open)
.show(ctx, |ui| {
egui::Grid::new("help grid")
Expand Down
2 changes: 1 addition & 1 deletion src/app/image_view/image_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ impl Vertex {
pub struct Uniform {
pub matrix: Matrix4<f32>,
pub size: Vec2<f32>,
pub padding: Vec2<f32>, // Padding because glsl is adding dumb padding
pub hue: f32,
pub contrast: f32,
pub brightness: f32,
pub saturation: f32,
pub grayscale: u32,
pub invert: u32,
pub padding: Vec2<f32>, // Padding because glsl is adding dumb padding
}

impl Default for Uniform {
Expand Down
25 changes: 21 additions & 4 deletions src/app/image_view/mosaic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ impl Mosaic {
pub fn from_images(wgpu: &WgpuState, images: Arc<ImageData>) -> Vec<Self> {
let limit = Limits::default().max_texture_dimension_2d;

let mut encoder = wgpu
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});

let mut output = Vec::new();
for image in &images.frames {
let mut tiles = Vec::new();
Expand All @@ -28,7 +34,6 @@ impl Mosaic {
let tile_width = (image.width() / limit) + 1;
let tile_height = (image.height() / limit) + 1;

// TODO: make parallel
for x in 0..tile_width {
for y in 0..tile_height {
let start_x = x * limit;
Expand All @@ -50,11 +55,23 @@ impl Mosaic {

// Fast path for small images
let texture = if tile_height == 1 && tile_width == 1 {
texture::Texture::from_image(&wgpu.device, &wgpu.queue, image, None)
texture::Texture::from_image(
&mut encoder,
&wgpu.device,
&wgpu.queue,
image,
None,
)
} else {
let sub_image =
get_tile(image, start_x, start_y, end_x - start_x, end_y - start_y);
texture::Texture::from_image(&wgpu.device, &wgpu.queue, &sub_image, None)
texture::Texture::from_image(
&mut encoder,
&wgpu.device,
&wgpu.queue,
&sub_image,
None,
)
};

tiles.push(Tile { vertices, texture });
Expand All @@ -72,7 +89,7 @@ impl Mosaic {

output.push(Mosaic { tiles, indices })
}
wgpu.queue.submit(iter::empty());
wgpu.queue.submit(iter::once(encoder.finish()));
output
}
}
Expand Down
110 changes: 108 additions & 2 deletions src/app/image_view/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::{borrow::Cow, mem};

use image::GenericImageView;

const MIP_LEVEL_COUNT: u32 = 10;

pub struct Texture {
pub texture: wgpu::Texture,
pub view: wgpu::TextureView,
Expand All @@ -20,6 +22,7 @@ fn to_u8<T: Copy + bytemuck::Pod>(input: Vec<T>) -> Vec<u8> {

impl Texture {
pub fn from_image(
command_encoder: &mut wgpu::CommandEncoder,
device: &wgpu::Device,
queue: &wgpu::Queue,
img: &image::DynamicImage,
Expand Down Expand Up @@ -50,11 +53,13 @@ impl Texture {
let texture = device.create_texture(&wgpu::TextureDescriptor {
label,
size,
mip_level_count: 1,
mip_level_count: MIP_LEVEL_COUNT,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING
| wgpu::TextureUsages::COPY_DST
| wgpu::TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
});

Expand Down Expand Up @@ -103,6 +108,8 @@ impl Texture {
label: Some("Diffuse Bind Group"),
});

generate_mipmaps(command_encoder, device, &texture, format, MIP_LEVEL_COUNT);

Self {
texture,
view,
Expand Down Expand Up @@ -136,3 +143,102 @@ impl Texture {
})
}
}

fn generate_mipmaps(
encoder: &mut wgpu::CommandEncoder,
device: &wgpu::Device,
texture: &wgpu::Texture,
texture_format: wgpu::TextureFormat,
mip_count: u32,
) {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("../../shader/blit.wgsl"))),
});

let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("blit"),
layout: None,
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[Some(texture_format.into())],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
..Default::default()
},
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
multiview: None,
});

let bind_group_layout = pipeline.get_bind_group_layout(0);

let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("mip"),
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::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
..Default::default()
});

let views = (0..mip_count)
.map(|mip| {
texture.create_view(&wgpu::TextureViewDescriptor {
label: Some("mip"),
format: None,
dimension: None,
aspect: wgpu::TextureAspect::All,
base_mip_level: mip,
mip_level_count: Some(1),
base_array_layer: 0,
array_layer_count: None,
})
})
.collect::<Vec<_>>();

for target_mip in 1..mip_count as usize {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&views[target_mip - 1]),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(&sampler),
},
],
label: None,
});

let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &views[target_mip],
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::WHITE),
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});

rpass.set_pipeline(&pipeline);
rpass.set_bind_group(0, &bind_group, &[]);
rpass.draw(0..3, 0..1);
}
}
2 changes: 2 additions & 0 deletions src/app/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ impl App {
.id(egui::Id::new("metadata window"))
.collapsible(false)
.resizable(true)
.pivot(egui::Align2::CENTER_CENTER)
.default_pos(self.size / 2.0)
.open(&mut open)
.show(ctx, |ui| {
ScrollArea::vertical().show(ui, |ui| {
Expand Down
2 changes: 1 addition & 1 deletion src/app/popup_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ impl PopupManager {
.id(egui::Id::new(key))
.collapsible(false)
.resizable(false)
.open(&mut open)
.pivot(egui::Align2::CENTER_CENTER)
.default_pos(size / 2.0)
.open(&mut open)
.show(ctx, |ui| done = (popup.closure)(ui));
if !open || done {
self.popups.remove(&key);
Expand Down
2 changes: 2 additions & 0 deletions src/app/preferences.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ impl App {
.id(egui::Id::new("preferences window"))
.collapsible(false)
.resizable(false)
.pivot(egui::Align2::CENTER_CENTER)
.default_pos(self.size / 2.0)
.open(&mut open)
.show(ctx, |ui| {
egui::Grid::new("preferences grid").show(ui, |ui| {
Expand Down
52 changes: 52 additions & 0 deletions src/shader/blit.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
struct VertexOutput {
@builtin(position) position: vec4<f32>,
@location(0) tex_coords: vec2<f32>,
};

// meant to be called with 3 vertex indices: 0, 1, 2
// draws one large triangle over the clip space like this:
// (the asterisks represent the clip space bounds)
//-1,1 1,1
// ---------------------------------
// | * .
// | * .
// | * .
// | * .
// | * .
// | * .
// |***************
// | . 1,-1
// | .
// | .
// | .
// | .
// |.
@vertex
fn vs_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
var result: VertexOutput;
let x = i32(vertex_index) / 2;
let y = i32(vertex_index) & 1;
let tc = vec2<f32>(
f32(x) * 2.0,
f32(y) * 2.0
);
result.position = vec4<f32>(
tc.x * 2.0 - 1.0,
1.0 - tc.y * 2.0,
0.0, 1.0
);
result.tex_coords = tc;
return result;
}

@group(0)
@binding(0)
var r_color: texture_2d<f32>;
@group(0)
@binding(1)
var r_sampler: sampler;

@fragment
fn fs_main(vertex: VertexOutput) -> @location(0) vec4<f32> {
return textureSample(r_color, r_sampler, vertex.tex_coords);
}
1 change: 0 additions & 1 deletion src/shader/image.frag
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ vec3 getCheckColor() {
}

void main() {
vec2 size = input.size;
float hue = input.hue;
float contrast = input.contrast;
float brightness = input.brightness;
Expand Down

0 comments on commit 361132b

Please sign in to comment.