1.【UnityShader】3D拾取(PickBuffer)(19)
2.UnityShader 基础(29)-球面朝向映射(Matcap)-视角法线与平面反射
3.UnityShader 透明度混合(Alpha Blend)
4.unity urp源码学习一(渲染流程)
5.UnityShaderBillBoard(公告牌)原理和实现
6.UnityShader 基础(13)-高光渐变-Phong-Blinn高光与Shader分支
【UnityShader】3D拾取(PickBuffer)(19)
这篇文章讲述了如何在Unity URP 环境中使用PickBuffer技术实现3D场景中的鼠标拾取物体功能。首先,作者提到尽管射线检测常被提及,但通过渲染方式也能达成目标,这被称为PickBuffer。核心思想是topit.me 源码将每个渲染物体赋予一个唯一的ID,编码为颜色并渲染到RenderTexture上。
具体步骤包括创建PickBufferManager来管理颜色与物体映射,将物体ID直接与颜色数组对应,然后在渲染时通过Input类处理鼠标事件。接下来,需要创建自定义的PickBufferRenderFeature和RenderPass,将PickBufferManager的数据渲染到RenderTexture中,同时保持深度信息的准确性。创建一个Shader用于处理颜色渲染,以及一个RenderTexture用于存放PickBuffer数据。
在GPU Image回读阶段,通过Unity的接口读取RenderTexture,然后在PickBufferManager的Update函数中根据鼠标坐标获取目标物体的ID。通过在场景中添加辅助元素(如quad和标志物)进行调试,确保拾取功能正常工作。此外,文章还简要介绍了Unity原版描边功能的实现方法。
性能优化部分,通过对比PickBuffer和射线检测的性能,发现GPU Image回读是一个性能瓶颈。为了解决这个问题,作者考虑了只回读单个像素而非整个,利用Compute Shader来实现这一目标。最终,通过Compute Shader将鼠标坐标映射到单个像素颜色,成功地减少了性能开销。
总的来说,尽管Unity内置的PickBuffer功能可能在实际项目中并不常见,但它提供了一个学习和实践Unity渲染技术的好机会,鼓励读者在自己的渲染器中实现类似的功能。
UnityShader 基础()-球面朝向映射(Matcap)-视角法线与平面反射
在Unity Shader中,有一种叫做Matcap的技术,它是一种快速模拟反射效果的便捷方法。Matcap源自于ZBrush,其原理是通过让物体表面的视角法线与Matcap球体表面的坐标方向对应,实现直观的反射效果展示。视角法线是一种特殊的法线,它依据摄像机视角定义,例如物体正面朝向正左时,视角法线的X值为1,正右则为-1,java云笔记源码以此类推。
在处理法线数据时,需要注意缩放可能带来的影响,通过normalize()函数将其转换为标准的-1到1范围。然后,通过UV坐标映射,使用*0.5+0.5的转换方法和saturate()函数防止溢出,确保视角法线与UV对应。Matcap通常来自金属球体或鱼眼相机,被称为鱼眼图像,获取更多素材可以通过加入指定QQ群。
基础Matcap Shader代码中,可以引入_MatCapMipLevel来控制清晰度级别,以便在不同的LOD(Level of Detail)下显示。在处理纯平面物体时,反射效果会呈现出单一颜色,这是因为取色和反射取色规则不同。通过reflect()函数可以实现反射,但可能产生折返效果。通过调整法线数据,可以控制反射的强度和形状,如使用Pow()函数或自定义函数。
针对平面颜色一致问题,需要在顶点和法线到视角空间的转换中进行修正,确保法线方向在缩放时保持正确。通过这种方式,平面图像的反射效果得以改善。最后,可以结合曲率计算,混合平面和曲面的反射效果,创建更丰富的视觉效果。
总的来说,Matcap技术为Unity Shader提供了直观、高效的反射模拟,通过灵活的处理和组合,可以实现丰富多样的材质效果。
UnityShader 透明度混合(Alpha Blend)
透明度混合,即Alpha Blend,是Unity Shader中实现半透明效果的关键技术。其原理在于,利用当前片段的透明度值与已有颜色缓冲中的颜色进行混合,生成新的颜色值。值得注意的是,进行透明度混合时需要关闭深度写入,以确保正确渲染。在Unity Shader中,iapp 免杀源码通过Blend混合命令来实现这一功能。
BlendOp命令决定了混合操作的类型,若未指定,则默认为Add操作。例如,使用传统透明度混合命令:
上图与下方命令效果一致。通用混合公式为:finalValue = sourceFactor * sourceValue operation destinationFactor * destinationValue
具体到Blend SrcAlpha OneMinusSrcAlpha命令,即:源Alpha通道与反Alpha通道进行混合。
为了实现传统透明效果,需考虑关闭深度写入可能产生的错误渲染问题。解决方法是分两个Pass渲染模型:第一个Pass开启深度写入,但不输出颜色,仅记录深度值;第二个Pass执行正常透明度混合。此方案虽增加渲染开销,但确保了模型间的正确透明效果。
使用ColorMask命令可控制颜色通道的写入,例如设置为ColorMask 0,表示该Pass不写入任何颜色通道,不输出颜色。
若需观察正方体内部或背面形状,需使用Cull指令控制剔除面的渲染。在Unity中,Cull指令默认执行背面剔除(Cull Back)。通过将渲染分为两个Pass,分别渲染背面和正面,确保正确的深度关系,实现双面渲染。
本文基于《Unity Shader入门精要》的学习笔记,加入了个人理解。如有错误,欢迎指正。
unity urp源码学习一(渲染流程)
sprt的一些基础:
绘制出物体的关键代码涉及设置shader标签(例如"LightMode" = "CustomLit"),以确保管线能够获取正确的shader并绘制物体。排序设置(sortingSettings)管理渲染顺序,如不透明物体从前至后排序,透明物体从后至前,以减少过绘制。逐物体数据的启用、动态合批和gpuinstance支持,以及主光源索引等配置均在此进行调整。
过滤规则(filteringSettings)允许选择性绘制cullingResults中的几何体,依据RenderQueue和LayerMask等条件进行过滤。
提交渲染命令是关键步骤,无论使用context还是commandbuffer,调用完毕后必须执行提交操作。例如,生日祝福源码下载context.DrawRenderers()用于绘制场景中的网格体,本质上是执行commandbuffer以渲染网格体。
sprt管线的基本流程涉及context的命令贯穿整个渲染流程。例如,首次调用渲染不透明物体,随后可能调用渲染半透明物体、天空盒、特定层渲染等。流程大致如下:
多相机情况也通过单个context实现渲染。
urp渲染流程概览:
渲染流程始于遍历相机,如果是游戏相机,则调用RenderCameraStack函数。此函数区分base相机和Overlay相机:base相机遍历渲染自身及其挂载的Overlay相机,并将Overlay内容覆盖到base相机上;Overlay相机仅返回,不进行渲染操作。
RenderCameraStack函数接受CameraData参数,其中包含各种pass信息。添加pass到m_ActiveRenderPassQueue队列是关键步骤,各种pass类实例由此添加至队列。
以DrawObjectsPass为例,其渲染流程在UniversialRenderer.cs中实现。首先在Setup函数中将pass添加到队列,执行时,执行队列内的pass,并按顺序提交渲染操作。
UnityShaderBillBoard(公告牌)原理和实现
公告牌技术
公告牌技术是基于视角确定纹理矩形朝向的一种图形处理方法。它广泛应用于实现诸如草、烟、火、雾、爆炸、云等特殊效果。这一技术的核心在于建立一个基于视角的坐标系,通过旋转物体来保持纹理矩形在特定方向上固定,从而模拟各种动态效果。
公告牌原理
在实现公告牌技术时,需要记录物体在物体空间的顶点相对于原点的各方向位移。利用相机位置确定视线方向,从而确定物体的法向量(与视线方向相反且平行)。通过指定一个向上向量重建新的坐标系,并将顶点在原坐标系的位移转移至新坐标系建立旋转后的顶点位置,完成在物体空间下的旋转。
公告牌分类
屏幕对齐的广告牌是最简单的一种形式,其图像总是平行于屏幕,具有恒定的向上向量。摄像机将物体投影到与远近平面平行的海豚源码破解教程视图平面上。在这种类型的广告牌中,物体表面的法线为视图平面法线的相反方向。通常用于粒子系统或总是面向屏幕的文本。
Viewpoint-oriented广告牌则更为复杂。在这种情况下,向上的向量由相机本身的向上向量变为世界空间下的向上向量。通过与物体法向(与视线方向相反且平行)叉乘求得向右向量,最后使用物体法向与该向右向量叉乘求得物体最终准确的向上向量,完成新的坐标系的重建。这使得广告牌能够更好地模拟真实世界中的运动。
公告牌实现
在UnityShader中,实现公告牌技术可以通过编写特定的着色器代码来完成。参考《UnityShader入门精要(冯乐乐)》等资源,可以学习到具体的实现方法。在Unity中,物体的scale属性必须等比例缩放,且rotation属性全为0,才能确保广告牌达到预期效果。这确保了物体空间的向上向量与世界空间的向上向量同向平行。
公告牌技巧
虽然等比例缩放和旋转属性为0是推荐的做法,但也可以利用这些属性达到一些特殊效果,例如特定视角下的物体缩放。通过调整物体的scale属性在不同坐标轴上的比例,可以实现特定视角下物体形状的变化。这展示了公告牌技术的灵活性和多用途性。
UnityShader 基础()-高光渐变-Phong-Blinn高光与Shader分支
本节将深入探讨UnityShader的基础,特别是关于高光渐变的两种实现方式:Phong高光模式与Blinn高光模式。首先,制作光照效果时,我们需要获取物体表面的法线向量,以及灯光方向与摄像机视角。
为了规范化矢量,我们将使用`normalize()`函数。在高光计算过程中,Phong与Blinn两种模式各有特点。Phong高光模式中,我们通过`reflect()`函数求取反射向量,并翻转灯光方向,接着计算反射方向与视角方向的点乘,将其结果与数值1对应红色,-1对应蓝色,以便直观观察计算结果。
而Blinn高光模式则提供了一种快速简化的方法。其核心在于将灯光与视角相加以获得高光方向,然后计算高光方向与表面法线之间的点乘,最终通过着色查看高光渐变的过程。
在总结部分,我们发现Phong算法在准确性方面具有优势,而Blinn算法则在速度上表现更快。无论是Phong还是Blinn算法,都能依据摄像机与视角的不同,产生不同的高光效果。
为了实现高光模式的灵活切换,可以使用Shader分支开关来控制Phong与Blinn高光模式的使用,需确保名称一致性。
接下来,我们将深入高光的调整,通过`pow()`函数对渐变过程进行修改,调整`_specularRange`的数值可以控制高光范围的大小。同时,通过调整`_specularIntensity`参数,可以提高高光的亮度。为了实现卡通硬边高光效果,可以使用`step()`阈值函数将数据转换为0或1。
最后,通过为高光添加`_specularColor`参数,我们可以为高光着色。将调整后的Shader代码与上一节的照明过程相加,即可实现高光与照明的混合效果。
UGUI源码阅读之Mask
Mask主要基于模版测试来进行裁剪,因此先来了解一下unity中的模版测试。
Unity Shader中的模版测试配置代码大致如上
模版测试的伪代码大概如上
传统的渲染管线中,模版测试和深度测试一般发生在片元着色器(Fragment Shader)之后,但是现在又出现了Early Fragment Test,可以在片元着色器之前进行。
Mask直接继承了UIBehaviour类,同时继承了ICanvasRaycastFilter和IMaterialModifier接口。
Mask主要通过GetModifiedMaterial修改graphic的Material。大致流程:
1.获取当前Mask的层stencilDepth
2.StencilMaterial.Add修改baseMaterial的模板测试相关配置,并将其缓存
3.StencilMaterial.Add设置一个unmaskMaterial,用于最后将模板值还原
MaskableGraphic通过MaskUtilities.GetStencilDepth计算父节点的Mask层数,然后StencilMaterial.Add修改模板测试的配置。
通过Frame Debugger看看具体每个batch都做了什么。先看第一个,是Mask1的m_MaskMaterial,关注Stencil相关的数值,白色圆内的stencil buffer的值设置为1
这个是Mask2的m_MaskMaterial,根据stencil的计算公式,Ref & ReadMask=1,Comp=Equal,只有stencil buffer & ReadMask=1的像素可以通过模板测试,即第一个白色圆内的像素,然后Pass=Replace,会将通过的像素写入模板值(Ref & WriteMask=3),即两圆相交部分模板值为3
这个是RawImage的Material,只有模板值等于3的像素可以通过模板测试,所以只有两个圆相交的部分可以写入buffer,其他部分舍弃,通过或者失败都不改变模板值
这是Mask2的unmaskMaterial,将两个圆相交部分的模板值设置为1,也就是还原Mask2之前的stencil buffer
这是Mask1的unmaskMaterial,将第一个圆内的模板值设置为0,还有成最初的stencil buffer
可以看到Mask会产生比较严重的overdraw。
2.drawcall和合批
每添加一个mask,一般会增加2个drawcall(加上mask会阻断mask外和mask内的合批造成的额外drawcall),一个用于设置遮罩用的stencil buffer,一个用于还原stencil buffer。
如图,同一个Mask下放置两个使用相同的RawImage,通过Profiler可以看到两个RawImage可以进行合批
如图,两个RawImage使用相同的,它们处于不同的Mask之下,但是只要m_StencilValue相等,两个RawImage还是可以进行合批。同时可以看到Mask1和Mask1 (1),Mask2和Mask2 (1)也进行了合批,说明stencilDepth相等的Mask符合合批规则也可以进行合批。
StencilMaterial.Add会将修改后的材质球缓存在m_List中,因此调用StencilMaterial.Add在相同参数情况下将获得同一个材质球。
如何更高效的学习和编写UnityShader(工具+收藏分享帖)
分享一些高效编写Unity Shader的学习技巧和工具,希望能对大家有所帮助。以下工具与插件,均非与我有商业关系,不包含任何推广链接。
工具与插件:
1. 使用VScode + Shaderlab插件进行Shader编写。VScode快速且轻量,Shaderlab插件功能强大且持续更新。其引用查找功能极为便捷,如下图所示。
2. 使用翻译插件,如彩云小译,实现网页翻译、文献翻译、在线翻译,具备双语对照功能,帮助理解晦涩词汇。同时,支持PDF云端翻译,功能虽不完美,但在某些场景下仍能使用。
3. 推荐使用Github插件Sourcegraph,免费提供,用于查找引用和关键字,操作方便,效率高。
4. 笔记类软件方面,原本使用有道,但mac版本的搜索功能不佳,后改为语雀,体验良好。对于有道笔记能否一键迁移至语雀,目前未找到解决方案。
5. 使用taecg/ShaderReference工具,查询Shader语法大全,可联系作者请求新版本。
6. JetBrains Rider是一款强大的编辑器,最新版本支持Shader跳转功能,可快速查找引用和文件,功能强大。
白嫖圣地及学习资源:
1. 在个人书签中分享各种资源链接,由于篇幅限制,已移至Git仓库。
2. 探索其他白嫖资源,自行发掘和体验。
3. killop的书签,是一个宝藏资源,收藏了大量总结文档,值得深入学习。
持续更新中...
UnityShader 曲面细分着色器(Tessellation Shader)()
UnityShader曲面细分着色器(Tessellation Shader)详解()
在深入理解几何着色器后,曲面细分着色器(Tessellation Shader,简称TS)是另一个值得探索的领域。它利用GPU技术对网格中的三角形进行精细的细分,以提升模型表面的细节。TS并非独立的着色器,而是由壳着色器(HullShader)、域着色器(DomainShader)和镶嵌器阶段(Tessellation Stage)组成的一个概念。嵌套在这一过程中的常量外壳着色器(Constant Hull Shader)负责计算细分因子。
Hull Shader作为传递着色器,接收输入的控制点,并根据指定的参数,如细分模式(整数或非整数)、输出顶点数量等,输出控制点。控制点的设置决定了细分形状,就如同贝塞尔曲线中的控制点定义了曲线的形态。
Constant Hull Shader主要负责确定每个边的细分因子,影响细分后顶点的数量。细分因子的动态调整,如根据摄像机距离,是通过简单的归一化算法实现的,以实现LOD(层次细节)效果。
Domain Shader则是执行细分的阶段,计算细分后的顶点位置,并进行MVP变换。这个阶段的输出是新的顶点坐标,它们在原始网格的基础上进行了插值计算。
TS的执行流程在渲染管线中表现为:Vertex Shader -> Tessellation Shader -> Fragment Shader。在实际项目中,TS可以与几何着色器(GS)结合,增加更多的几何处理可能性。
虽然TS看似复杂,但理解和应用它有助于技术工具的掌握。通过HeightMap案例,我们可以看到TS如何在地形细节上发挥作用,但具体应用到实际项目中的细节仍需进一步学习和实践。
UnityShaderBlur 模糊(5)
本节介绍模糊算法。模糊、边沿查找本质是一个滤波器,使用低通滤波/高通滤波来完成图像处理的目的。这些似乎涉及CV(计算机视觉)的研究范围,本文旨在展示如何在Unity中实现模糊效果,而非深入研究“信号与系统”的理论知识。做工程讲究实用性,能用即可。 后续更新:在Unity中实现模糊算法的步骤。一、在Unity中的前期准备
在上一节中,我们了解到如何在Unity URP中实现后处理效果。为了扩展PostProcessing相关组件(现在称为Volume),我们需要编写一个cs脚本,继承于VolumeComponent。Volume组件包含了常用的后处理特效,如Bloom(辉光)与ToneMapping(色调映射),可以显著提升画面效果。尽管Volume组件本身没有提供模糊功能,我们可以通过自定义实现。二、模糊算法实现
虽然高斯模糊是模糊算法的代表,但还有其他方式,如方框模糊、径向模糊、双重模糊、Kawase模糊等。本节将实现其中几种自认为实用的模糊效果。1. 模糊的本质
当我们感觉图像“模糊”时,实际上是因为像素点的颜色受到周围区域颜色的影响,使得像素点的“对比度”下降,颜色特征不鲜明。这种现象可以类比于人眼在远视状态下的视觉体验,物体反射的光线无法聚焦在视网膜上,形成多个“重影”,增加了模糊感。在图像处理中,模糊算法通过“污染”像素点的颜色,达到“模糊”效果。2. Kawase Blur
Kawase模糊采用动态卷积核来提升效率,不同于高斯模糊或方框模糊中的恒定卷积核。其核心思路是对距离当前像素较远的位置进行采样,并在两个大小相等的纹理之间进行乒乓式的blit操作。通过随迭代次数移动的blur kernel,实现更加灵活且高效的模糊效果。3. Dual Blur
双重模糊通过降采样和升采样过程实现,即在blit过程中进行图像大小的调整。相比于Kawase模糊,双重模糊在实现上更加复杂,但能提供不同场景下的模糊效果。4. Radial Blur
为了在图像中产生“速度感”和“打击感”,径向模糊是最常用的技术。通过在指定方向上进行模糊处理,可以模拟出物体移动或光线照射的效果。实现径向模糊时,需要调整纹理和采样方向,以达到预期的视觉效果。小结
通过上述方法,我们能够在Unity URP中实现常见的模糊算法。在实际应用中,可以根据需求选择最合适的模糊类型,例如,Kawase模糊在性能和效果上通常被认为是一个不错的选择。模糊算法在后处理中有着广泛的应用,如体积光处理,能够有效提升场景的视觉效果。