URP

您所在的位置:网站首页 vr体积雾怎么设置 URP

URP

2024-04-02 01:40| 来源: 网络整理| 查看: 265

目前是后处理最后一篇,还有一篇是后处理整理,后面会上传到github。

内容篇多前看目录

效果

目的

怎么做体积光?都使用到了什么技术?

Ray Marching 是什么?还可以实现什么效果。

怎么使用后处理实现体积光,都需要注意什么。

使用版本Unity 2021.3.15

介绍

体积光(Volumetric Lights )是模拟现实中散射效果,  散射的光线进入人眼,让这些介质看起来像拢住了光线一样,也就是所谓的体积光。

因为体积光是我们生活中能看到的现象,我们可以看到其实不是光有体积, 我们也看不到光的体积, 光穿过物体,产生的形状。

当空气中粒子的密度足够高时,

部分遮挡光源的物体将以光束或光线的形式在这些粒子上投射阴影。

我们这里是使用后处理的方式来实现效果。

后处理实现方法

制作遮罩,使用深度制作一个遮罩,光是白色,物体渲染成黑色。

使用Ray Marching 计算光线进步,

处理完的图叠加到原图上面

Ray Marching 是什么

Ray Marching是光线进步 ,光线进步的原理是由我们的摄像机朝屏幕渲染的每一个像素发射一条射线,

Ray-marching 原理

在实时渲染中,通常采用 ray-marching 的方式实现介质中散射光的渲染。即对屏幕上每个像素,计算从摄像机发出的视线光线,在介质中以一个特定的步长迭代步进,并在每次步进的位置向光源再做一次 ray-marching 计算入射光强度,再根据 phase function 和 transmittance function 计算从当前位置到摄像机的散射光强度

流程

使用后处理获取到场景的物体的深度,然后使用深度屏幕空间重建世界空间坐标。 使用Ray Marching进行物体判断空间中这个点是否在阴影中。

在阴影中就不进行光的叠加,

如果不在阴影中进行光的叠加。

实现过程Render Feature

我们前准备一个基础的后处理效果,

Render Feature

Shader

Volume

准备一个场景验证效果

室内场景

Shader

整个计算过程,主要是分怎么几步,

获取深度计算

重构世界空间坐标

判断物体是否在阴影里

获取深度贴图

URP | Depth 深度 - 哔哩哔哩 (bilibili.com)

2. 使用屏幕空间去重构世界空间坐标

    这一步是给后面计算物体是否被光线影响准备。

    定义一个函数

这一步就使用屏幕纹理坐标和深度值重构出当前像素在世界空间中的位置

这里ro 前获取摄像机在世界空间中的位置。

效果

还有另一种方法 使用摄像机,在由摄像机来生成矩阵,传到我们的Shader中实现。

URP | 后处理-SSAO效果 - 哔哩哔哩 (bilibili.com)

扩展 ndc空间是什么?

我们在渲染的时候,物体世界空间转换到屏幕空间的时候,是需要进行ndc正交投影的,这个是渲染流水线的过程。

摄像机空间转换到屏幕空间

这个变换就将3D坐标变换成了2D坐标,即我们所看到的画面了。经过这个变换后,将看到的整个世界会被压缩到一个[-1,1]的立方体中。

这个过程我们有两个点需要注意, NDC 和 屏幕映射

正交投影 (NDC)

这里我们需要知道,摄像机渲染到屏幕,摄像机是有一个近裁面和远裁面的。 只有在这里才会显示。

透视视角

这里使用Unity 的摄像机 做演示,

顶视图

3. 计算光照强度叠加

    我们判断物体位置是不是在阴影里,如果在阴影里,我们的光照是不叠加的。    

    URP | 物体阴影 - 哔哩哔哩 (bilibili.com)    

    定义获取阴影的函数

注意:增加Lighting.hlsl库

在片元着色器阶段

初始化一个变量 currentPos 为相机位置

使用 length 函数计算出当前像素到相机之间的距离

定义三个属性

首先初始化一个变量 delta 为步长大小 _StepSize,用于控制每次迭代的步长

然后初始化两个变量 totalInt 和 d 为 0,分别用于记录总的积分值和当前的积分距离

