当前位置:网站首页>Cartoon rendering - average normal stroke
Cartoon rendering - average normal stroke
2022-07-02 09:03:00 【Ink pool Ivory】
【01】 Cartoon rendering from scratch - Stroke article ]
Recently learning rendering , I also learned when I started Back facing Stroke method , However, the cube is seriously fragmented , Just skip .
After reading this article, I learned how to average normals , The author saves the average normal to the tangent data of the model , It is also mentioned that you can convert to tangent space and then save to color or uv On . Because he only made the scheme of saving tangent data , I just want to try the scheme of using tangent space normals , Only when you write it out can you understand it well .
Slightly modify the author's tools , Save the grid locally .
《UnityShader Introduction to topic 》 Normal mapping related chapters of this book , Referred to the TBN matrix , stay C# Achieve it , And similar to the normal map, the numerical range is processed to [0,1].
Tools : Model average normal writes vertex color
[MenuItem("Tools/ Model average normal writes vertex color ")]
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]];
// Go to tangent space And set it to [0,1] Range
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;
// Construction is by column , Here you need to press line
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;
}
stay Shader It's similar , Transpose the matrix , It is the matrix from tangent space to model space
v2f vert(appdata v)
{
v2f o;
float4 pos = UnityObjectToClipPos(v.vertex);
TANGENT_SPACE_ROTATION;
float3 anormal = v.colors.rgb * 2 - 1;
// Transpose here ( The inverse ) once , because rotation Is the matrix from model space to tangent space
anormal = normalize(mul(transpose(rotation), anormal));
float3 viewNormal = mul((float3x3)UNITY_MATRIX_IT_MV, anormal.xyz);
float3 ndcNormal = normalize(TransformViewToProjection(viewNormal.xyz)) ;// Transform normals to NDC Space
float aspect = _ScreenParams.x / _ScreenParams.y;// Find the screen aspect ratio
ndcNormal.x /= aspect;
//pos.w It's about distance It will be removed after cutting , Zoom in and out , But we hope the trace in the distance is as big , So take it back , Avoid being eliminated
pos.xy += 0.01 * _OutlineScale * ndcNormal.xy * pos.w;
o.vertex = pos;
return o;
}
TANGENT_SPACE_ROTATION; You will get the model space to tangent space matrix rotation, Another transpose is tangent to model .
anormal Is the average normal in the restored model space
In order to be on the screen , No matter far or near, the stroke size remains the same , That is, to restore “ Perspective division ” To deal with , take w Multiply the weight back .
in addition , We found the extended x The incremental , After viewport transformation , It will be adjusted according to the screen resolution , The horizontal screen becomes larger and the vertical screen smaller , Therefore, it is also necessary to eliminate this influence .
边栏推荐
- 队列的基本概念介绍以及典型应用示例
- Tensorflow2 keras classification model
- D interface and domain problems
- C language implementation of mine sweeping game
- C Gaode map obtains the address according to longitude and latitude
- Sentinel easy to use
- Sentinel 简单使用
- Aneng logistics' share price hit a new low: the market value evaporated by nearly 10 billion yuan, and it's useless for chairman Wang Yongjun to increase his holdings
- History of Web Technology
- Openfeign is easy to use
猜你喜欢

Kubedm deploys kubernetes v1.23.5 cluster

C#钉钉开发:取得所有员工通讯录和发送工作通知

C4D quick start tutorial - Chamfer

Mysql安装时mysqld.exe报`应用程序无法正常启动(0xc000007b)`

Installing Oracle database 19C RAC on Linux

Sqli labs (post type injection)

Openfeign is easy to use

Function ‘ngram‘ is not defined

Solution and analysis of Hanoi Tower problem

汉诺塔问题的求解与分析
随机推荐
Function ‘ngram‘ is not defined
Driving test Baodian and its spokesperson Huang Bo appeared together to call for safe and civilized travel
Getting started with k8s: building MySQL with Helm
Web技术发展史
Image transformation, transpose
Openshift deployment application
NPOI 导出Word 字号对应
libusb的使用
选择排序和插入排序
Linux二进制安装Oracle Database 19c
使用递归函数求解字符串的逆置问题
Qunhui NAS configuring iSCSI storage
Count the number of various characters in the string
Nacos 下载启动、配置 MySQL 数据库
统计字符串中各类字符的个数
QT qtimer class
oracle删除表空间及用户
将一串数字顺序后移
Mysql安装时mysqld.exe报`应用程序无法正常启动(0xc000007b)`
win10使用docker拉取redis镜像报错read-only file system: unknown