Desktop add viewport texture (#2953)
* Allow rendering viewport texture beneath ui texture * Add viewport scale * Update desktop/src/render/fullscreen_texture.wgsl --------- Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
parent
83d39fb320
commit
6119dea58c
|
|
@ -1834,6 +1834,7 @@ dependencies = [
|
|||
name = "graphite-desktop"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"cef",
|
||||
"dirs",
|
||||
"futures",
|
||||
|
|
|
|||
|
|
@ -28,4 +28,5 @@ cef = { workspace = true }
|
|||
include_dir = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
dirs = {workspace = true}
|
||||
dirs = { workspace = true }
|
||||
bytemuck = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
|
|||
match event {
|
||||
CustomEvent::UiUpdate(texture) => {
|
||||
if let Some(graphics_state) = self.graphics_state.as_mut() {
|
||||
graphics_state.bind_texture(&texture);
|
||||
graphics_state.bind_ui_texture(&texture);
|
||||
graphics_state.resize(texture.width(), texture.height());
|
||||
}
|
||||
if let Some(window) = &self.window {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use thiserror::Error;
|
||||
use winit::window::Window;
|
||||
|
||||
|
|
@ -79,13 +80,15 @@ impl WgpuContext {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let required_limits = adapter.limits();
|
||||
|
||||
let (device, queue) = adapter
|
||||
.request_device(&wgpu::DeviceDescriptor {
|
||||
required_features: wgpu::Features::empty(),
|
||||
required_limits: wgpu::Limits::default(),
|
||||
label: None,
|
||||
required_features: wgpu::Features::PUSH_CONSTANTS,
|
||||
required_limits,
|
||||
memory_hints: Default::default(),
|
||||
..Default::default()
|
||||
trace: wgpu::Trace::Off,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
@ -99,10 +102,13 @@ pub(crate) struct GraphicsState {
|
|||
surface: wgpu::Surface<'static>,
|
||||
context: WgpuContext,
|
||||
config: wgpu::SurfaceConfiguration,
|
||||
texture: Option<wgpu::Texture>,
|
||||
bind_group: Option<wgpu::BindGroup>,
|
||||
render_pipeline: wgpu::RenderPipeline,
|
||||
sampler: wgpu::Sampler,
|
||||
viewport_scale: [f32; 2],
|
||||
viewport_offset: [f32; 2],
|
||||
viewport_texture: Option<wgpu::Texture>,
|
||||
ui_texture: Option<wgpu::Texture>,
|
||||
bind_group: Option<wgpu::BindGroup>,
|
||||
}
|
||||
|
||||
impl GraphicsState {
|
||||
|
|
@ -156,6 +162,16 @@ impl GraphicsState {
|
|||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
multisampled: false,
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
|
|
@ -166,7 +182,10 @@ impl GraphicsState {
|
|||
let render_pipeline_layout = context.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Render Pipeline Layout"),
|
||||
bind_group_layouts: &[&texture_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
push_constant_ranges: &[wgpu::PushConstantRange {
|
||||
stages: wgpu::ShaderStages::FRAGMENT,
|
||||
range: 0..size_of::<Constants>() as u32,
|
||||
}],
|
||||
});
|
||||
|
||||
let render_pipeline = context.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
|
|
@ -211,10 +230,13 @@ impl GraphicsState {
|
|||
surface,
|
||||
context,
|
||||
config,
|
||||
texture: None,
|
||||
bind_group: None,
|
||||
render_pipeline,
|
||||
sampler,
|
||||
viewport_scale: [1.0, 1.0],
|
||||
viewport_offset: [0.0, 0.0],
|
||||
viewport_texture: None,
|
||||
ui_texture: None,
|
||||
bind_group: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -226,25 +248,47 @@ impl GraphicsState {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn bind_texture(&mut self, texture: &wgpu::Texture) {
|
||||
let bind_group = self.create_bindgroup(texture);
|
||||
self.texture = Some(texture.clone());
|
||||
pub(crate) fn bind_ui_texture(&mut self, texture: &wgpu::Texture) {
|
||||
let bind_group = self.create_bindgroup(texture, &self.viewport_texture.clone().unwrap_or(texture.clone()));
|
||||
|
||||
self.ui_texture = Some(texture.clone());
|
||||
|
||||
self.bind_group = Some(bind_group);
|
||||
}
|
||||
|
||||
fn create_bindgroup(&self, texture: &wgpu::Texture) -> wgpu::BindGroup {
|
||||
let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
pub(crate) fn bind_viewport_texture(&mut self, texture: &wgpu::Texture) {
|
||||
let bind_group = self.create_bindgroup(&self.ui_texture.clone().unwrap_or(texture.clone()), texture);
|
||||
|
||||
self.viewport_texture = Some(texture.clone());
|
||||
|
||||
self.bind_group = Some(bind_group);
|
||||
}
|
||||
|
||||
pub(crate) fn set_viewport_scale(&mut self, scale: [f32; 2]) {
|
||||
self.viewport_scale = scale;
|
||||
}
|
||||
|
||||
pub(crate) fn set_viewport_offset(&mut self, offset: [f32; 2]) {
|
||||
self.viewport_offset = offset;
|
||||
}
|
||||
|
||||
fn create_bindgroup(&self, ui_texture: &wgpu::Texture, viewport_texture: &wgpu::Texture) -> wgpu::BindGroup {
|
||||
let ui_texture_view = ui_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let viewport_texture_view = viewport_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
self.context.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &self.render_pipeline.get_bind_group_layout(0),
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(&texture_view),
|
||||
resource: wgpu::BindingResource::TextureView(&ui_texture_view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&viewport_texture_view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::Sampler(&self.sampler),
|
||||
},
|
||||
],
|
||||
|
|
@ -275,6 +319,14 @@ impl GraphicsState {
|
|||
});
|
||||
|
||||
render_pass.set_pipeline(&self.render_pipeline);
|
||||
render_pass.set_push_constants(
|
||||
wgpu::ShaderStages::FRAGMENT,
|
||||
0,
|
||||
bytemuck::bytes_of(&Constants {
|
||||
viewport_scale: self.viewport_scale,
|
||||
viewport_offset: self.viewport_offset,
|
||||
}),
|
||||
);
|
||||
if let Some(bind_group) = &self.bind_group {
|
||||
render_pass.set_bind_group(0, bind_group, &[]);
|
||||
render_pass.draw(0..6, 0..1); // Draw 3 vertices for fullscreen triangle
|
||||
|
|
@ -288,3 +340,10 @@ impl GraphicsState {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||
struct Constants {
|
||||
viewport_scale: [f32; 2],
|
||||
viewport_offset: [f32; 2],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,27 @@ fn vs_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
|
|||
return out;
|
||||
}
|
||||
|
||||
struct Constants {
|
||||
viewport_scale: vec2<f32>,
|
||||
viewport_offset: vec2<f32>,
|
||||
};
|
||||
|
||||
var<push_constant> constants: Constants;
|
||||
|
||||
@group(0) @binding(0)
|
||||
var t_diffuse: texture_2d<f32>;
|
||||
var t_ui: texture_2d<f32>;
|
||||
@group(0) @binding(1)
|
||||
var t_viewport: texture_2d<f32>;
|
||||
@group(0) @binding(2)
|
||||
var s_diffuse: sampler;
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
return textureSample(t_diffuse, s_diffuse, in.tex_coords);
|
||||
let ui_color: vec4<f32> = textureSample(t_ui, s_diffuse, in.tex_coords);
|
||||
if (ui_color.a == 1.0) {
|
||||
return ui_color;
|
||||
}
|
||||
let viewport_tex_coords = (in.tex_coords - constants.viewport_offset) * constants.viewport_scale;
|
||||
let viewport_color: vec4<f32> = textureSample(t_viewport, s_diffuse, viewport_tex_coords);
|
||||
return ui_color * ui_color.a + viewport_color * (1.0 - ui_color.a);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue