Unity插件使用(2)_剖切插件CrossSection(HDRP)
目录
一、插件使用
二、修改增加动态切换的功能
三、包围盒移动问题
四、合并项目中后剖切的效果错误问题
五、剖切面贴图
插件默认是Build-in,需要打开HDRP包,2.7版本才开始支持HDRP,有个crossSection(HDRP)和crossSection(URP&HDRP),(URP&HDRP)是用shadergraph的
一、插件使用
1.创建一个HDRP项目
2.加载crossSection 2.7.unitypackage(淘宝上购买的,注意有些老的版本不知道HDRP的2.7开始才支持的)
3.在Unity中开crossSection(HDRP)和crossSection(URP&HDRP)
4.修改AutoLoadPipelineAsset,原本的代码是对应于URP的,HDRP下相应的改一下
using UnityEngine;
using UnityEngine.Rendering;[ExecuteAlways]
public class AutoLoadPipelineAsset : MonoBehaviour
{public RenderPipelineAsset pipelineAsset;private void OnEnable(){UpdatePipeline();}void UpdatePipeline(){//if (pipelineAsset)//{GraphicsSettings.renderPipelineAsset = pipelineAsset;//}}
}
5.可以运行测试场景了,打开hdrp相关场景,6个场景前4个完全正常,
最后2个有点问题
二、修改增加动态切换的功能
剖切的功能实际上是通过Shader实现的,对于项目中的模型来说,就是切换模型材质的Shader,创建剖切平面。
1.切换材质Shader
[ContextMenu("ReplaceMaterialShader")]void ReplaceMaterialShader(){if(csShader==null){return;}foreach(var mat in hdrpMaterials){if(!shaderSaved.ContainsKey(mat)){shaderSaved.Add(mat,mat.shader);}//获取HDRP/Lit的属性var texture=mat.GetTexture("_BaseColorMap");var color=mat.GetColor("_BaseColor");color=new Color(color.r*ColorPower,color.g*ColorPower,color.b*ColorPower,color.a);//原来的颜色作为自发光颜色有点太亮了,乘于一个系数,暗一点。var smoothness=mat.GetFloat("_Smoothness");var metallic=mat.GetFloat("_Metallic");var scale=mat.GetTextureScale("_BaseColorMap");var offset=mat.GetTextureOffset("_BaseColorMap");mat.shader=csShader;//修改材质,csShader选择CrossSectionGraph/PBR_Box先,需要法线什么的要考虑其他Shader//设置新Shader的属性mat.SetColor("_SectionColor",color);mat.SetColor("_EmissionColor",color);mat.SetTexture("_MainTex",texture);mat.SetFloat("_metallic",metallic);mat.SetFloat("_smoothness",smoothness);mat.SetVector("_UvOffset",offset);mat.SetVector("_UvTiling",scale);mat.SetFloat("__retractBackfaces",1);mat.SetFloat("_inverse",0);mat.SetFloat("_oneSided",0);}}[ContextMenu("RecoverMaterialShader")]void RecoverMaterialShader(){foreach(var mat in materials){if(shaderSaved.ContainsKey(mat)){mat.shader=shaderSaved[mat];}}shaderSaved.Clear();}
2.修改剖切平面
修改剖切平面,包围住新的要剖切的物体。
SectionSetup里面已经提供了一个函数SetModel,调用一下就好了
3.隐藏其他物体
public List<GameObject> hideObjects=new List<GameObject>();public List<Renderer> targetRenders=new List<Renderer>();public List<Renderer> allRenderers=new List<Renderer>();[ContextMenu("HideOthers")]public void HideOthers(){ShowOthers();//hideObjects.Clear();targetRenders.Clear();targetRenders.AddRange(setup.model.GetComponentsInChildren<Renderer>());//剖切目标模型targetRenders.AddRange(setup.gameObject.GetComponentsInChildren<Renderer>());//剖切包围盒的面if(Environment!=null){targetRenders.AddRange(Environment.GetComponentsInChildren<Renderer>());//地面等环境模型}allRenderers=GameObject.FindObjectsOfType<Renderer>().ToList();foreach(var renderer in targetRenders){renderer.gameObject.SetActive(true);}foreach(var renderer in allRenderers){if(!targetRenders.Contains(renderer)){renderer.gameObject.SetActive(false);hideObjects.Add(renderer.gameObject);}}}[ContextMenu("ShowOthers")]public void ShowOthers(){foreach(var obj in hideObjects){obj.SetActive(true);}hideObjects.Clear();}
三、包围盒移动问题
合并到项目中后,发现包围盒的控制出问题了,明明选中的是一个面(+Z)拖动时移动的是另一个面(-X),
就是我明明要拖动前面的一个面,结果被判断为拖动后面的面了。
看代码,发现它的算法就是调整包围盒(CrossSectionBox)的比例和位置,最终达到拖动一个包围盒的平面的效果。
原来的判断代码:
ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if (xAxis.Raycast(ray, out hit, 1000f)){selectedAxis = GizmoAxis.X;dragplane.SetNormalAndPosition(transform.up, transform.position);}else if (xAxisNeg.Raycast(ray, out hit, 1000f)){selectedAxis = GizmoAxis.Xneg;dragplane.SetNormalAndPosition(-transform.up, transform.position);}else if (yAxis.Raycast(ray, out hit, 1000f)){selectedAxis = GizmoAxis.Y;dragplane.SetNormalAndPosition(transform.forward, transform.position);}else if (yAxisNeg.Raycast(ray, out hit, 1000f)){selectedAxis = GizmoAxis.Yneg;dragplane.SetNormalAndPosition(-transform.forward, transform.position);}else if (zAxis.Raycast(ray, out hit, 1000f)){selectedAxis = GizmoAxis.Z;dragplane.SetNormalAndPosition(transform.up, transform.position);}else if (zAxisNeg.Raycast(ray, out hit, 1000f)){selectedAxis = GizmoAxis.Zneg;dragplane.SetNormalAndPosition(-transform.up, transform.position);}else{//Debug.Log(hit.collider.name);return;}
我加了个
ray = Camera.main.ScreenPointToRay(Input.mousePosition);var hits=Physics.RaycastAll(ray);hitObjs.Clear();foreach(var h in hits){hitObjs.Add(h.collider.gameObject);}
在独立的测试项目中,hitObjs只能打中前面的平面
而在工作项目中,前后平面都能打到,奇怪不奇怪....
平面本身是个Quad,没怎么用过....
它用if else的方式硬生生的导致有些面判断错误了....
不明白干嘛不用Physics.Raycast....
反正我改成用Physics.Raycast判断了,问题解决了。
RaycastHit hit;if(Physics.Raycast(ray,out hit)){hitCollider=hit.collider;if (xAxis == hitCollider){selectedAxis = GizmoAxis.X;dragplane.SetNormalAndPosition(transform.up, transform.position);}else if (xAxisNeg == hitCollider){selectedAxis = GizmoAxis.Xneg;dragplane.SetNormalAndPosition(-transform.up, transform.position);}else if (yAxis == hitCollider){selectedAxis = GizmoAxis.Y;dragplane.SetNormalAndPosition(transform.forward, transform.position);}else if (yAxisNeg == hitCollider){selectedAxis = GizmoAxis.Yneg;dragplane.SetNormalAndPosition(-transform.forward, transform.position);}else if (zAxis == hitCollider){selectedAxis = GizmoAxis.Z;dragplane.SetNormalAndPosition(transform.up, transform.position);}else if (zAxisNeg == hitCollider){selectedAxis = GizmoAxis.Zneg;dragplane.SetNormalAndPosition(-transform.up, transform.position);}else{//Debug.Log(hit.collider.name);return;}}else{return;}
发现在这种情况下无法点到包围平面
再调整一下吧,用RaycastAll
ray = Camera.main.ScreenPointToRay(Input.mousePosition);var hits=Physics.RaycastAll(ray);if(hits.Length==0) return;hitObjs.Clear();selectedAxis=GizmoAxis.none;RaycastHit hit=new RaycastHit();foreach(var h in hits){hit=h;hitObjs.Add(h.collider.gameObject);hitCollider=h.collider;if (xAxis == hitCollider){selectedAxis = GizmoAxis.X;dragplane.SetNormalAndPosition(transform.up, transform.position);break;}else if (xAxisNeg == hitCollider){selectedAxis = GizmoAxis.Xneg;dragplane.SetNormalAndPosition(-transform.up, transform.position);break;}else if (yAxis == hitCollider){selectedAxis = GizmoAxis.Y;dragplane.SetNormalAndPosition(transform.forward, transform.position);break;}else if (yAxisNeg == hitCollider){selectedAxis = GizmoAxis.Yneg;dragplane.SetNormalAndPosition(-transform.forward, transform.position);break;}else if (zAxis == hitCollider){selectedAxis = GizmoAxis.Z;dragplane.SetNormalAndPosition(transform.up, transform.position);break;}else if (zAxisNeg == hitCollider){selectedAxis = GizmoAxis.Zneg;dragplane.SetNormalAndPosition(-transform.up, transform.position);break;}}if(selectedAxis==GizmoAxis.none)return;
当然,设置一个Layer的话,上面的问题就没有了,但是这不是 可以不用设置Layer嘛。
合并到项目中发现还是有问题,在合并到项目中后,碰撞到的剖切面顺序好像不是按照一定的规则的....,反正明明在前面的平面不是第一个。
那,只能加个Layer了。
----------------------------------------------------------
四、合并项目中后剖切的效果错误问题
每个面都差了一段距离。
剖切区域跟随包围盒是受脚本CappedSectionFollow控制的,里面有
void OnEnable(){if (sectionMode == Mode.box){Shader.DisableKeyword("CLIP_NONE");Shader.EnableKeyword("CLIP_BOX");//Shader.SetGlobalInt("_CLIP_BOX", 1);}if (sectionMode == Mode.corner){Shader.DisableKeyword("CLIP_NONE");Shader.EnableKeyword("CLIP_CORNER");//Shader.SetGlobalInt("_CLIP_CORNER", 1);}SetSection();}
而我的项目似乎是材质太多了
Maximum number (256) of shader global keywords exceeded, keyword CLIP_NONE will be ignored.
解决方案,将keyword改为local。
参考1,讨论:https://forum.unity.com/threads/maximum-number-256-of-shader-global-keywords-exceeded-keyword-will-be-ignored-and-black-materials.803613/
参考2,调查:https://forum.unity.com/threads/shader-keyword-limit.545491/#post-3832954
参考3,例子:https://docs.google.com/document/d/156MgqojKIgWgrpJLJ0WgD8pVzG0A0T42e3wr0d0oaLg/edit
#pragma multi_compile_local _ FOO_ON//This will result in two variants with local keyword FOO_ON.public Material mat;
…
Private void Start()
{mat.EnableKeyword(“FOO_ON”);
}
...//Local keyword can be enabled the same way like before.
参考4,文档:https://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html?_ga=2.105567555.1551600638.1607676658-60239732.1590568025
Enabling and disabling shader keywords
To enable and disable shader keywords, use the following APIs:Shader.EnableKeyword: enable a global keyword
Shader.DisableKeyword: disable a global keyword
CommandBuffer.EnableShaderKeyword: use a CommandBuffer to enable a global keyword
CommandBuffer.DisableShaderKeyword: use a CommandBuffer to disable a global keyword
Material.EnableKeyword: enable a local keyword for a regular shader
Material.DisableKeyword: disable a local keyword for a regular shader
ComputeShader.EnableKeyword: enable a local keyword for a compute shader
ComputeShader.DisableKeyword: disable a local keyword for a compute shader
When you enable or disable a keyword, Unity uses the appropriate variant.
修改ShaderGraph的Globle:
修改其他材质的Shader,CapWrite.shader
//#pragma multi_compile __ CLIP_BOX CLIP_CORNER CLIP_PLANE CLIP_SPHERE_OUT#pragma multi_compile_local _ CLIP_BOX CLIP_CORNER CLIP_PLANE CLIP_SPHERE_OUT
加载相关的材质,
最后设置Keyword
public void DisableKeyword(string key){Debug.Log("CappedSectionFollow.DisableKeyword:"+key);if(IsLocalKeyword==false){Shader.DisableKeyword(key);}else{foreach(var mat in modelMaterials){mat.DisableKeyword(key);}foreach(var mat in sectionMaterials){mat.DisableKeyword(key);}}}public void EnableKeyword(string key){Debug.Log("CappedSectionFollow.EnableKeyword:"+key);if(IsLocalKeyword==false){Shader.EnableKeyword(key);}else{if(setup==null){setup=GameObject.FindObjectOfType<SectionSetup>();}if(setup.model!=lastSetupModel){lastSetupModel=setup.model;}GetMatierals(setup.model);foreach(var mat in modelMaterials){mat.EnableKeyword(key);}foreach(var mat in sectionMaterials){mat.EnableKeyword(key);}}}
最终,单独测试,和原本的功能不变。
合并到项目中,剖切效果正常了,但是打印里面还是有那个
Maximum number (256) of shader global keywords exceeded, keyword CLIP_NONE will be ignored.
奇怪....
另外_MAPPING_TRIPLANAR,_MASKMAP,_Emission,几个local的keyword设置时也是会提示错误的,但是效果正常。
五、剖切面贴图
剖面效果受几个方面影响
1.模型材质上的SectionColor,这是最基本的,我一般设置成和主颜色一致。
没有将物体的layer设置为下面的CustomWritePass上的LayerMask的情况下显示的就是这个颜色,或者直接CustomWritePass没有时。
注意oneSided必须是false,不然会是直接透过的
透过效果
2.CustomeWritePass上的CapWrite材质上的StencilMask的数值影响,1-63,64-127,128-191,192-255,4个类别。
1-63:SectionColor颜色
64-127:纹理1
128-191:纹理2
192-255:纹理3
学习一下StencilMask吧。。。
3.hatch平面,将CrossSectionBox里面的x_hatch平面去掉则纹理不显示
Hatch上有三个材质
三种切面的效果就是这三种材质的
总之,
1.模型上需要使用CrossSectionGraph/PBR_Box Shader
2.需要有CrawRenderersCustomPass,使用CrossSectionHDRP/Renderers/CapWrite Shader ,
3.有个x_patch平面,使用 CrossSectionHDRP/StencilShow Shader。
1是剖切的核心 2+3做出剖切面的纹理效果。
说实话,没学过理解这些效果原理的知识啊!!!!!
----------------------------------------------------------------------------------------------------------
3.项目中使用时,没有设置layer,
设置了Layer
总之无法得到实心的剖切效果。
虽然拖出来,独立一块,不要和其他模型重叠在一起是,剖切效果会好一点,比较“实心”,但是剖切面会闪面,有时候显示的不是剖切面
纯色切面的话倒是看不大出来问题
不考虑有纹理的剖切面的闪烁问题的话,剩下的注意问题就是,重叠模型导致的“非实心”效果,CrossSectionGraph/PBR_Box
几种材质切换测试,发现CrossSectionGraph/Autodesk Interactive效果比CrossSectionGraph/PBR_Box好一点点
onesiede:true的话
两者方式如果结合起来姐好了
或者从模型开始处理,让模型不相互重叠,其实也就是我要的剖切效果了,但是模型的数量很大
现在渲染2个模型的话大概有4个部分,模型1正面,模型2正面,模型1反面,模型2反面,正面渲染的优先级高,也就是先渲染的反面再渲染的正面。两个物体的正面之间又是根据深度来觉得渲染顺序的。
没有剖切前是正常的,红色的正面最终都会挡住灰色的正面,
剖切后先渲染了灰色的反面和红色的反面,然后再渲染了灰色的正面和红色正面,结果就是,灰色的反面挡住红色的反面,灰色的正面挡住了红色的反面,应该一片红的区域出现了灰色。
如果剖面效果能够渲染在最后面,将这些都挡住的话,在重叠部分无法是哪个模型的剖切纹理在前,都不会出现这种空心的效果
但实际上看来,纹理是渲染在模型的反面上的,效果还是穿插了的。甚至,它这个渲染还不稳定!
............................对于我当前没有渲染知识的人来说,要做出合理的剖切效果,只能是纯色切面+处理模型不重叠,暂时。
演示项目其实如果模型重叠在一起也不会那么和谐的,所以呢,我还是处理模型吧。
---------------------------------------------------再挣扎一下
Unity插件使用(2)_剖切插件CrossSection(HDRP)相关推荐
- 插件怎么用_【Anki插件篇】(01)插件介绍
https://www.bilibili.com/video/av59953393www.bilibili.com Anki的插件是anki相较于其他flashcard软件最大的优点之一,得益于an ...
- 【Unity3D插件】UniRx(基于Unity的响应式编程框架)插件学习
一.介绍UniRx插件 UniRx是一种基于Unity3D的响应式编程框架. UniRx就是Unity版本的Rx响应式扩展,响应式就是观察者和定时器,扩展指的是LINQ的操作符.Rx响应式扩展的特点就 ...
- 【Unity3D插件】UniRx(基于Unity的响应式编程框架)插件教程
推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有 ...
- Bootstrap学习笔记02【全局CSS样式、组件和插件、案例_黑马旅游网_首页】
Java后端 学习路线 笔记汇总表[黑马程序员] Bootstrap学习笔记01[快速入门.栅格布局][day01] Bootstrap学习笔记02[全局CSS样式.组件和插件.案例_黑马旅游网][d ...
- excel python插件_利用 Python 插件 xlwings 读写 Excel
Python 通过 xlwings 读取 Excel 数据 去年底公司让我做设备管理,多次委婉拒绝,最终还是做了.其实我比较喜欢技术.做管理后发现现场没有停机率统计,而原始数据有,每次要自己在Exce ...
- wordpress插件-Media folder插件汉化版_优化加速插件
介绍: Media folder插件汉化版_优化加速插件: 是一款真正的节省图片加载时间的插件,你可以管理文件和图片,从本地WordPress媒体管理器.该插件还包括一个增强版的WordPress图库 ...
- 多啦咪图虫_浏览器插件图片批量下载工具扩展插件图片下载
下载地址: 多啦咪图虫_浏览器插件图片批量下载工具扩展插件图片下载-紫咖啡小站是一款内嵌到浏览器的工具:可以帮你方便地从任意网站上批量采集喜欢的图片并迅速完成筛选和保存 多啦咪图虫 图片批量下载工具支 ...
- Unity 工具之 内嵌网页/浏览器插件使用和学习笔记
1.Embedded Browser 插件(文件夹名ZFBrowserUnity) 优点:设置简单,功能强大:输入url地址,拉取网页信息,可设置页面尺寸,可显示透明背景的网页,可与显示的页面进行互动 ...
- java代码自动生成的插件_如何使用插件生成自定义Java 8代码
java代码自动生成的插件 大多数程序员讨厌的一件事就是编写样板代码. 无休止的时间花费在设置实体类和配置数据库连接上. 为了避免这种情况,您可以让Speedment Open Source之类的程序 ...
最新文章
- Spring Boot 配置文件中的花样,看这一篇足矣!
- linux下开放端口
- docker 核心概念整理
- dubbo-go v3 版本 go module 踩坑记
- 微信摇一摇插件ios_微信开发平台 Jeewx-Boot
- 信安 | 网上吵个架都能被封号?是“黑科技”还是“黑产”?
- OJ1039: n个数求和(C语言for循环)
- am大学计算机科学,曹同学-综合大学排名80的TexasAMUniversity计算机科学硕士
- Delphi XE5教程1:语言概述
- IDEA修改Jsp模板
- ubuntu 测试硬盘读写速度
- VB 注册ocx控件的方法
- 在线考试系统微信小程序的实现(一)
- Python初级项目之随机漫步的Matplotlib实现
- 为什么按序流动只可能出现RAW即写后读相关?
- Java判断单个字符是否为空格
- 蒋松廷 荣获第六季完美童模全球总决赛 全球总冠军
- nkd 编译ffmpeg错误: clang is unable to create an executable file. C compiler test failed.
- 十条优秀的网站设计经验
- window电脑拖动直接安装apk应用的.bat