【Ue4卡通渲染描边方案】平均法线存入切线的改进算法——O(n)时间复杂度
目录
- 改进算法的必要性
- 改进方案
- 题外话
- 1/10日更新:别存切线!
改进算法的必要性
因为知乎帖子(https://zhuanlan.zhihu.com/p/234535777)写的比较全面(建议先去看他的帖子,我只是他 的改进),我有充裕的时间去优化迭代完成我的单子,就对他的算法做出了一点优化。
本以为只是一个小小的优化,但实际上Fbx的顶点数是真的多,时间复杂度的改进会非常明显。我拿了一个22万面的mesh做测试,改进前导入花费了50分钟,改进后7秒(共43秒,后面是ue4的模型转换逻辑导致)。可以说不改的话,顶点数一多就不能用了,所以改进是必要的。
以下是压力测试的结果:
原本耗时50分钟
改进后耗时43秒
改进方案
时间都是消耗在查找重叠点上的,很多网上方案查找重复序号用了二重循环,这样,模型顶点数一多就撑不住了。也看到用排序或者多线程(unity job system)的,其实没必要搞那么复杂,花费一点空间换时间,以序号为健名存在字典里面就好了,计算量大减。
(O(n^2)->O(n))
题外话
我改的是切线的,如果你需要存在其他地方,还要额外修改。另外这是Ue4代码片段,实际上还做了一些Fbx导入的UI勾选项等,这部分可以去找FbxSkeletalMeshImportData.h和FbxMainImport.cpp。因为本贴分享的重点在于时间复杂度的优化,就不全部贴出了。
如何还有什么需要在意的话,那就是法线平均值其实还有三种:等加权、角度加权、面积加权。(甚至还可以有混合的面积角度加权)但顶点偏移法画出的描边粗细会随着NdotV变化,没有一种方案是完成正确的,而且区别也不大,不用过渡纠结。(不过面积加权肯定是不好的,看猴子耳朵和壶嘴)
如果想实现角度加权可以去遍历面,但效果不一定会提升可能还会变差。
1/10日更新:别存切线!
存切线的话,切线空间都会乱掉,法线贴图会用不了,切空间各自操作都会用不了!存顶点色,uv都可以,别存切线。
void UnFbx::FFbxImporter::StoreAVGNormalsToTangent(FbxMesh* mesh)
{// 如果不存在 自动生成切线 副切线if (mesh->GetElementTangentCount() == 0 || mesh->GetElementBinormalCount() == 0){mesh->GenerateTangentsData(0, true);}//获取layerFbxLayer* layer0 = mesh->GetLayer(0);//依次获取layer中的顶点色、2uv、法线、切线、副法线FbxLayerElementNormal* VertNormal = layer0->GetNormals();FbxLayerElementTangent* VertTangent = layer0->GetTangents();TMap<int, FbxArray<FbxVector4>> VertexNormalsGroup;TMap<int, FbxVector4> VertexAVGNormals;//逐顶点遍历缓存法线信息for (int i = 0; i < mesh->GetPolygonVertexCount(); ++i){int vtxIdx = mesh->GetPolygonVertices()[i];FbxVector4 Normal = VertNormal->GetDirectArray()[i];//将顶点法线们 以顶点序号为key 填入字典if (!VertexNormalsGroup.Contains(vtxIdx)){FbxArray<FbxVector4> Normals;Normals.Add(Normal);VertexNormalsGroup.Add(vtxIdx, Normals);}else{VertexNormalsGroup[vtxIdx].AddUnique(Normal);}}//遍历tmap计算等权法线平均值for (auto& kvp : VertexNormalsGroup){FbxVector4 EqualWeightedSmoothNormal;if (kvp.Value.Size() == 1) {VertexAVGNormals.Add(kvp.Key, kvp.Value[0]);}else{for (int n = 0; n < kvp.Value.Size(); ++n){//万一法线模不为1,之前max脚本里看到过不是单位向量的法线EqualWeightedSmoothNormal += kvp.Value[n];}EqualWeightedSmoothNormal.Normalize();VertexAVGNormals.Add(kvp.Key, EqualWeightedSmoothNormal);}}VertexNormalsGroup.Empty();//FbxVector4::DotProduct()//改写顶点切线为法平均for (int j = 0; j < mesh->GetPolygonVertexCount(); ++j){int vtxIdx = mesh->GetPolygonVertices()[j];VertTangent->GetDirectArray().SetAt(j, VertexAVGNormals[vtxIdx]);}VertexAVGNormals.Empty();
}
参考了很多大佬的帖子:
【Ue4卡通渲染描边方案】平均法线存入切线的改进算法——O(n)时间复杂度相关推荐
- unity 3d物体描边效果_从零开始的卡通渲染描边篇
序言: 一直对卡通渲染非常感兴趣,前后翻找了不少的文档,做了一些工作.前段时间<从零开始>的手游上线了,试着渲染了一下的其中模型,觉得效果很不错.打算写一个专栏记录其中的渲染技术.在后面的 ...
- 卡通渲染描边的另一种做法
在我之前的文章中有一遍的说描边的问题汇总的: https://blog.csdn.net/llsansun/article/details/83744775 这里面也说了一些问题,最典型的问题是描边的 ...
- 卡通渲染-平均法线描边
[01]从零开始的卡通渲染-描边篇] 最近在学习渲染,入门的时候也学了Back facing描边法,但是表现在正方体上割裂严重,就先略过了. 看了这篇文章才了解到平均法线的做法,作者将平均法线存到模型 ...
- Unity下的日式卡通渲染实现-描边篇(三)
这边文章讲述的是项目中用到的一些卡通渲染描边相关技术. 一.Back Face外扩描边 背面外扩描边和后处理描边是卡通渲染中主要应用到的描边方式. 1.1 实现原理 第一个Pass正常渲染物体.第二个 ...
- UE4全场景卡通渲染
UE4全场景卡通渲染效果 这个配色实在是.. 大概效果就是这样了. 用后处理材质做卡通渲染 色块渲染和描边都是用后处理材质做的.描边就不详细说了,以前的文章有. 色块渲染,前面文章UE4卡通渲染提到的 ...
- 【非真实渲染】【卡通渲染技术点介绍】
阅读指南 文本介绍卡通渲染的基本技术,实现会放在另外的文档 关键词 Cel Shading,ToonShading,色块.色调,各向异性,描边,高光 特征 看起来像手绘的图片 少渐变(指光影的变换), ...
- 二次元卡通渲染——进阶技巧
前言 随着<原神>游戏的盛行,国内对于二次元游戏这块儿领域越来越看重了.二次元项目中本身基于日本的卡通动漫而来,所以最后的本质都是为了尽量还原2D立绘,而并不像PBR追求物理正确,只要好看 ...
- 寄存器分配图着色_【02】从零开始的卡通渲染-着色篇1
专栏目录 2173:[01]从零开始的卡通渲染-描边篇zhuanlan.zhihu.com 2173:[02]从零开始的卡通渲染-着色篇1zhuanlan.zhihu.com 2173:[03]从 ...
- 着色器实例 代码+注释 更新中【描边、卡通渲染、法线颜色、贴图动画等等】
描边着色器 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader " ...
最新文章
- 使用HTML5画布实现的超棒javascript动画仪表板:gauge.js
- 可可肉的奋斗(第一天)2012-12-24
- php 中的 mysqli事务处理
- webbrowser 百度列表点击_前嗅ForeSpider采集教程:关键词的「检索列表」采集「检索结果」...
- 微型php框架 include/mysql.class.php
- Typescript实现单例之父类调用子类
- 进击的程序媛:从 Google 第一位程序媛到硅谷女王进化史
- 社交界的 Linux,为何败给了 Facebook、Twitter?
- 如何查看IOS系统APP的包名
- vscode win10笔记本 蓝屏_老鸟教你win10开机蓝屏0xc000000d的详尽解决办法
- 分享一个返利系统源码,前端uni+后端php开发的影票返利系统源码
- 用VScode搭建uni-app项目(较全)
- 用Python画圣诞树
- SpringBoot+Vue 实现大文件断点下载
- SQL查询语句逻辑执行顺序
- 6.27软件园与血站见习报告
- ShardingSphere使用(一)
- JSJ——java基本概念二
- ubuntu下如何批量修改文件后缀名
- c语言 整数和浮点数_C ++处理整数和浮点数