计算光线进步

首先根据步长 delta 和方向向量 rd 计算出当前像素的位置 currentPos,然后使用 Getshadow 函数计算出当前像素位置的阴影值,并将其乘上光照强度 _LightIntensity,加入到总的积分值 totalInt 中。

接下来,根据场景中的主光源 mylight,将其颜色和积分值 totalInt 相乘,得到一个表示光照颜色的向量 lightCol。然后从原始纹理中采样出当前像素的颜色 oCol,并将光照颜色和原始颜色相加,得到最终的颜色 dCol。

shader部分完成

注意:这里加入一个_Color变量控制 颜色。

Volume

这里是外部控制的一些属性,

lightIntensity、stepSize、maxDistance 和 maxStep 是用于控制体积光效果的参数。

lightIntensity 控制体积光的强度,可以用来调整体积光的明暗程度。

stepSize 控制每次迭代的步长大小,可以用来控制体积光的精度和性能。

maxDistance 控制体积光的最大渲染距离,可以用来进行远近裁剪,避免在远处或者超出可视范围的位置进行不必要的计算。

maxStep 控制体积光的最大迭代次数,可以用来控制体积光的精度和性能。

注意这里 ColorChange  控制体积光的颜色, ColorChange 的 a 通道也可以控制强度,

效果

RendererFeature

这里简单没有难度,只是把Shader的材质赋值过来,不是很清楚的看前面

URP | 后处理-自定义后处理 - 哔哩哔哩 (bilibili.com)

注意 当前只在Game 视图显示,  Scene视图不显示

优化体积光

我们调整步长大小,就会出现很明显的 锯齿

这里我们使用前面处理的过的方法,使用模糊。这样的缺点就的更费,性能占比增加。

URP | 后处理-模糊算法总结 - 哔哩哔哩 (bilibili.com)

实现思路

我们生成体积光的以后在进行一步模糊,在和原图叠加起来,这里我们使用多Pass的方式实现。

高斯模糊

我们前处理Shader 计算高斯模糊

第一个Pass ,我们只需要获取到 体积光就可以,不需要和背景叠加,

修改Shader

把和背景叠加去掉,

只输出 体积光

2. 修改第二个的Pass ,我们来执行模糊效果,把上面出现的纹理进行模糊

这里具体参考前面的内容。

URP | 后处理-模糊算法总结 - 哔哩哔哩 (bilibili.com)

3.我们需要把模糊后面的效果和原场景进行叠加,才能显示出来。

所以第三个Pass 合并  (PS. 这里类型Bloom的效果)

全Shader

我们需要在Post 中控制两个属性,一个是模糊的次数和模糊的大小。

Volume 代码

记得在 RendererFeature 中绑定属性。

我们接着在RendererFeature 中增加代码  调整调用模糊

RendererFeature  

主要是处理两个地方,一个是使用循环执行模糊,一个是把原图传入到Shader进行融合。

注意:需要cmd.SetGlobalTexture("_FinalTex", source);   把原画传入到Shader进行融合

效果

我们就可以看到,模糊了间隔缝隙。

全代码  RendererFeature

问题:但是我们的边缘也模糊了,亮色颜色多出来了,

双边滤波

我们换一种模糊方式,这里使用双边滤波的方法,”保留了图像的边缘信息。

扩展

双边滤波和 高斯模糊有什么区别吗?

双边滤波是一种图像处理技术,它可以在保留边缘信息的同时,对图像进行平滑处理。它的基本思路是同时考虑将要被滤波的像素点的空域信息(domain)和值域信息(range)。因此是一种 combined 滤波方式,因此叫做 bilateral ,即同时考虑两方面的信息

在双边滤波中,两个要素即:closeness 和 similarity ,或者说 domain 和 range ,

其数学表达方式相近。其中积分号前面为归一化因子,这里考虑对所有的像素点进行加权,c 和 s 是 closeness 和 similarity 函数,x 代表要求的点,f (x) 代表该点的像素值。 f (x) –> h (x) 为滤波前后的image。我们最后的滤波函数为:

双边滤波算法介绍与实现_自适应双边滤波-CSDN博客

