当前位置:网站首页>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 .
边栏推荐
猜你喜欢
Driving test Baodian and its spokesperson Huang Bo appeared together to call for safe and civilized travel
Minecraft air Island service
OpenShift构建镜像
群辉 NAS 配置 iSCSI 存储
kubernetes部署loki日志系统
Minecraft module service opening
OpenShift 部署应用
Openfeign facile à utiliser
Redis安装部署(Windows/Linux)
Zipkin is easy to use
随机推荐
ORA-12514问题解决方法
QT qtimer class
C Gaode map obtains the address according to longitude and latitude
Luogu greedy part of the backpack line segment covers the queue to receive water
Introduction to the basic concept of queue and typical application examples
OpenShift构建镜像
将一串数字顺序后移
gocv拆分颜色通道
Judge whether it is Sudoku
C# 调用系统声音 嘀~
队列管理器running状态下无法查看通道
gocv边界填充
gocv图片裁剪并展示
判断是否是数独
OpenShift 容器平台社区版 OKD 4.10.0部署
commands out of sync. did you run multiple statements at once
There is a problem with MySQL installation (the service already exists)
OpenFeign 简单使用
gocv图片读取并展示
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