更新:URP支持透明,版本2023.1.11(URP15),时间:2023.10.20*
Unity采用内置渲染管线,版本2020.3.0
参考网上资料:链接
Unity新版需要关闭选项:Edit——ProjectSettings——Player——ResolutionandPresentation——UseDXGIFlipModelSwapchainforD3D11
这个参考上面链接
没有按照上面链接的方式对颜色进行比较,部分场景会有非常多的锯齿,而是直接清空背景颜色
重要的事说三遍:
说下思路:先清除颜色,再渲染需要的!先清除颜色,再渲染需要的!先清除颜色,再渲染需要的!
第一种:不采用UI
在OnRenderImage方法上添加属性ImageEffectOpaque,这样会渲染完不透明物体后立刻执行,所以在自定义UnlitShader的片元阶段直接返回float4(0.0,0.0,0.0,0.0),即清除所有颜色,把我们需要显示的材质改为不透明顺序之后材质,如透明材质,这样就可以了。
第二种:采用UI
在自定义的Shader的片元阶段直接返回float4(0.0,0.0,0.0,0.0),即清除所有颜色,用UI显示我们的图片或视频就可以了,因为UI的渲染靠后。
透明后,窗口置顶,鼠标穿透等功能可参考网上资料
URP实现:版本2023.1.11(URP15)
总体思路和内置管线一样,但是需要URP14以后的版本才行(大牛可以自己添加功能,请忽略)
URP14新增了Full Screen Pass Renderer Feature功能,和内置管线的OnRenderImage类似的功能(URP版本不能使用OnRenderImage)
1.新建一个ShaderGraph,再由此ShaderGraph创建一个材质:
1.1.设置里Material类型改为Fullscreen
1.2.片元着色器透明度设置为0,颜色为黑色
测试后也可以设置其他颜色(导致整体带某种颜色,也是透明的)
透明的也可以不是0,大于0小于1背景半透明效果
2.添加Full Screen Pass Renderer Feature功能:
2.1.项目使用哪个渲染器对哪个渲染器设置,可以都设置上了,不同渲染器对应不同质量的设置,在ProjectSetting下的Quality
2.2.如下图添加Full Screen Pass Renderer Feature,把上一步创建的ShaderGraph新建一个材质放进来即可
2.3.把InjectionPoint改为Before Rendering Transparents(在渲染透明对象前)
3.把相机的后处理和HDR功能关闭,也可以在URP渲染管线设置里关闭(最彻底)
如果没有关闭渲染管线的设置,一个相机关闭的设置,一个相机没有关闭设置,则只用关闭设置的相机渲染部分是透明的,也可能是你想要的效果
几个设置关闭的地方:
4.最后把这个脚本挂在任意物体上,上面链接里的脚本,去掉了OnRenderImage
最重要的代码是:DwmExtendFrameIntoClientArea(_hwnd, ref margins);
没有它无法透明
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class TransparentWindow : MonoBehaviour
{
private struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("Dwmapi.dll")]
private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int cx, int cy,
int uFlags);
[DllImport("user32.dll")]
static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
const int GWL_STYLE = -16;
const int GWL_EXSTYLE = -20;
const uint WS_POPUP = 0x80000000;
const uint WS_VISIBLE = 0x10000000;
const uint WS_EX_TOPMOST = 0x00000008;
const uint WS_EX_LAYERED = 0x00080000;
const uint WS_EX_TRANSPARENT = 0x00000020;
const int SWP_FRAMECHANGED = 0x0020;
const int SWP_SHOWWINDOW = 0x0040;
const int LWA_ALPHA = 2;
private IntPtr HWND_TOPMOST = new IntPtr(-1);
private IntPtr _hwnd;
void Start()
{
#if !UNITY_EDITOR
MARGINS margins = new MARGINS() { cxLeftWidth = -1 };
_hwnd = GetActiveWindow();
int fWidth = Screen.width;
int fHeight = Screen.height;
SetWindowLong(_hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
//SetWindowLong(_hwnd, GWL_EXSTYLE, WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT);//若想鼠标穿透,则将这个注释恢复即可
DwmExtendFrameIntoClientArea(_hwnd, ref margins);
SetWindowPos(_hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
ShowWindowAsync(_hwnd, 3); //Forces window to show in case of unresponsive app // SW_SHOWMAXIMIZED(3)
#endif
}
}
5.把想要显示的物体的材质设置为透明,比如下图的方块和圆球,UI可以直接添加,因为UI的渲染顺序更靠后
效果如下:颜色设置的是红色,设置为黑色就完全透明,左边相机禁用了后处理和HDR(左边透明),右边没有禁用
Github上有一个透明软件背景的项目:添加链接描述
更新:又发现一种方式,官方给的例子,代码的方式:官方链接
这种是自己定义全屏渲染功能,上一种是官方提供了直接用,原理是一样的。在shader里把返回颜色和透明度改成需要的即可
不同的地方是要修改插入点,改为:BeforeRenderingTransparents
public ColorBlitPass(Material material)
{
m_Material = material;
renderPassEvent = RenderPassEvent.BeforeRenderingTransparents;
}