Unity Shader 实现磨皮效果_unity 给相机 双边滤波-CSDN博客

简单理解就是 双边滤波不处理边缘信息,只是模糊物体内部的部分。

这里我们在Shader中增加双边滤波的算法,具体公式计算查看参考资料。

我们只需要知道

_KernelSize

表示核大小。在这段代码中,它用于控制双边模糊的范围.

_Space_Sigma

表示空域高斯函数

_Range_Sigma

值域高斯函数的标准差

在双边模糊中,空域高斯函数和值域高斯函数都是用于计算像素点之间的权重,

其中空域高斯函数用于计算像素点之间的空间距离,值域高斯函数用于计算像素点之间的颜色差异。

标准差越大,表示像素点之间的差异越大,计算出来的权重也就越小,从而降低了双边模糊的程度。

反之,标准差越小,双边模糊的程度就越大。

代码

下面是这个Pass 中的全代码

注意: 增加 _MainTex_TexelSize 变量属性

RendererFeature

在RendererFeature 中我们增加 变量和 调整Pass

在Set MatData 增加属性

在Render 中 增加属性

效果

我们看到,亮色部分的边缘没有颜色溢出来。完成。

全代码

Shader

Volume

RendererFeature

总结

实现体积光的方法主要是使用光线进步方法, 由我们的摄像机朝屏幕渲染的每一个像素发射一条射线,根据深度判断这个像素是否在阴影中,如果不在阴影中就向光源的方向进行   ray-marching 计算光的强度,这些不在阴影中就是我们的体积光。

具体属性

VolumeLight   否启用体积光效果

ColorChange     体积光的颜色,   alpha 也可以控制体积光的强度

lightIntensity     体积光的强度

stepSize        体积光的步长大小

maxDistance    体积光最大的渲染距离

maxStep               体积光最大的迭代次数

所以在增大  体积光的步长时候我们看到有类型圆形的一个扩散效果。

体积光步长增大,

2. 模糊的使用,因为我们想降低步长,所会出现类似上面的效果,那我们就需要使用模糊进行,

这里第一种使用的高斯模糊,会把整个屏幕的像素进行修改,这不是我们想要的效果。

然后这里使用双边滤波(滤镜)的方法,这里补充了模糊的实现方法,双边滤波可以保留边缘的信息同时模糊物体信息。

3. 双边滤波(滤镜)主要用于平滑图像并保留图像的边缘信息。

在双边滤波中,每个像素点的新值是由它周围的像素点加权平均得到的。

双边滤波的核函数是空间域核与像素范围域核的综合结果:在图像的平坦区域,像素值变化很小,对应的像素范围域权重接近于1,此时空间域权重起主要作用,相当于进行高斯模糊;在图像的边缘区域,像素值变化很大,像素范围域权重变大,从而保持了边缘的信息。

权重由两个部分组成:空间权重和值域权重。

空间权重表示像素之间的空间距离,距离越远,权重越小;

值域权重表示像素之间的灰度差异,差异越大,权重越小。这样做可以保留图像中的边缘信息,因为边缘处的像素值变化剧烈,值域权重会比较小,从而保留了边缘处的细节信息。

优点:

是可以平滑图像并保留细节信息,同时对噪声有一定的抑制作用。

缺点

是算法复杂度较高,计算量大,对于大尺寸的图像,可能需要较长的处理时间。

单独定义一个Sahder,查看图像之间的变化。

Shader

资料

Unity Shader学习:体积光(Volumetric Light) - 知乎 (zhihu.com)

URP简易光线步进体积光 - 知乎 (zhihu.com)

URP使用RendererFeature实现体积光 - 知乎 (zhihu.com)

Unity快速实现平行光体积光(URP) - syb7384 - 博客园 (cnblogs.com)

【UnityShader】双边滤波(Bilateral Filtering)(5.2) - 知乎 (zhihu.com)

Unity Shader-GodRay,体积光(BillBoard,Volume Shadow,Raidal Blur,Ray-Marching)_houdini体积光_puppet_master的博客-CSDN博客

在 Unity 中实现体积光渲染 - 知乎 (zhihu.com)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3