add transparency
This commit is contained in:
parent
c007121b41
commit
7ab2d0d800
3 changed files with 166 additions and 154 deletions
|
@ -677,6 +677,7 @@ features = [
|
|||
"Win32_Graphics_Direct3D",
|
||||
"Win32_Graphics_Direct3D11",
|
||||
"Win32_Graphics_Direct3D_Fxc",
|
||||
"Win32_Graphics_DirectComposition",
|
||||
"Win32_Graphics_DirectWrite",
|
||||
"Win32_Graphics_Dwm",
|
||||
"Win32_Graphics_Dxgi",
|
||||
|
|
|
@ -3,7 +3,8 @@ use std::{mem::ManuallyDrop, sync::Arc};
|
|||
use ::util::ResultExt;
|
||||
use anyhow::{Context, Result};
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// use windows::Win32::Graphics::DirectComposition::*;
|
||||
use windows::Win32::Graphics::DirectComposition::*;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowRect;
|
||||
use windows::{
|
||||
Win32::{
|
||||
Foundation::{HMODULE, HWND},
|
||||
|
@ -26,7 +27,6 @@ pub(crate) struct DirectXRenderer {
|
|||
context: DirectXContext,
|
||||
globals: DirectXGlobalElements,
|
||||
pipelines: DirectXRenderPipelines,
|
||||
hwnd: HWND,
|
||||
transparent: bool,
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ struct DirectXContext {
|
|||
msaa_view: ID3D11RenderTargetView,
|
||||
viewport: [D3D11_VIEWPORT; 1],
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// direct_composition: DirectComposition,
|
||||
direct_composition: DirectComposition,
|
||||
}
|
||||
|
||||
struct DirectXRenderPipelines {
|
||||
|
@ -73,11 +73,11 @@ struct DrawInstancedIndirectArgs {
|
|||
}
|
||||
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// struct DirectComposition {
|
||||
// comp_device: IDCompositionDevice,
|
||||
// comp_target: IDCompositionTarget,
|
||||
// comp_visual: IDCompositionVisual,
|
||||
// }
|
||||
struct DirectComposition {
|
||||
comp_device: IDCompositionDevice,
|
||||
comp_target: IDCompositionTarget,
|
||||
comp_visual: IDCompositionVisual,
|
||||
}
|
||||
|
||||
impl DirectXDevices {
|
||||
pub(crate) fn new() -> Result<Self> {
|
||||
|
@ -115,7 +115,6 @@ impl DirectXRenderer {
|
|||
context,
|
||||
globals,
|
||||
pipelines,
|
||||
hwnd,
|
||||
transparent,
|
||||
})
|
||||
}
|
||||
|
@ -215,11 +214,6 @@ impl DirectXRenderer {
|
|||
)
|
||||
.unwrap();
|
||||
}
|
||||
// let backbuffer = set_render_target_view(
|
||||
// &self.context.swap_chain,
|
||||
// &self.devices.device,
|
||||
// &self.devices.device_context,
|
||||
// )?;
|
||||
let (render_target, render_target_view) =
|
||||
create_render_target_and_its_view(&self.context.swap_chain, &self.devices.device)
|
||||
.unwrap();
|
||||
|
@ -248,31 +242,6 @@ impl DirectXRenderer {
|
|||
}
|
||||
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// pub(crate) fn update_transparency(
|
||||
// &mut self,
|
||||
// background_appearance: WindowBackgroundAppearance,
|
||||
// ) -> Result<()> {
|
||||
// // We only support setting `Transparent` and `Opaque` for now.
|
||||
// match background_appearance {
|
||||
// WindowBackgroundAppearance::Opaque => {
|
||||
// if self.transparent {
|
||||
// return Err(anyhow::anyhow!(
|
||||
// "Set opaque backgroud from transparent background, a restart is required. Or, you can open a new window."
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
// WindowBackgroundAppearance::Transparent | WindowBackgroundAppearance::Blurred => {
|
||||
// if !self.transparent {
|
||||
// return Err(anyhow::anyhow!(
|
||||
// "Set transparent backgroud from opaque background, a restart is required. Or, you can open a new window."
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "enable-renderdoc")]
|
||||
pub(crate) fn update_transparency(
|
||||
&mut self,
|
||||
background_appearance: WindowBackgroundAppearance,
|
||||
|
@ -281,33 +250,84 @@ impl DirectXRenderer {
|
|||
if self.transparent == transparent {
|
||||
return Ok(());
|
||||
}
|
||||
self.transparent = transparent;
|
||||
// unsafe {
|
||||
// // recreate the swapchain
|
||||
// self.transparent = transparent;
|
||||
// let (width, height) = unsafe {
|
||||
// self.devices.device_context.OMSetRenderTargets(None, None);
|
||||
// drop(self.context.back_buffer[0].take().unwrap());
|
||||
// ManuallyDrop::drop(&mut self.context.render_target);
|
||||
// drop(self.context.render_target_view[0].take().unwrap());
|
||||
// let desc = self.context.swap_chain.GetDesc1().unwrap();
|
||||
// ManuallyDrop::drop(&mut self.context.swap_chain);
|
||||
// self.context.swap_chain = create_swap_chain_default(
|
||||
// &self.devices.dxgi_factory,
|
||||
// &self.devices.device,
|
||||
// self.hwnd,
|
||||
// transparent,
|
||||
// )?;
|
||||
// self.context.back_buffer = [Some(set_render_target_view(
|
||||
// &self.context.swap_chain,
|
||||
// &self.devices.device,
|
||||
// &self.devices.device_context,
|
||||
// )?)];
|
||||
// self.context.viewport = set_viewport(
|
||||
// &self.devices.device_context,
|
||||
// self.context.viewport[0].Width,
|
||||
// self.context.viewport[0].Height,
|
||||
// );
|
||||
// set_rasterizer_state(&self.devices.device, &self.devices.device_context)?;
|
||||
// (desc.Width, desc.Height)
|
||||
// };
|
||||
// self.context.swap_chain = create_swap_chain(
|
||||
// &self.devices.dxgi_factory,
|
||||
// &self.devices.device,
|
||||
// transparent,
|
||||
// width,
|
||||
// height,
|
||||
// )
|
||||
// .unwrap();
|
||||
// self.context
|
||||
// .direct_composition
|
||||
// .set_swap_chain(&self.context.swap_chain)
|
||||
// .context("Failed to set swap chain for DirectComposition")?;
|
||||
// let (render_target, render_target_view) =
|
||||
// create_render_target_and_its_view(&self.context.swap_chain, &self.devices.device)
|
||||
// .unwrap();
|
||||
// self.context.render_target = render_target;
|
||||
// self.context.render_target_view = render_target_view;
|
||||
// unsafe {
|
||||
// self.devices
|
||||
// .device_context
|
||||
// .OMSetRenderTargets(Some(&self.context.render_target_view), None);
|
||||
// }
|
||||
|
||||
// let (msaa_target, msaa_view) =
|
||||
// create_msaa_target_and_its_view(&self.devices.device, width, height)?;
|
||||
// self.context.msaa_target = msaa_target;
|
||||
// self.context.msaa_view = msaa_view;
|
||||
|
||||
// self.context.viewport = set_viewport(&self.devices.device_context, width as _, height as _);
|
||||
// set_rasterizer_state(&self.devices.device, &self.devices.device_context)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// #[cfg(feature = "enable-renderdoc")]
|
||||
// pub(crate) fn update_transparency(
|
||||
// &mut self,
|
||||
// background_appearance: WindowBackgroundAppearance,
|
||||
// ) -> Result<()> {
|
||||
// let transparent = background_appearance != WindowBackgroundAppearance::Opaque;
|
||||
// if self.transparent == transparent {
|
||||
// return Ok(());
|
||||
// }
|
||||
// self.transparent = transparent;
|
||||
// unsafe {
|
||||
// // recreate the swapchain
|
||||
// self.devices.device_context.OMSetRenderTargets(None, None);
|
||||
// drop(self.context.back_buffer[0].take().unwrap());
|
||||
// ManuallyDrop::drop(&mut self.context.swap_chain);
|
||||
// self.context.swap_chain = create_swap_chain_default(
|
||||
// &self.devices.dxgi_factory,
|
||||
// &self.devices.device,
|
||||
// self.hwnd,
|
||||
// transparent,
|
||||
// )?;
|
||||
// self.context.back_buffer = [Some(set_render_target_view(
|
||||
// &self.context.swap_chain,
|
||||
// &self.devices.device,
|
||||
// &self.devices.device_context,
|
||||
// )?)];
|
||||
// self.context.viewport = set_viewport(
|
||||
// &self.devices.device_context,
|
||||
// self.context.viewport[0].Width,
|
||||
// self.context.viewport[0].Height,
|
||||
// );
|
||||
// set_rasterizer_state(&self.devices.device, &self.devices.device_context)?;
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
fn draw_shadows(&mut self, shadows: &[Shadow]) -> Result<()> {
|
||||
if shadows.is_empty() {
|
||||
return Ok(());
|
||||
|
@ -461,24 +481,35 @@ impl DirectXRenderer {
|
|||
|
||||
impl DirectXContext {
|
||||
pub fn new(devices: &DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> {
|
||||
let (width, height) = unsafe {
|
||||
let mut rect = std::mem::zeroed();
|
||||
GetWindowRect(hwnd, &mut rect)?;
|
||||
(rect.right - rect.left, rect.bottom - rect.top)
|
||||
};
|
||||
assert!(
|
||||
width > 0 && height > 0,
|
||||
"Window size must be greater than zero"
|
||||
);
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, transparent)?;
|
||||
let swap_chain = create_swap_chain(
|
||||
&devices.dxgi_factory,
|
||||
&devices.device,
|
||||
transparent,
|
||||
width as u32,
|
||||
height as u32,
|
||||
)?;
|
||||
// #[cfg(feature = "enable-renderdoc")]
|
||||
let swap_chain =
|
||||
create_swap_chain_default(&devices.dxgi_factory, &devices.device, hwnd, transparent)?;
|
||||
// let swap_chain =
|
||||
// create_swap_chain_default(&devices.dxgi_factory, &devices.device, hwnd, transparent)?;
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?;
|
||||
let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?;
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// direct_composition.set_swap_chain(&swap_chain)?;
|
||||
direct_composition.set_swap_chain(&swap_chain)?;
|
||||
let (render_target, render_target_view) =
|
||||
create_render_target_and_its_view(&swap_chain, &devices.device)?;
|
||||
// let back_buffer = [Some(set_render_target_view(
|
||||
// &swap_chain,
|
||||
// &devices.device,
|
||||
// &devices.device_context,
|
||||
// )?)];
|
||||
let (msaa_target, msaa_view) = create_msaa_target_and_its_view(&devices.device, 1, 1)?;
|
||||
let viewport = set_viewport(&devices.device_context, 1.0, 1.0);
|
||||
let (msaa_target, msaa_view) =
|
||||
create_msaa_target_and_its_view(&devices.device, width as u32, height as u32)?;
|
||||
let viewport = set_viewport(&devices.device_context, width as f32, height as f32);
|
||||
unsafe {
|
||||
devices
|
||||
.device_context
|
||||
|
@ -494,7 +525,7 @@ impl DirectXContext {
|
|||
msaa_view,
|
||||
viewport,
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// direct_composition,
|
||||
direct_composition,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -545,28 +576,28 @@ impl DirectXRenderPipelines {
|
|||
}
|
||||
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// impl DirectComposition {
|
||||
// pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result<Self> {
|
||||
// let comp_device = get_comp_device(&dxgi_device)?;
|
||||
// let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?;
|
||||
// let comp_visual = unsafe { comp_device.CreateVisual() }?;
|
||||
impl DirectComposition {
|
||||
pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result<Self> {
|
||||
let comp_device = get_comp_device(&dxgi_device)?;
|
||||
let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?;
|
||||
let comp_visual = unsafe { comp_device.CreateVisual() }?;
|
||||
|
||||
// Ok(Self {
|
||||
// comp_device,
|
||||
// comp_target,
|
||||
// comp_visual,
|
||||
// })
|
||||
// }
|
||||
Ok(Self {
|
||||
comp_device,
|
||||
comp_target,
|
||||
comp_visual,
|
||||
})
|
||||
}
|
||||
|
||||
// pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> {
|
||||
// unsafe {
|
||||
// self.comp_visual.SetContent(swap_chain)?;
|
||||
// self.comp_target.SetRoot(&self.comp_visual)?;
|
||||
// self.comp_device.Commit()?;
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> {
|
||||
unsafe {
|
||||
self.comp_visual.SetContent(swap_chain)?;
|
||||
self.comp_target.SetRoot(&self.comp_visual)?;
|
||||
self.comp_device.Commit()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl DirectXGlobalElements {
|
||||
pub fn new(device: &ID3D11Device) -> Result<Self> {
|
||||
|
@ -1030,39 +1061,45 @@ fn get_device(
|
|||
}
|
||||
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result<IDCompositionDevice> {
|
||||
// Ok(unsafe { DCompositionCreateDevice(dxgi_device)? })
|
||||
// }
|
||||
fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result<IDCompositionDevice> {
|
||||
Ok(unsafe { DCompositionCreateDevice(dxgi_device)? })
|
||||
}
|
||||
|
||||
// fn create_swap_chain(
|
||||
// dxgi_factory: &IDXGIFactory6,
|
||||
// device: &ID3D11Device,
|
||||
// transparent: bool,
|
||||
// ) -> Result<IDXGISwapChain1> {
|
||||
// let alpha_mode = if transparent {
|
||||
// DXGI_ALPHA_MODE_PREMULTIPLIED
|
||||
// } else {
|
||||
// DXGI_ALPHA_MODE_IGNORE
|
||||
// };
|
||||
// let desc = DXGI_SWAP_CHAIN_DESC1 {
|
||||
// Width: 1,
|
||||
// Height: 1,
|
||||
// Format: DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
// Stereo: false.into(),
|
||||
// SampleDesc: DXGI_SAMPLE_DESC {
|
||||
// Count: 1,
|
||||
// Quality: 0,
|
||||
// },
|
||||
// BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
// BufferCount: BUFFER_COUNT as u32,
|
||||
// // Composition SwapChains only support the DXGI_SCALING_STRETCH Scaling.
|
||||
// Scaling: DXGI_SCALING_STRETCH,
|
||||
// SwapEffect: DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
|
||||
// AlphaMode: alpha_mode,
|
||||
// Flags: 0,
|
||||
// };
|
||||
// Ok(unsafe { dxgi_factory.CreateSwapChainForComposition(device, &desc, None)? })
|
||||
// }
|
||||
fn create_swap_chain(
|
||||
dxgi_factory: &IDXGIFactory6,
|
||||
device: &ID3D11Device,
|
||||
transparent: bool,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<ManuallyDrop<IDXGISwapChain1>> {
|
||||
println!("Creating swap chain for DirectComposition: {}", transparent);
|
||||
let transparent = true;
|
||||
let alpha_mode = if transparent {
|
||||
DXGI_ALPHA_MODE_PREMULTIPLIED
|
||||
} else {
|
||||
DXGI_ALPHA_MODE_IGNORE
|
||||
};
|
||||
let desc = DXGI_SWAP_CHAIN_DESC1 {
|
||||
Width: width,
|
||||
Height: height,
|
||||
Format: RENDER_TARGET_FORMAT,
|
||||
Stereo: false.into(),
|
||||
SampleDesc: DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
BufferCount: BUFFER_COUNT as u32,
|
||||
// Composition SwapChains only support the DXGI_SCALING_STRETCH Scaling.
|
||||
Scaling: DXGI_SCALING_STRETCH,
|
||||
SwapEffect: DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
|
||||
AlphaMode: alpha_mode,
|
||||
Flags: 0,
|
||||
};
|
||||
Ok(ManuallyDrop::new(unsafe {
|
||||
dxgi_factory.CreateSwapChainForComposition(device, &desc, None)?
|
||||
}))
|
||||
}
|
||||
|
||||
// #[cfg(feature = "enable-renderdoc")]
|
||||
fn create_swap_chain_default(
|
||||
|
@ -1289,33 +1326,6 @@ fn create_indirect_draw_buffer(device: &ID3D11Device, buffer_size: usize) -> Res
|
|||
Ok(buffer.unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pre_draw(
|
||||
device_context: &ID3D11DeviceContext,
|
||||
global_params_buffer: &[Option<ID3D11Buffer>; 1],
|
||||
view_port: &[D3D11_VIEWPORT; 1],
|
||||
render_target_view: &[Option<ID3D11RenderTargetView>; 1],
|
||||
clear_color: [f32; 4],
|
||||
blend_state: &ID3D11BlendState,
|
||||
) -> Result<()> {
|
||||
let global_params = global_params_buffer[0].as_ref().unwrap();
|
||||
update_buffer(
|
||||
device_context,
|
||||
global_params,
|
||||
&[GlobalParams {
|
||||
viewport_size: [view_port[0].Width, view_port[0].Height],
|
||||
..Default::default()
|
||||
}],
|
||||
)?;
|
||||
unsafe {
|
||||
device_context.RSSetViewports(Some(view_port));
|
||||
device_context.OMSetRenderTargets(Some(render_target_view), None);
|
||||
device_context.ClearRenderTargetView(render_target_view[0].as_ref().unwrap(), &clear_color);
|
||||
device_context.OMSetBlendState(blend_state, None, 0xFFFFFFFF);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update_buffer<T>(
|
||||
device_context: &ID3D11DeviceContext,
|
||||
|
|
|
@ -384,7 +384,8 @@ impl WindowsWindow {
|
|||
(WS_EX_TOOLWINDOW | WS_EX_LAYERED, WINDOW_STYLE(0x0))
|
||||
} else {
|
||||
(
|
||||
WS_EX_APPWINDOW | WS_EX_LAYERED,
|
||||
WS_EX_APPWINDOW | WS_EX_NOREDIRECTIONBITMAP,
|
||||
// WS_EX_APPWINDOW | WS_EX_LAYERED,
|
||||
WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
|
||||
)
|
||||
};
|
||||
|
@ -461,7 +462,7 @@ impl WindowsWindow {
|
|||
// window is going to be composited with per-pixel alpha, but the render
|
||||
// pipeline is responsible for effectively calling UpdateLayeredWindow
|
||||
// at the appropriate time.
|
||||
unsafe { SetLayeredWindowAttributes(hwnd, COLORREF(0), 255, LWA_ALPHA)? };
|
||||
// unsafe { SetLayeredWindowAttributes(hwnd, COLORREF(0), 255, LWA_ALPHA)? };
|
||||
|
||||
Ok(Self(state_ptr))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue