【01】从零开始的卡通渲染-描边篇]

最近在学习渲染,入门的时候也学了Back facing描边法,但是表现在正方体上割裂严重,就先略过了。

看了这篇文章才了解到平均法线的做法,作者将平均法线存到模型的切线数据中,也提及了可以转换到切线空间再存到颜色或者uv上。因为他只做了存到切线数据的方案,我就想试试使用切线空间法线的方案,写出来才算融会贯通了。

对作者的工具稍作修改,将网格保存到本地。

《UnityShader入门精要》这本书的法线贴图相关章节,提到了TBN矩阵,在C#实现一下,并且类似法线贴图把数值范围处理到[0,1]。

工具:模型平均法线写入顶点颜色

    [MenuItem("Tools/模型平均法线写入顶点颜色")]public static void WriteToColor(){MeshFilter[] meshFilters = Selection.activeGameObject.GetComponentsInChildren<MeshFilter>();foreach (var meshFilter in meshFilters){Mesh mesh = Object.Instantiate(meshFilter.sharedMesh);ToColor(mesh);AssetDatabase.CreateAsset(mesh, "Assets/" + meshFilter.name + "New.mesh");}SkinnedMeshRenderer[] skinMeshRenders = Selection.activeGameObject.GetComponentsInChildren<SkinnedMeshRenderer>();foreach (var skinMeshRender in skinMeshRenders){Mesh mesh = Object.Instantiate(skinMeshRender.sharedMesh);ToColor(mesh);AssetDatabase.CreateAsset(mesh, "Assets/" + skinMeshRender.name + "New.mesh");}}private static void ToColor(Mesh mesh){var averageNormalHash = new Dictionary<Vector3, Vector3>();for (var j = 0; j < mesh.vertexCount; j++){if (!averageNormalHash.ContainsKey(mesh.vertices[j])){averageNormalHash.Add(mesh.vertices[j], mesh.normals[j]);}else{averageNormalHash[mesh.vertices[j]] =(averageNormalHash[mesh.vertices[j]] + mesh.normals[j]).normalized;}}var averageNormals = new Vector3[mesh.vertexCount];for (var j = 0; j < mesh.vertexCount; j++){averageNormals[j] = averageNormalHash[mesh.vertices[j]];//转到切线空间 并且设置成[0,1]范围var mNormal = mesh.normals[j];var mTangent = mesh.tangents[j];var mBinormal = Vector3.Cross(mNormal, new Vector3(mTangent.x, mTangent.y, mTangent.z)) * mTangent.w;//构造是按列,此处需要按行Matrix4x4 matrix = new Matrix4x4(new Vector3(mTangent.x, mTangent.y, mTangent.z).normalized, mBinormal.normalized, mNormal.normalized, Vector4.zero);Matrix4x4 tmatrix = Matrix4x4.Transpose(matrix);//[-1,1]=>[0,2]=>[0,1]averageNormals[j] = (tmatrix.MultiplyVector(averageNormals[j]).normalized + Vector3.one) / 2.0f;}var colors = new Color[mesh.vertexCount];for (var j = 0; j < mesh.vertexCount; j++){colors[j] = new Color(averageNormals[j].x, averageNormals[j].y, averageNormals[j].z, 0);}mesh.colors = colors;}

在Shader是类似的,将矩阵转置一下,就是切线空间转模型空间的矩阵

v2f vert(appdata v)
{v2f o;float4 pos = UnityObjectToClipPos(v.vertex);TANGENT_SPACE_ROTATION;float3 anormal = v.colors.rgb * 2 - 1;//这里再转置(逆)一下,因为rotation是模型空间转切线空间的矩阵anormal = normalize(mul(transpose(rotation), anormal));float3 viewNormal = mul((float3x3)UNITY_MATRIX_IT_MV, anormal.xyz);float3 ndcNormal = normalize(TransformViewToProjection(viewNormal.xyz)) ;//将法线变换到NDC空间float aspect = _ScreenParams.x / _ScreenParams.y;//求得屏幕宽高比ndcNormal.x /= aspect;//pos.w跟距离有关 裁剪后会除掉,进行近大远小缩放,但我们希望远处的描边也一样大,所以乘回去,避免被除没了pos.xy += 0.01 * _OutlineScale * ndcNormal.xy * pos.w;o.vertex = pos;return o;
}

TANGENT_SPACE_ROTATION; 会得到模型空间转切线空间矩阵rotation,再做一下转置就是切线转模型。

anormal就是还原好的模型空间下的平均法线

为了在屏幕上,无论远近描边大小都不变,也就是说要还原“透视除法”的处理,将w分量乘回去。
另外,我们在屏幕上沿着发现扩展的x增量,在视口变换后,会根据屏幕分辨率调整,横屏变得更大竖屏更小,因此也要消除掉这个影响。

卡通渲染-平均法线描边相关推荐

  1. 着色器实例 代码+注释 更新中【描边、卡通渲染、法线颜色、贴图动画等等】

    描边着色器 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader " ...

  2. 二次元卡通渲染-着色

    前言 本文为"优梦创客"原创文章,您可以自由转载,但必须加入完整的版权声明 更多学习资源请加QQ:1517069595获取(企业级性能优化/热更新/Shader特效/服务器/商业项 ...

  3. [Unity Shader]卡通渲染

    最终效果,包含描边,明暗双色阶的渲染,边缘光. 参考来源:https://www.zhihu.com/column/c_1215952152252121088 卡通渲染 Back facing描边 光 ...

  4. unity 3d物体描边效果_从零开始的卡通渲染描边篇

    序言: 一直对卡通渲染非常感兴趣,前后翻找了不少的文档,做了一些工作.前段时间<从零开始>的手游上线了,试着渲染了一下的其中模型,觉得效果很不错.打算写一个专栏记录其中的渲染技术.在后面的 ...

  5. Unity下的日式卡通渲染实现-描边篇(三)

    这边文章讲述的是项目中用到的一些卡通渲染描边相关技术. 一.Back Face外扩描边 背面外扩描边和后处理描边是卡通渲染中主要应用到的描边方式. 1.1 实现原理 第一个Pass正常渲染物体.第二个 ...

  6. 二次元卡通渲染之描边

    前言 本文为"优梦创客"原创文章,您可以自由转载,但必须加入完整的版权声明 更多学习资源请加QQ:1517069595获取(企业级性能优化/热更新/Shader特效/服务器/商业项 ...

  7. Unity Shader 卡通渲染 模型描边之退化四边形

    目录 前言 一.基于空间的边缘检测算法 二.退化四边形 三.Unity中的CommandBuffer和ComputeBuffer 四.构成描边的简单实例 五.模型描边的实现 前言 之前写了一篇< ...

  8. Unity Shader 卡通渲染 实时模型动画描边的研究

    前言 卡通渲染也叫非真实感渲染(英文简写:NPR),"描边"在图形学和数字图像里都叫边缘检测.因此你可以在很多文献网站上面找到很多这类文献,但最后我发现基于图形学使用的方式基本都是 ...

  9. Unity Shader 学习笔记(27)渲染轮廓线(描边)方法、卡通风格渲染、素描风格渲染

    Unity Shader 学习笔记(27)渲染轮廓线(描边)方法.卡通风格渲染.素描风格渲染 参考书籍:<Unity Shader 入门精要> 渲染轮廓线(描边) 五种方法: 基于观察角度 ...

最新文章

  1. pythonos模块修改文件名_python如何动态改变文件名
  2. 003_Redis配置
  3. [C#] C#访问数据库(SQL Server版本)
  4. 【Tools】cmake之编写CMakeLists.txt示例
  5. java类结构图_java 集合类结构图
  6. PHP调用数据库数据乱码问题
  7. 矢量合成和分解的法则_力的合成与分解
  8. 表示不同文件类型的魔术数字
  9. Java 数组在内存中的结构
  10. 用JavaScript来写浏览器上的应用
  11. win98万能显卡驱动_win98/98系统 u盘万能驱动
  12. unzip命令 – 解压缩zip文件
  13. FlashFXP使用阿里云ECS私钥登录
  14. 联通服务器光信号亮红灯移动,联通los红灯闪啥意思(图文)
  15. 互联网运营之道读书笔记
  16. 从心理学和传统文化角度来初步理解个体与环境
  17. 长沙地铁一号线大客流运输组织优化研究
  18. 第三方打码平台超级鹰图文识别,md5算法加密
  19. 陆奇:“黑客精神”过时了吗?答案是永远不会
  20. RISC-V基本介绍

热门文章

  1. tf.device does not support functions when eager execution
  2. C语言编程规范 — 头文件、函数
  3. html5文字开始空两格,一段文字的开头为什么要空两格
  4. 有一个棋盘有64个格子,第一个格子放一粒米,第二个格子放2粒米,第三个格子放4粒米,第四个格子放8粒米,以此类推,问放满64个格子有多少粒米?
  5. 从qsort函数和选择法排列得到的启发。
  6. 图片QPixmap和QByteArray之间的互转——Qt
  7. 李笑来泄露的50分钟谈话录音到底说了什么?
  8. 快速排序 Java模板
  9. java for循环遍历解释_三种for循环遍历
  10. Error: (‘IM002‘, ‘[IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序‘)