{"id":756,"date":"2024-06-25T16:56:12","date_gmt":"2024-06-25T07:56:12","guid":{"rendered":"https:\/\/xn--k10aa.com\/?p=756"},"modified":"2024-10-17T15:32:18","modified_gmt":"2024-10-17T06:32:18","slug":"unity-ts","status":"publish","type":"post","link":"https:\/\/remoooo.com\/en\/unity-ts\/","title":{"rendered":"Unity Tessellation"},"content":{"rendered":"<p>Tags: Getting Started\/Shader\/Tessellation Shader\/Displacement Map\/LOD\/Smooth Outline\/Early Culling<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The word tessellation refers to a broad category of design activities, usually involving the arrangement of tiles of various geometric shapes next to each other to form a pattern on a flat surface. Its purpose can be artistic or practical, and many examples date back thousands of years. \u2014 Tessellation, Wikipedia, accessed July 2020.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>This article mainly refers to:<\/p>\n\n\n\n<p><a href=\"https:\/\/nedmakesgames.medium.com\/mastering-tessellation-shaders-and-their-many-uses-in-unity-9caeb760150e\">https:\/\/nedmakesgames.medium.com\/mastering-tessellation-shaders-and-their-many-uses-in-unity-9caeb760150e<\/a><\/p>\n\n\n\n<p>Surface subdivision in game development is generally done in a triangle<strong>flat<\/strong>(or Quad) and then use the Displacement map to do vertex displacement, or use the Phong subdivision or PN triangles subdivision implemented in this article to do vertex displacement.<\/p>\n\n\n\n<p>Phong subdivision does not need to know the adjacent topological information, only uses interpolation calculation, which is more efficient than PN triangles and other algorithms. Loop and Schaefer mentioned in GAMES101 use low-degree quadrilateral surfaces to approximate Catmull-Clark surfaces. The polygons input by these methods are replaced by a polynomial surface. The Phong subdivision in this article does not require any operation to correct additional geometric areas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Overview of the tessellation process<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>This chapter introduces the process of surface subdivision in the rendering pipeline.<\/p>\n<\/blockquote>\n\n\n\n<p>The tessellation shader is located after the vertex shader, and the tessellation is divided into three steps: Hull, Tesselllator and Domain, among which Tessellator is not programmable.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-145-1024x527.png\" alt=\"\" class=\"wp-image-803 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"527\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-145-1024x527.png\" alt=\"\" class=\"wp-image-803 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-145-1024x527.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-145-300x154.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-145-768x395.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-145.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>The first step of tessellation is the tessellation control shader (also known as Tessellation Control Shader, TCS), which will output control points and tessellation factors. This stage mainly consists of two parallel functions: Hull Function and Patch Constant Function.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-102-1024x461.png\" alt=\"\" class=\"wp-image-758 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"461\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-102-1024x461.png\" alt=\"\" class=\"wp-image-758 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-102-1024x461.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-102-300x135.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-102-768x346.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-102.png 1284w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Both functions receive patches, which are a set of vertex indices. For example, a triangle uses three numbers to represent the vertex indices. One patch can form a fragment, for example, a triangle fragment is composed of three vertex indices.<\/p>\n\n\n\n<p>Moreover, the Hull Function is executed once for each vertex, and the Path Constant Function is executed once for each Patch. The former outputs the modified control point data (usually including vertex position, possible normals, texture coordinates and other attributes), while the latter outputs the constant data related to the entire fragment, that is, the subdivision factor. The subdivision factor tells the next stage (the tessellator) how to subdivide each fragment.<\/p>\n\n\n\n<p>In general, the Hull Function modifies each control point, while the Patch Constant Function determines the level of subdivision based on the distance from the camera.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-104-1024x524.png\" alt=\"\" class=\"wp-image-760 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"524\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-104-1024x524.png\" alt=\"\" class=\"wp-image-760 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-104-1024x524.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-104-300x153.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-104-768x393.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-104.png 1228w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Next comes the non-programmable stage, the tessellator. It receives the patch and the subdivision factor just obtained. The tessellator generates a barycentric coordinate for each vertex data.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-103-1024x533.png\" alt=\"\" class=\"wp-image-759 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"533\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-103-1024x533.png\" alt=\"\" class=\"wp-image-759 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-103-1024x533.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-103-300x156.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-103-768x400.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-103.png 1326w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Next comes the last step, the Domain Stage (also known as Tessellation Evaluation Shader, TES), which is programmable. This part consists of domain functions, which are executed once per vertex. It receives the barycentric coordinates and the results generated by the two functions in the Patch and Hull Stage. Most of the logic is written here. The most important thing is that you can reposition the vertices in this stage, which is the most important part of tessellation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-105-1024x445.png\" alt=\"\" class=\"wp-image-761 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"445\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-105-1024x445.png\" alt=\"\" class=\"wp-image-761 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-105-1024x445.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-105-300x130.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-105-768x334.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-105.png 1326w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>If there is a geometry shader, it will be executed after the Domain Stage. But if not, it will come to the rasterization stage.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-106-1024x527.png\" alt=\"\" class=\"wp-image-762 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"527\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-106-1024x527.png\" alt=\"\" class=\"wp-image-762 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-106-1024x527.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-106-300x154.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-106-768x395.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-106.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>In summary, the first thing is the vertex shader. The Hull stage accepts vertex data and decides how to subdivide the mesh. Then the tessellator stage processes the subdivided mesh, and finally the Domain stage outputs vertices for the fragment shader.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Surface subdivision analysis<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>This chapter contains code analysis of Unity&#039;s surface subdivision, practical example effects display and an overview of the underlying principles.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">2.1 Key code analysis<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">2.1.1 Basic settings of Unity tessellation<\/h3>\n\n\n\n<p>First of all, the tessellation shader needs to use shader target 5.0.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"HLSLPROGRAM#pragma target 5.0 \/\/ 5.0 required for tessellation#pragma vertex Vertex#pragma hull Hull#pragma domain Domain#pragma fragment FragmentENDHLSL\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">HLSLPROGRAM<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">Pragmas<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">target<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">5.0<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ 5.0 required for tessellation<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">Pragmas<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">vertex<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Vertex<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">Pragmas<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">hull<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Hull<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">Pragmas<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">domain<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Domain<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">Pragmas<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">fragment<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Fragment<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">ENDHLSL<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">2.1.2 Hull Stage Code 1 \u2013 Hull Function<\/h3>\n\n\n\n<p>In the classic process, the vertex shader converts the position and normal information into world space. Then the output result is passed to the Hull Stage. It should be noted that, unlike the vertex shader, the vertices of the Hull shader are represented by INTERNALTESSPOS semantics instead of POSITION semantics. The reason is that Hull does not need to output these vertex positions to the next rendering process, but for its own internal tessellation algorithm, so it will convert these vertices to a coordinate system that is more suitable for tessellation. In addition, developers can also distinguish more clearly.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"struct Attributes {    float3 positionOS : POSITION;    float3 normalOS : NORMAL;    UNITY_VERTEX_INPUT_INSTANCE_ID};struct TessellationControlPoint {    float3 positionWS : INTERNALTESSPOS;    float3 normalWS : NORMAL;    UNITY_VERTEX_INPUT_INSTANCE_ID};TessellationControlPoint Vertex(Attributes input) {    TessellationControlPoint output;    UNITY_SETUP_INSTANCE_ID(input);    UNITY_TRANSFER_INSTANCE_ID(input, output);    VertexPositionInputs posnInputs = GetVertexPositionInputs(input.positionOS);    VertexNormalInputs normalInputs = GetVertexNormalInputs(input.normalOS);    output.positionWS = posnInputs.positionWS;    output.normalWS = normalInputs.normalWS;    return output;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Attributes<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> positionOS <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">POSITION<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> normalOS <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">NORMAL<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">UNITY_VERTEX_INPUT_INSTANCE_ID<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> positionWS <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">INTERNAL LTESS POS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> normalWS <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">NORMAL<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">UNITY_VERTEX_INPUT_INSTANCE_ID<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Vertex<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">Attributes<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">UNITY_SETUP_INSTANCE_ID<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">UNITY_TRANSFER_INSTANCE_ID<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">VertexPositionInputs<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">posnInputs<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">GetVertexPositionInputs<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionOS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">VertexNormalInputs<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalInputs<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">GetVertexNormalInputs<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalOS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">posnInputs<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalInputs<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Below are some setting parameters for the Hull Shader.<\/p>\n\n\n\n<p>The first line, domain, defines the domain type of the tessellation shader, which means that both the input and output are triangle primitives. You can choose tri (triangle), quad (quadrilateral), etc.<\/p>\n\n\n\n<p>The second line outputcontrolpoints indicates the number of output control points, 3 corresponds to the three vertices of the triangle.<\/p>\n\n\n\n<p>The third line outputtopology indicates the topological structure of the primitive after subdivision. triangle_cw means that the vertices of the output triangle are sorted clockwise. The correct order can ensure that the surface faces outward. triangle_cw (clockwise around the triangle), triangle_ccw (counterclockwise around the triangle), line (line segment)<\/p>\n\n\n\n<p>The fourth line patchconstantfunc is another function of the Hull Stage, which outputs constant data such as subdivision factors. A patch is executed only once.<\/p>\n\n\n\n<p>The fifth line, partitioning, specifies how to distribute additional vertices to the edges of the original Path primitive. This step can make the subdivision process smoother and more uniform. integer, fractional_even, fractional_odd.<\/p>\n\n\n\n<p>The maxtessfactor in the sixth line represents the maximum subdivision factor. Limiting the maximum subdivision can control the rendering burden.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"[domain(&quot;tri&quot;)][outputcontrolpoints(3)][outputtopology(&quot;triangle_cw&quot;)][patchconstantfunc(&quot;patchconstant&quot;)][partitioning(&quot;fractional_even&quot;)][maxtessfactor(64.0)]\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">tri<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">outputcontrolpoints<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">outputtopology<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">triangle_cw<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">patchconstantfunc<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">patchconstant<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">partitioning<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">fractional_even<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">maxtessfactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">64.0<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>In the Hull Shader, each control point will be called once independently, so this function will be executed the same number of control points. To know which vertex is currently being processed, we use the variable id with the semantics of SV_OutputControlPointID to determine. The function also passes in a special structure that can be used to easily access any control point in the Patch like an array.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"TessellationControlPoint Hull(    InputPatch<TessellationControlPoint, 3&gt; patch, uint id : SV_OutputControlPointID) {    TessellationControlPoint h;    \/\/ Hull shader code here    return patch[id];}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Hull<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">InputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">uint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_OutputControlPointID<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">h<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Hull shader code here<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">2.1.3 Hull Stage Code 2 \u2013 Patch Constant Function<\/h3>\n\n\n\n<p>In addition to the Hull Shader, there is another function in the Hull Stage that runs in parallel, the patch constant function. The signature of this function is relatively simple. It inputs a patch and outputs the calculated subdivision factor. The output structure contains the tessellation factor specified for each edge of the triangle. These factors are identified by the special system value semantics SV_TessFactor. Each tessellation factor defines how many small segments the corresponding edge should be subdivided into, thereby affecting the density and details of the resulting mesh. Let&#039;s take a closer look at what this factor specifically contains.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"struct TessellationFactors {    float edge[3] : SV_TessFactor;    float inside : SV_InsideTessFactor;};\/\/ The patch constant function runs once per triangle, or &quot;patch&quot;\/\/ It runs in parallel to the hull functionTessellationFactors PatchConstantFunction(    InputPatch<TessellationControlPoint, 3&gt; patch) {    UNITY_SETUP_INSTANCE_ID(patch[0]); \/\/ Set up instancing    \/\/ Calculate tessellation factors    TessellationFactors f;    f.edge[0] = _FactorEdge1.x;    f.edge[1] = _FactorEdge1.y;    f.edge[2] = _FactorEdge1.z;    f.inside = _FactorInside;    return f;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\">] : <\/span><span style=\"color: #D8DEE9\">SV_TessFactor<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> inside <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">SV_InsideTessFactor<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ The patch constant function runs once per triangle, or &quot;patch&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ It runs in parallel to the hull function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PatchConstantFunction<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">InputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">UNITY_SETUP_INSTANCE_ID<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">])<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ Set up instancing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/Calculate tessellation factors<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">inside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorInside<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>First, there is an edge tessellation factor edge[3] in the TessellationFactors structure, marked as SV_TessFactor. When using triangles as the basic primitives for tessellation, each edge is defined as being located relative to the vertex with the same index. Specifically: edge 0 corresponds to vertex 1 and vertex 2. Edge 1 corresponds to vertex 2 and vertex 0. Edge 2 corresponds to vertex 0 and vertex 1. Why is this so? The intuitive explanation is that the index of the edge is the same as the index of the vertex it is not connected to. This helps to quickly identify and process the edges corresponding to specific vertices when writing shader code.<\/p>\n\n\n\n<p>There is also a center tessellation factor inside labeled SV_InsideTessFactor. This factor directly changes the final tessellation pattern, and more essentially determines the number of edge subdivisions, which is used to control the subdivision density inside the triangle. Compared with the edge subdivision factor, the center tessellation factor controls how the inside of the triangle is further subdivided into smaller triangles, while the edge tessellation factor affects the number of edge subdivisions.<\/p>\n\n\n\n<p>Patch Constant Function can also output other useful data, but it must be labeled with the correct semantics. For example, BEZIERPOS semantics is very useful and can represent float3 data. This semantics will be used later to output the control points of the smoothing algorithm based on the Bezier curve.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.1.4 Domain Stage Code<\/h3>\n\n\n\n<p>Next, we enter the Domain Stage. The Domain Function also has a Domain property, which should be the same as the output topology type of the Hull Function. In this example, it is set to a triangle. This function inputs the patch from the Hull Function, the output of the Patch Constant Function, and the most important vertex barycentric coordinates. The output structure is very similar to the output structure of the vertex shader, containing the position of the Clip space, as well as the lighting data required by the fragment shader.<\/p>\n\n\n\n<p>It doesn\u2019t matter if you don\u2019t know what it is for now. Just read Chapter 4 of this article and then come back to study it.<\/p>\n\n\n\n<p>Simply put, each new vertex that is subdivided will run this domain function.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"struct Interpolators {    float3 normalWS                 : TEXCOORD0;    float3 positionWS               : TEXCOORD1;    float4 positionCS               : SV_POSITION;};\/\/ Call this macro to interpolate between a triangle patch, passing the field name#define BARYCENTRIC_INTERPOLATE(fieldName) \\        patch[0].fieldName * barycentricCoordinates.x + \\        patch[1].fieldName * barycentricCoordinates.y + \\        patch[2].fieldName * barycentricCoordinates.z\/\/ The domain function runs once per vertex in the final, tessellated mesh\/\/ Use it to reposition vertices and prepare for the fragment stage[domain(&quot;tri&quot;)] \/\/ Signal we're inputting trianglesInterpolators Domain(    TessellationFactors factors, \/\/ The output of the patch constant function    OutputPatch<TessellationControlPoint, 3&gt; patch, \/\/ The Input triangle    float3 barycentricCoordinates : SV_DomainLocation) { \/\/ The barycentric coordinates of the vertex on the triangle    Interpolators output;    \/\/ Setup instancing and stereo support (for VR)    UNITY_SETUP_INSTANCE_ID(patch[0]);    UNITY_TRANSFER_INSTANCE_ID(patch[0], output);    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);    float3 positionWS = BARYCENTRIC_INTERPOLATE(positionWS);    float3 normalWS = BARYCENTRIC_INTERPOLATE(normalWS);    output.positionCS = TransformWorldToHClip(positionWS);    output.normalWS = normalWS;    output.positionWS = positionWS;    return output;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> normalWS                 <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TEXCOORD0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> positionWS               <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TEXCOORD1<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> positionCS               <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">SV_POSITION<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Call this macro to interpolate between a triangle patch, passing the field name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">define<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">fieldName<\/span><span style=\"color: #D8DEE9FF\">) \\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">fieldName<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> \\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">fieldName<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> \\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">fieldName<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ The domain function runs once per vertex in the final, tessellated mesh<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Use it to reposition vertices and prepare for the fragment stage<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">tri<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)] <\/span><span style=\"color: #616E88\">\/\/ Signal we&#039;re inputting triangles<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/The output of the patch constant function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">OutputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The Input triangle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DomainLocation<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The barycentric coordinates of the vertex on the triangle<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Setup instancing and stereo support (for VR)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">UNITY_SETUP_INSTANCE_ID<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">])<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">UNITY_TRANSFER_INSTANCE_ID<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">TransformWorldToHClip<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>In this function, Unity will give us the subdivision factor, the three vertices of the patch, and the centroid coordinates of the current new vertex. We can use this data to do displacement processing, etc.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.2 Detailed explanation of subdivision factors and division modes<\/h3>\n\n\n\n<p>From this<a target=\"_blank\" href=\"https:\/\/gist.github.com\/NedMakesGames\/09784830b01e2b7c5f0559e807d48815\" rel=\"noreferrer noopener\">Link <\/a>Copy the code, then make the corresponding material and turn on the wireframe mode. We have only drawn vertices for the Mesh and have not applied any operations in the fragment shader, so it looks transparent.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-107.png\" alt=\"\" class=\"wp-image-763 lazyload\"\/><noscript><img decoding=\"async\" width=\"972\" height=\"632\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-107.png\" alt=\"\" class=\"wp-image-763 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-107.png 972w, https:\/\/remoooo.com\/wp-content\/uploads\/image-107-300x195.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-107-768x499.png 768w\" sizes=\"(max-width: 972px) 100vw, 972px\" \/><\/noscript><\/figure>\n\n\n\n<p>If any component of the Edge Factor is set to 0 or less than 0, the Mesh will disappear completely. The following figure shows what it looks like after it disappears (the Unity editor&#039;s object border stroke is turned on). This feature is very important.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-109.png\" alt=\"\" class=\"wp-image-765 lazyload\"\/><noscript><img decoding=\"async\" width=\"1020\" height=\"660\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-109.png\" alt=\"\" class=\"wp-image-765 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-109.png 1020w, https:\/\/remoooo.com\/wp-content\/uploads\/image-109-300x194.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-109-768x497.png 768w\" sizes=\"(max-width: 1020px) 100vw, 1020px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.1 Overview of subdivision factors<\/h3>\n\n\n\n<p>To put it bluntly, after these factors are set in the Hull Stage, they are simply and crudely written into the barycentric coordinates in the Tessellation Stage, such as edge factors and internal factors. (Assuming they are all tri, if it is quad, it is calculated using uv, which may be more complicated, I don&#039;t know) This simple and crude stage is not programmable.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-113-1024x543.png\" alt=\"\" class=\"wp-image-769 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"543\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-113-1024x543.png\" alt=\"\" class=\"wp-image-769 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-113-1024x543.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-113-300x159.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-113-768x407.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-113.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Take &quot;integer (uniform) cutting mode&quot; as an example. (temporarily) [partitioning(&quot;integer&quot;)] The domain is all triangles [domain(&quot;tri&quot;)] The number of output vertices is also 3. [outputcontrolpoints(3)] And the output topology is a triangle clockwise. [outputtopology(&quot;triangle_cw&quot;)]<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.2 Preparatory work and potential parallel issues<\/h3>\n\n\n\n<p>Modify the code to the following:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ .shader_FactorEdge1(&quot;[Float3]Edge factors,[Float]Inside factor&quot;, Vector) = (1, 1, 1, 1) \/\/ --  Edited  -- \/\/ .hlslfloat4 _FactorEdge1; \/\/ --  Edited  -- ...f.edge[0] = _FactorEdge1.x;f.edge[1] = _FactorEdge1.y; \/\/ --  Edited  -- f.edge[2] = _FactorEdge1.z; \/\/ --  Edited  -- f.inside = _FactorEdge1.w; \/\/ --  Edited  --\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ .shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">_FactorEdge1<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">[Float3]Edge factors,[Float]Inside factor<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Vector<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ .hlsl<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">inside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited --<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-112.png\" alt=\"\" class=\"wp-image-768 lazyload\"\/><noscript><img decoding=\"async\" width=\"630\" height=\"140\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-112.png\" alt=\"\" class=\"wp-image-768 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-112.png 630w, https:\/\/remoooo.com\/wp-content\/uploads\/image-112-300x67.png 300w\" sizes=\"(max-width: 630px) 100vw, 630px\" \/><\/noscript><\/figure>\n\n\n\n<p>There may be a problem here. Sometimes the compiler will split the Patch Constant Function and calculate each factor in parallel, which may cause some factors to be deleted, and the factors may be inexplicably equal to 0. The solution is to pack these factors into a vector so that the compiler will not use undefined quantities. The following is a simple reproduction of what may happen.<\/p>\n\n\n\n<p>Modify the Path Constant Function as follows and open two new properties in the panel.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The modified code lines are commented out with \/\/ \u2014 Edited \u2014 .<\/p>\n<\/blockquote>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ The patch constant function runs once per triangle, or &quot;patch&quot;\/\/ It runs in parallel to the hull functionTessellationFactors PatchConstantFunction(InputPatch<TessellationControlPoint, 3&gt; patch) {UNITY_SETUP_INSTANCE_ID(patch[0]); \/\/ Set up instancing\/\/ Calculate tessellation factors    TessellationFactors f;    f.edge[0] = _FactorEdge1.x;    f.edge[1] = _FactorEdge2; \/\/ --  Edited  --    f.edge[2] = _FactorEdge3; \/\/ --  Edited  --    f.inside = _FactorInside;return f;}_FactorEdge2(&quot;Edge 2 factor&quot;, Float) = 1 \/\/ --  Edited  --_FactorEdge3(&quot;Edge 3 factor&quot;, Float) = 1 \/\/ --  Edited  --\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ The patch constant function runs once per triangle, or &quot;patch&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ It runs in parallel to the hull function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PatchConstantFunction<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">InputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">UNITY_SETUP_INSTANCE_ID<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">])<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ Set up instancing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/Calculate tessellation factors<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge2<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited --<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorEdge3<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited --<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">inside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_FactorInside<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">_FactorEdge2<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Edge 2 factor<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Float<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited --<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">_FactorEdge3<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Edge 3 factor<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Float<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited --<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.3 Edge Factor \u2013 SV_TessFactor<\/h3>\n\n\n\n<p>It can be seen that the edge factors correspond approximately to the number of times the corresponding edge is split, and the internal factor corresponds to the complexity of the center.<\/p>\n\n\n\n<p>The edge factor only affects<strong>Original triangle edge<\/strong>As for the complex internal pattern, it is controlled by the internal factor Inside Factor and the division mode.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>It should be noted that the surface subdivision in &quot;integer cutting mode&quot; is rounded up, for example, 2.1 is rounded up to 3.<\/p>\n<\/blockquote>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-110-1024x694.png\" alt=\"\" class=\"wp-image-766 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"694\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-110-1024x694.png\" alt=\"\" class=\"wp-image-766 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-110-1024x694.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-110-300x203.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-110-768x520.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-110.png 1166w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>One picture says it all.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-111-1024x359.png\" alt=\"\" class=\"wp-image-767 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"359\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-111-1024x359.png\" alt=\"\" class=\"wp-image-767 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-111-1024x359.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-111-300x105.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-111-768x269.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-111.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.4 Inside Factor \u2013 SV_InsideTessFactor<\/h3>\n\n\n\n<p>Let&#039;s take the INTEGER mode as an example. The internal factor will only affect the complexity of the internal pattern. The specific influence is described in detail below.<strong>To summarize, the edge factor affects the triangular subdivision between the outermost layer and the first layer, the internal factor affects how many layers there are, and the division mode affects how each internal layer is subdivided.<\/strong><\/p>\n\n\n\n<p>Assuming that the Edge Factors are set to (2,3,4) and only the Insider Factor is modified, an interesting property can be observed: when the internal factor n is an even number, a vertex can be found whose coordinates are exactly at the centroid position (13,13,13).<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Generally, it is good to set the edge factors to the same value. Here, different values are set, and the graph may be more confusing, but the most essential rules can be seen.<\/p>\n<\/blockquote>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-115-1024x967.png\" alt=\"\" class=\"wp-image-771 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"967\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-115-1024x967.png\" alt=\"\" class=\"wp-image-771 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-115-1024x967.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-115-300x283.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-115-768x725.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-115.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>It can be further observed that the number of vertices on any edge closest to the outermost triangle has an equal relationship with the internal factor Inside Factor (n): n=Numpoint\u22121. That is, the number of vertices on this edge is always equal to the subdivision factor minus 1.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-117-1024x538.png\" alt=\"\" class=\"wp-image-773 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"538\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-117-1024x538.png\" alt=\"\" class=\"wp-image-773 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-117-1024x538.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-117-300x158.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-117-768x404.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-117.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>The number of vertices in each layer decreases by 1. That is, the first layer (not counting the outermost layer, as it will not be subdivided) will have n vertices, the second layer inward will have n\u22122 vertices, and so on.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Combining the above three observations, we can get a guess and conclusion<strong>(It\u2019s useless, but I calculated it when I had nothing to do)<\/strong>The total number of internal vertices can be calculated using the formula, where n corresponds to the internal factor n-1. Note that the internal factor starts at 2: a2n=3n2a2n\u22121=3n(n\u22121)+1. This can be simplified and combined to: ak=\u22120.125(\u22121)k+0.75k2+0.125. The formula for all integer operations is as follows: ak=\u230a\u2212(\u22121)k+6k2+18\u230b<\/p>\n<\/blockquote>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-114-1024x604.png\" alt=\"\" class=\"wp-image-770 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"604\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-114-1024x604.png\" alt=\"\" class=\"wp-image-770 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-114-1024x604.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-114-300x177.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-114-768x453.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-114.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2.2.5 Partitioning Mode \u2013 [partitioning(\u201c_\u201d)]<\/h3>\n\n\n\n<p>The above only describes the simplest way to divide integers evenly, which uses integer multiples for subdivision. Let&#039;s talk about the other methods.<strong>Simply put, Fractional Odd and Fractional Even are advanced versions of Integer, but the former is an advanced version of Integer when it is an odd number, and the latter is an advanced version of Integer when it is an even number. The specific advancement is that the fractional part can be used to make the division no longer equal.<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-116-1024x561.png\" alt=\"\" class=\"wp-image-772 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"561\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-116-1024x561.png\" alt=\"\" class=\"wp-image-772 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-116-1024x561.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-116-300x164.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-116-768x421.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-116.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Fractional Odd: Inside Factor can be a fraction (not Ceil), and the denominator is an odd number. Note that the denominator here is actually the denominator represented by the barycentric coordinates of each vertex. The division method with an odd number as the denominator will definitely make a vertex fall on the barycentric coordinates of the triangle, while an even number will not.<a target=\"_blank\" href=\"https:\/\/www.zhihu.com\/people\/ecidevilin\" rel=\"noreferrer noopener\">Kaios<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-1.gif\" alt=\"\" class=\"wp-image-774 lazyload\"\/><noscript><img decoding=\"async\" width=\"200\" height=\"128\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-1.gif\" alt=\"\" class=\"wp-image-774 lazyload\"\/><\/noscript><figcaption class=\"wp-element-caption\">Gif<\/figcaption><\/figure>\n\n\n\n<p>Fractional Even: Similar to fractional_odd, but with an even denominator. I&#039;m not sure how to choose this.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-2.gif\" alt=\"\" class=\"wp-image-775 lazyload\"\/><noscript><img decoding=\"async\" width=\"200\" height=\"128\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-2.gif\" alt=\"\" class=\"wp-image-775 lazyload\"\/><\/noscript><figcaption class=\"wp-element-caption\">Gif<\/figcaption><\/figure>\n\n\n\n<p>Pow2 (power of 2): This mode only allows the use of powers of 2 (such as 1, 2, 4, 8, etc.) as subdivision levels. Generally used for texture mapping or shadow calculations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Segment Optimization<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">3.1 View Frustum Culling<\/h3>\n\n\n\n<p>Generating so many vertices will result in very bad performance! Therefore, some methods are needed to improve rendering efficiency. Although vertices outside the frustum will be culled before T rasterization, if unnecessary patches are culled in advance in TCS, the calculation pressure of the tessellation shader will be reduced.<\/p>\n\n\n\n<p>If the tessellation factor is set to 0 in the Patch Constant Function, the tessellation generator will ignore the patch, which means that the culling here is for the entire patch, rather than the vertex-by-vertex culling in the frustum culling.<\/p>\n\n\n\n<p>We test every point in the patch to see if they are out of view. To do this, transform every point in the patch into clip space. So we need to calculate the clip space coordinates of each point in the vertex shader and pass it to the Hull Stage. Use GetVertexPositionInputs to get what we want.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"struct TessellationControlPoint {    float4 positionCS : SV_POSITION; \/\/ --  Edited  --     ...};TessellationControlPoint Vertex(Attributes input) {    TessellationControlPoint output;    ...    VertexPositionInputs posnInputs = GetVertexPositionInputs(input.positionOS);    ...    output.positionCS = posnInputs.positionCS; \/\/ --  Edited  --     ...    return output;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> positionCS <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">SV_POSITION<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Vertex<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">Attributes<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">VertexPositionInputs<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">posnInputs<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">GetVertexPositionInputs<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionOS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">posnInputs<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Then write a test function above the Patch Constant Function to determine whether to cull the patch. Temporarily pass false here. The function passes in three points in the clipping space.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Returns true if it should be clipped due to frustum or winding cullingbool ShouldClipPatch(float4 p0PositionCS, float4 p1PositionCS, float4 p2PositionCS) {    return false;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if it should be clipped due to frustum or winding culling<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">ShouldClipPatch<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">false;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Then write the IsOutOfBounds function to test whether a point is outside the bounds. The bounds can also be specified, and this method can be used in another function to determine whether a point is outside the view frustum.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Returns true if the point is outside the bounds set by lower and higherbool IsOutOfBounds(float3 p, float3 lower, float3 higher) {    return p.x < lower.x || p.x &gt; higher.x || p.y < lower.y || p.y &gt; higher.y || p.z < lower.z || p.z &gt; higher.z;}\/\/ Returns true if the given vertex is outside the camera fustum and should be culledbool IsPointOutOfFrustum(float4 positionCS) {    float3 culling = positionCS.xyz;    float w = positionCS.w;    \/\/ UNITY_RAW_FAR_CLIP_VALUE is either 0 or 1, depending on graphics API    \/\/ Most use 0, however OpenGL uses 1    float3 lowerBounds = float3(-w, -w, -w * UNITY_RAW_FAR_CLIP_VALUE);    float3 higherBounds = float3(w, w, w);    return IsOutOfBounds(culling, lowerBounds, higherBounds);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if the point is outside the bounds set by lower and higher<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">IsOutOfBounds<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">lower<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">higher<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">lower<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">||<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">higher<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">||<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">lower<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">||<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">higher<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">||<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">lower<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">||<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">higher<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if the given vertex is outside the camera fustum and should be culled<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">culling<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ UNITY_RAW_FAR_CLIP_VALUE is either 0 or 1, depending on graphics API<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Most use 0, however OpenGL uses 1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">lowerBounds<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float3<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">UNITY_RAW_FAR_CLIP_VALUE<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">higherBounds<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float3<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">IsOutOfBounds<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">culling<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">lowerBounds<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">higherBounds<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>In Clip Space, the W component is the secondary coordinate that determines whether a point is in the view frustum. If xyz is outside the range [-w, w], these points will be culled because they are outside the view frustum. Different APIs have different<strong>Depth of processing<\/strong>There is a different logic on the , we need to pay attention when we use this component as the boundary. DirectX and Vulkan use the left-handed system, the Clip depth is [0, 1], so UNITY_RAW_FAR_CLIP_VALUE is 0. OpenGL is a right-handed system, the Clip depth range is [-1, 1], and UNITY_RAW_FAR_CLIP_VALUE is 1.<\/p>\n\n\n\n<p>After preparing these, you can determine whether a patch needs to be culled. Go back to the function at the beginning and determine whether all the points of a patch need to be culled.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Returns true if it should be clipped due to frustum or winding cullingbool ShouldClipPatch(float4 p0PositionCS, float4 p1PositionCS, float4 p2PositionCS) {    bool allOutside = IsPointOutOfFrustum(p0PositionCS) &amp;&amp;        IsPointOutOfFrustum(p1PositionCS) &amp;&amp;        IsPointOutOfFrustum(p2PositionCS); \/\/ --  Edited  --     return allOutside; \/\/ --  Edited  -- }\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if it should be clipped due to frustum or winding culling<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">ShouldClipPatch<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">allOutside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">&amp;&amp;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">&amp;&amp;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">allOutside<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">3.2 Backface Culling<\/h3>\n\n\n\n<p>In addition to frustum culling, patches can also undergo backface culling, using the normal vector to determine whether a patch needs to be culled.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-118-1024x576.png\" alt=\"\" class=\"wp-image-776 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-118-1024x576.png\" alt=\"\" class=\"wp-image-776 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-118-1024x576.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-118-300x169.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-118-768x432.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-118.png 1400w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><figcaption class=\"wp-element-caption\">img<\/figcaption><\/figure>\n\n\n\n<p>The normal vector is obtained by taking the cross product of two vectors. Since we are currently in Clip space, we need to do a perspective division to get NDC, which should be in the range of [-1,1]. The reason for converting to NDC is that the position in Clip space is nonlinear, which may cause the position of the vertex to be distorted. Converting to a linear space like NDC can more accurately determine the front and back relationship of the vertices.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Returns true if the points in this triangle are wound counter-clockwisebool ShouldBackFaceCull(float4 p0PositionCS, float4 p1PositionCS, float4 p2PositionCS) {    float3 point0 = p0PositionCS.xyz \/ p0PositionCS.w;    float3 point1 = p1PositionCS.xyz \/ p1PositionCS.w;    float3 point2 = p2PositionCS.xyz \/ p2PositionCS.w;    float3 normal = cross(point1 - point0, point2 - point0);    return dot(normal, float3(0, 0, 1)) < 0;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if the points in this triangle are wound counter-clockwise<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">ShouldBackFaceCull<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normal<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">cross<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">point1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">dot<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">normal<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float3<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The above code still has a cross-platform problem. The viewing direction is different in different APIs, so modify the code.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ In clip space, the view direction is float3(0, 0, 1), so we can just test the z coord#if UNITY_REVERSED_Z    return cross(point1 - point0, point2 - point0).z < 0;#else \/\/ In OpenGL, the test is reversed    return cross(point1 - point0, point2 - point0).z &gt; 0;#endif\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ In clip space, the view direction is float3(0, 0, 1), so we can just test the z coord<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">UNITY_REVERSED_Z<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">cross<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">point1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #81A1C1\">else<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ In OpenGL, the test is reversed<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">cross<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">point1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">endif<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Finally, add the function you just wrote to ShouldClipPatch to determine backface culling.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Returns true if it should be clipped due to frustum or winding cullingbool ShouldClipPatch(float4 p0PositionCS, float4 p1PositionCS, float4 p2PositionCS) {    bool allOutside = IsPointOutOfFrustum(p0PositionCS) &amp;&amp;        IsPointOutOfFrustum(p1PositionCS) &amp;&amp;        IsPointOutOfFrustum(p2PositionCS);    return allOutside || ShouldBackFaceCull(p0PositionCS, p1PositionCS, p2PositionCS); \/\/ --  Edited  -- }\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if it should be clipped due to frustum or winding culling<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">ShouldClipPatch<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">allOutside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">&amp;&amp;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">&amp;&amp;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">allOutside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">||<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">ShouldBackFaceCull<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Then set the vertex factor of the patch to be culled to 0 in PatchConstantFunction.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"...if (ShouldClipPatch(patch[0].positionCS, patch[1].positionCS, patch[2].positionCS)) {        f.edge[0] = f.edge[1] = f.edge[2] = f.inside = 0; \/\/ Cull the patch}...\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #88C0D0\">ShouldClipPatch<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">inside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ Cull the patch<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">...<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">3.3 Increase Tolerance<\/h3>\n\n\n\n<p>You may want to verify the correctness of the code, or there may be some unexpected exclusions. In this case, adding a tolerance is a flexible approach.<\/p>\n\n\n\n<p>The first is the frustum culling tolerance. If the tolerance is positive, the culling boundaries will be expanded so that some objects near the edge of the frustum will not be culled even if they are partially out of bounds. This method can reduce the frequent changes in culling state due to small perspective changes or object dynamics.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Returns true if the given vertex is outside the camera fustum and should be culledbool IsPointOutOfFrustum(float4 positionCS, float tolerance) {    float3 culling = positionCS.xyz;    float w = positionCS.w;    \/\/ UNITY_RAW_FAR_CLIP_VALUE is either 0 or 1, depending on graphics API    \/\/ Most use 0, however OpenGL uses 1    float3 lowerBounds = float3(-w - tolerance, -w - tolerance, -w * UNITY_RAW_FAR_CLIP_VALUE - tolerance);    float3 higherBounds = float3(w + tolerance, w + tolerance, w + tolerance);    return IsOutOfBounds(culling, lowerBounds, higherBounds);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if the given vertex is outside the camera fustum and should be culled<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">culling<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ UNITY_RAW_FAR_CLIP_VALUE is either 0 or 1, depending on graphics API<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Most use 0, however OpenGL uses 1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">lowerBounds<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float3<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">UNITY_RAW_FAR_CLIP_VALUE<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">higherBounds<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float3<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">IsOutOfBounds<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">culling<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">lowerBounds<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">higherBounds<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Next, backface culling is adjusted. In practice, this is done by comparing to a tolerance instead of zero to avoid issues with numerical precision. If the dot product result is less than some small positive value (the tolerance) instead of being strictly less than zero, then the primitive is considered a backface. This approach provides an additional buffer, ensuring that only explicitly backface primitives are culled.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Returns true if the points in this triangle are wound counter-clockwisebool ShouldBackFaceCull(float4 p0PositionCS, float4 p1PositionCS, float4 p2PositionCS, float tolerance) {    float3 point0 = p0PositionCS.xyz \/ p0PositionCS.w;    float3 point1 = p1PositionCS.xyz \/ p1PositionCS.w;    float3 point2 = p2PositionCS.xyz \/ p2PositionCS.w;    \/\/ In clip space, the view direction is float3(0, 0, 1), so we can just test the z coord#if UNITY_REVERSED_Z    return cross(point1 - point0, point2 - point0).z < -tolerance;#else \/\/ In OpenGL, the test is reversed    return cross(point1 - point0, point2 - point0).z &gt; tolerance;#endif}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if the points in this triangle are wound counter-clockwise<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">ShouldBackFaceCull<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ In clip space, the view direction is float3(0, 0, 1), so we can just test the z coord<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">UNITY_REVERSED_Z<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">cross<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">point1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #81A1C1\">else<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ In OpenGL, the test is reversed<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">cross<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">point1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">point0<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tolerance<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">endif<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>It is possible to expose a Range in the Material Panel.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ .shaderProperties{    _tolerance(&quot;_tolerance&quot;,Range(-0.002,0.001)) = 0    ...}\/\/ .hlslfloat _tolerance;...\/\/ Returns true if it should be clipped due to frustum or winding cullingbool ShouldClipPatch(float4 p0PositionCS, float4 p1PositionCS, float4 p2PositionCS) {    bool allOutside = IsPointOutOfFrustum(p0PositionCS, _tolerance) &amp;&amp;        IsPointOutOfFrustum(p1PositionCS, _tolerance) &amp;&amp;        IsPointOutOfFrustum(p2PositionCS, _tolerance); \/\/ --  Edited  --     return allOutside || ShouldBackFaceCull(p0PositionCS, p1PositionCS, p2PositionCS,_tolerance); \/\/ --  Edited  -- }\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ .shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">Properties<\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">_tolerance<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">_tolerance<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #88C0D0\">Range<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #B48EAD\">0.002<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">0.001<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ .hlsl<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_tolerance<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Returns true if it should be clipped due to frustum or winding culling<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">ShouldClipPatch<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bool<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">allOutside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_tolerance<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">&amp;&amp;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_tolerance<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">&amp;&amp;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">IsPointOutOfFrustum<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_tolerance<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">allOutside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">||<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">ShouldBackFaceCull<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9\">_tolerance<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ -- Edited -- <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-120.png\" alt=\"\" class=\"wp-image-778 lazyload\"\/><noscript><img decoding=\"async\" width=\"994\" height=\"434\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-120.png\" alt=\"\" class=\"wp-image-778 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-120.png 994w, https:\/\/remoooo.com\/wp-content\/uploads\/image-120-300x131.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-120-768x335.png 768w\" sizes=\"(max-width: 994px) 100vw, 994px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">3.4 Dynamic subdivision factor<\/h3>\n\n\n\n<p>So far, our algorithm has subdivided all surfaces indiscriminately. However, in a complex Mesh, there may be large and small faces.<strong>Uneven Mesh Area<\/strong>The large face is more obvious visually due to its large area, and more subdivisions are needed to ensure the smoothness and details of the surface. The small face is small in area, so you can consider reducing the subdivision level of this part, which will not have a big impact on the visual effect. Dynamically changing the factor according to the length change is a common method. Set an algorithm to give faces with longer side lengths a higher subdivision factor.<\/p>\n\n\n\n<p>In addition to the large and small faces of the Mesh itself,<strong>The distance between the camera and the patch<\/strong>It can also be used as a factor to dynamically change the factor. Objects that are farther away from the camera can have a lower tessellation factor because they occupy fewer pixels on the screen.<strong>The user\u2019s viewing angle and gaze direction<\/strong>, you can prioritize subdividing faces that face the camera, and reduce the level of subdivision for faces that face away from the camera or to the sides.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.4.1 Fixed Segment Scaling<\/h3>\n\n\n\n<p>Get the distance between two vertices. The larger the distance, the larger the subdivision factor. The scale is exposed in the control panel and set to [0,1]. When the scale is 1, the subdivision factor is directly contributed by the distance between the two points. The closer the scale is to 0, the larger the subdivision factor. In addition, an initial value bias is added. Finally, let it take a number of 1 or above to ensure accuracy.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Calculate the tessellation factor for an edgefloat EdgeTessellationFactor(float scale, float bias, float3 p0PositionWS, float3 p1PositionWS) {    float factor = distance(p0PositionWS, p1PositionWS) \/ scale;    return max(1, factor + bias);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/Calculate the tessellation factor for an edge<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">scale<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factor<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">distance<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">scale<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">max<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factor<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bias<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Then modify the material panel and Patch Constant Function. Generally speaking, the average value of the edge subdivision factor is used as the internal subdivision factor, which will give a more consistent visual effect.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ .shaderProperties{    ...    _TessellationBias(&quot;_TessellationBias&quot;, Range(-1,5)) = 1     _TessellationFactor(&quot;_TessellationFactor&quot;, Range(0,1)) = 0}\/\/ .hlslf.edge[0] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[1].positionWS, patch[2].positionWS);f.edge[1] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[2].positionWS, patch[0].positionWS);f.edge[2] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[0].positionWS, patch[1].positionWS);f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) \/ 3.0;\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ .shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">Properties<\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">_TessellationBias<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Range<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">5<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">     <\/span><span style=\"color: #88C0D0\">_TessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Range<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ .hlsl<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">inside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The degree of subdivision of fragments of different sizes will change dynamically, and the effect is as follows.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-119-1024x520.png\" alt=\"\" class=\"wp-image-777 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"520\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-119-1024x520.png\" alt=\"\" class=\"wp-image-777 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-119-1024x520.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-119-300x152.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-119-768x390.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-119.png 1240w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>By the way, if you find that your internal factor pattern is very strange, this may be caused by the compiler. Try to modify the internal factor code to the following to solve it.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"f.inside = ( \/\/ If the compiler doesn't play nice...  EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[1].positionWS, patch[2].positionWS) +   EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[2].positionWS, patch[0].positionWS) +   EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[0].positionWS, patch[1].positionWS)  ) \/ 3.0;\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">inside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> ( <\/span><span style=\"color: #616E88\">\/\/ If the compiler doesn&#039;t play nice...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  ) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">3.4.2 Screen Space Subdivision Scaling<\/h3>\n\n\n\n<p>Next, we need to determine the camera distance. We can directly<strong>Use screen space distance to adjust the subdivision level<\/strong>, which perfectly solves the problem of large and small surfaces + screen distance at the same time!<\/p>\n\n\n\n<p>Since we already have the data in Clip space, and since screen space is very similar to NDC space, we only need to convert it to NDC, that is, do a perspective division.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"float EdgeTessellationFactor(float scale, float bias, float3 p0PositionWS, float4 p0PositionCS, float3 p1PositionWS, float4 p1PositionCS) {    float factor = distance(p0PositionCS.xyz \/ p0PositionCS.w, p1PositionCS.xyz \/ p1PositionCS.w) \/ scale;    return max(1, factor + bias);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">scale<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factor<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">distance<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">scale<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">max<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factor<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bias<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Next, pass the Clip space coordinates into the Patch Constant Function.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"f.edge[0] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias,   patch[1].positionWS, patch[1].positionCS, patch[2].positionWS, patch[2].positionCS);f.edge[1] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias,   patch[2].positionWS, patch[2].positionCS, patch[0].positionWS, patch[0].positionCS);f.edge[2] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias,   patch[0].positionWS, patch[0].positionCS, patch[1].positionWS, patch[1].positionCS);f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) \/ 3.0;\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">inside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The current effect is quite good, and the level of subdivision changes dynamically as the camera distance (screen space distance) changes. If you use a subdivision mode other than INTEGER, you will get a more consistent effect.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-122-1024x482.png\" alt=\"\" class=\"wp-image-780 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"482\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-122-1024x482.png\" alt=\"\" class=\"wp-image-780 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-122-1024x482.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-122-300x141.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-122-768x362.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-122.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>There are still some areas that can be improved. For example, the unit of the scaling factor. Just now we controlled it to [0,1], which is not very suitable for us to adjust. We multiply it by the screen resolution and change the scaling factor range to [0,1080], which is more convenient for us to adjust. Then modify the material panel properties. Now it is a ratio in pixels.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ .hlslfloat factor = distance(p0PositionCS.xyz \/ p0PositionCS.w, p1PositionCS.xyz \/ p1PositionCS.w) * _ScreenParams.y \/ scale;\/\/ .shader_TessellationFactor(&quot;_TessellationFactor&quot;,Range(0,1080)) = 320\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ .hlsl<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factor<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">distance<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionCS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_ScreenParams<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">scale<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ .shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">_TessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #88C0D0\">Range<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1080<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">320<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-121-1024x664.png\" alt=\"\" class=\"wp-image-779 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"664\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-121-1024x664.png\" alt=\"\" class=\"wp-image-779 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-121-1024x664.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-121-300x195.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-121-768x498.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-121.png 1400w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">3.4.3 Camera distance subdivision scaling<\/h3>\n\n\n\n<p>How do we use camera distance scaling? It&#039;s very simple. We calculate the ratio of the distance between two points and the distance between the midpoint of the two vertices and the camera position. The larger the ratio, the larger the space occupied on the screen, and the more subdivision is needed.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ .hlslfloat EdgeTessellationFactor(float scale, float bias, float3 p0PositionWS, float3 p1PositionWS) {    float length = distance(p0PositionWS, p1PositionWS);    float distanceToCamera = distance(GetCameraPositionWS(), (p0PositionWS + p1PositionWS) * 0.5);    float factor = length \/ (scale * distanceToCamera * distanceToCamera);    return max(1, factor + bias);}...        f.edge[0] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[1].positionWS, patch[2].positionWS);        f.edge[1] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[2].positionWS, patch[0].positionWS);        f.edge[2] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias, patch[0].positionWS, patch[1].positionWS);\/\/ .shader_TessellationFactor(&quot;_TessellationFactor&quot;,Range(0, 1)) = 0.02\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ .hlsl<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">scale<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">length<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">distance<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">distanceToCamera<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">distance<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #88C0D0\">GetCameraPositionWS<\/span><span style=\"color: #D8DEE9FF\">()<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0.5<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factor<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">length<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">scale<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">distanceToCamera<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">distanceToCamera<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">max<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factor<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bias<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ .shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">_TessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #88C0D0\">Range<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0.02<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Note that the scaling factor is no longer in pixels, but in the original [0,1] unit. Because screen pixels are not very meaningful in this method, they are not used. And the world coordinates are used again.<\/p>\n\n\n\n<p>The results of screen space subdivision scaling and camera distance subdivision scaling are similar. Generally, a macro can be opened to switch the modes of the above dynamic factors. Here, it is left to the reader to complete.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.5 Specifying subdivision factors<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">3.5.1 Vertex Storage Subdivision Factor<\/h3>\n\n\n\n<p>In the previous section, we used different strategies to guess the appropriate subdivision factors. If we know exactly how the mesh should be subdivided, we can store the coefficients of these subdivision factors in the mesh. Since the coefficient only needs a float, only one color channel is needed. The following is a pseudo code, just give it a try.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"float EdgeTessellationFactor(float scale, float bias, float multiplier) {    ...    return max(1, (factor + bias) * multiplier);}...\/\/ PCF()[unroll] for (int i = 0; i < 3; i++) {    multipliers[i] = patch[i].color.g;}\/\/ Calculate tessellation factorsf.edge[0] = EdgeTessellationFactor(_TessellationFactor, _TessellationBias, (multipliers[1] + multipliers[2]) \/ 2);\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">scale<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multiplier<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">max<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">factor<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bias<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multiplier<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ PCF()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">unroll<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">for<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #81A1C1\">++<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">color<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">g<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/Calculate tessellation factors<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">EdgeTessellationFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_TessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationBias<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-123-1024x581.png\" alt=\"\" class=\"wp-image-781 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"581\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-123-1024x581.png\" alt=\"\" class=\"wp-image-781 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-123-1024x581.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-123-300x170.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-123-768x435.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-123.png 1210w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">3.5.2 SDF Control Surface Subdivision Factor<\/h3>\n\n\n\n<p>It is quite cool to combine the Signed Distance Field (SDF) to control the tessellation factor. Of course, this section does not involve the generation of SDF, assuming that it can be directly obtained through the ready-made function CalculateSDFDistance.<\/p>\n\n\n\n<p>For a given Mesh, use CalculateSDFDistance to calculate the distance from each vertex in each patch to the shape represented by the SDF (such as a sphere). After obtaining the distance, evaluate the subdivision requirements of the patch and perform subdivision.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"TessellationFactors PatchConstantFunction(    InputPatch<TessellationControlPoint, 3&gt; patch) {    float multipliers[3];    \/\/ \u5faa\u73af\u5904\u7406\u6bcf\u4e2a\u9876\u70b9    [unroll] for (int i = 0; i < 3; i++) {        \/\/ \u8ba1\u7b97\u6bcf\u4e2a\u9876\u70b9\u5230SDF\u8868\u9762\u7684\u8ddd\u79bb        float sdfDistance = CalculateSDFDistance(patch[i].positionWS);        \/\/ \u6839\u636eSDF\u8ddd\u79bb\u8c03\u6574\u7ec6\u5206\u56e0\u5b50        if (sdfDistance < _TessellationDistanceThreshold) {            multipliers[i] = lerp(_MinTessellationFactor, _MaxTessellationFactor, (1 - sdfDistance \/ _TessellationDistanceThreshold));        } else {            multipliers[i] = _MinTessellationFactor;        }    }    \/\/ \u8ba1\u7b97\u6700\u7ec8\u7684\u7ec6\u5206\u56e0\u5b50    TessellationFactors f;    f.Edge[0] = max(multipliers[0], multipliers[1]);    f.Edge[1] = max(multipliers[1], multipliers[2]);    f.Edge[2] = max(multipliers[2], multipliers[0]);    f.Inside = (multipliers[0] + multipliers[1] + multipliers[2]) \/ 3;    return f;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PatchConstantFunction<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">InputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Loop through each vertex<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    [<\/span><span style=\"color: #D8DEE9\">unroll<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">for<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #81A1C1\">++<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Calculate the distance from each vertex to the SDF surface<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">sdfDistance<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateSDFDistance<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Adjust subdivision factor based on SDF distance<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">sdfDistance<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationDistanceThreshold<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">lerp<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">_MinTessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_MaxTessellationFactor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">sdfDistance<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationDistanceThreshold<\/span><span style=\"color: #D8DEE9FF\">))<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">else<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_MinTessellationFactor<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Calculate the final subdivision factor<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">Edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">max<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">])<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">Edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">max<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">])<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">Edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">max<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">])<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">Inside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">multipliers<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>I don&#039;t know how to implement it specifically, so I&#039;ll try to understand it first.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-126-1024x567.png\" alt=\"\" class=\"wp-image-784 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"567\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-126-1024x567.png\" alt=\"\" class=\"wp-image-784 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-126-1024x567.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-126-300x166.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-126-768x425.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-126.png 1166w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">4. Vertex offset \u2013 contour smoothing<\/h2>\n\n\n\n<p>The easiest way to add details to a mesh is to use various high-resolution textures. However, the bottom line is that adding more vertices to a mesh is better than increasing the texture resolution. For example, a normal map can change the direction of each fragment&#039;s normal, but it does not change the geometry. Even a 128K texture cannot eliminate aliasing and pointy edges.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-127-1024x560.png\" alt=\"\" class=\"wp-image-785 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"560\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-127-1024x560.png\" alt=\"\" class=\"wp-image-785 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-127-1024x560.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-127-300x164.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-127-768x420.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-127.png 1072w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Therefore, we need to tessellate the surface and then offset the vertices. All the tessellation operations just mentioned are operated on the plane where the patch is located. If we want to bend these vertices, one of the simplest operations is Phong tessellation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4.1 Phong subdivision<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>First, the original paper is attached. https:\/\/perso.telecom-paristech.fr\/boubek\/papers\/PhongTessellation\/PhongTessellation.pdf<\/p>\n<\/blockquote>\n\n\n\n<p>Phong shading should be familiar to you. It is a technique that uses linear interpolation of normal vectors to obtain smooth shading. Phong subdivision is inspired by Phong shading and extends the concept of Phong shading to the spatial domain.<\/p>\n\n\n\n<p>The core idea of Phong subdivision is to use the vertex normals of each corner of the triangle to affect the position of new vertices during the subdivision process, thereby creating a curved surface instead of a flat surface.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>It is worth noting that many tutorials here use triangle corner to represent vertices. I think they are all the same, so I will still use vertices in this article.<\/p>\n<\/blockquote>\n\n\n\n<p>First, in the Domain function, Unity will give us the centroid coordinates of the new vertex we need to process. Suppose we are currently processing (13,13,13).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-124-1024x543.png\" alt=\"\" class=\"wp-image-782 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"543\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-124-1024x543.png\" alt=\"\" class=\"wp-image-782 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-124-1024x543.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-124-300x159.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-124-768x407.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-124.png 1120w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Each vertex of a patch has a normal. Imagine a tangent plane emanating from each vertex, perpendicular to the respective normal vector.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-125-1024x582.png\" alt=\"\" class=\"wp-image-783 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"582\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-125-1024x582.png\" alt=\"\" class=\"wp-image-783 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-125-1024x582.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-125-300x170.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-125-768x436.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-125.png 1172w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-128-1024x550.png\" alt=\"\" class=\"wp-image-786 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"550\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-128-1024x550.png\" alt=\"\" class=\"wp-image-786 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-128-1024x550.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-128-300x161.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-128-768x412.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-128.png 1166w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Then project the current vertex onto these three tangent planes respectively.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-129-1024x622.png\" alt=\"\" class=\"wp-image-787 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"622\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-129-1024x622.png\" alt=\"\" class=\"wp-image-787 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-129-1024x622.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-129-300x182.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-129-768x466.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-129.png 1044w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Describe it in mathematical language. P\u2032=P\u2212((P\u2212V)\u22c5N)N<\/p>\n\n\n\n<p>in :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>$P$ is the initially interpolated plane position.<\/li>\n\n\n\n<li>$V$ is a vertex position on the plane.<\/li>\n\n\n\n<li>$N$ is the normal at vertex $V$.<\/li>\n\n\n\n<li>\u22c5 represents the dot product.<\/li>\n\n\n\n<li>P\u2032 is the projection of $P$ on the plane.<\/li>\n<\/ul>\n\n\n\n<p>Get three $P&#039;$.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-130-1024x564.png\" alt=\"\" class=\"wp-image-788 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"564\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-130-1024x564.png\" alt=\"\" class=\"wp-image-788 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-130-1024x564.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-130-300x165.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-130-768x423.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-130.png 1260w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-131-1024x600.png\" alt=\"\" class=\"wp-image-789 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"600\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-131-1024x600.png\" alt=\"\" class=\"wp-image-789 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-131-1024x600.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-131-300x176.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-131-768x450.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-131.png 1222w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>The three points projected on the three tangent planes are re-formed into a new triangle, and then the centroid coordinates of the current vertex are applied to the new triangle to calculate the new point.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-132-1024x584.png\" alt=\"\" class=\"wp-image-790 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"584\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-132-1024x584.png\" alt=\"\" class=\"wp-image-790 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-132-1024x584.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-132-300x171.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-132-768x438.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-132.png 1224w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Calculate Phong projection offsetfloat3 PhongProjectedPosition(float3 flatPositionWS, float3 cornerPositionWS, float3 normalWS) {    return flatPositionWS - dot(flatPositionWS - cornerPositionWS, normalWS) * normalWS;}\/\/ Apply Phong smoothingfloat3 CalculatePhongPosition(float3 bary, float3 p0PositionWS, float3 p0NormalWS,    float3 p1PositionWS, float3 p1NormalWS, float3 p2PositionWS, float3 p2NormalWS) {    float3 smoothedPositionWS =        bary.x * PhongProjectedPosition(flatPositionWS, p0PositionWS, p0NormalWS) +        bary.y * PhongProjectedPosition(flatPositionWS, p1PositionWS, p1NormalWS) +        bary.z * PhongProjectedPosition(flatPositionWS, p2PositionWS, p2NormalWS);    return smoothedPositionWS;}\/\/ The domain function runs once per vertex in the final, tessellated mesh\/\/ Use it to reposition vertices and prepare for the fragment stage[domain(&quot;tri&quot;)] \/\/ Signal we're inputting trianglesInterpolators Domain(    TessellationFactors factors, \/\/ The output of the patch constant function    OutputPatch<TessellationControlPoint, 3&gt; patch, \/\/ The Input triangle    float3 barycentricCoordinates : SV_DomainLocation) { \/\/ The barycentric coordinates of the vertex on the triangle    Interpolators output;    ...    float3 positionWS = CalculatePhongPosition(barycentricCoordinates,       patch[0].positionWS, patch[0].normalWS,       patch[1].positionWS, patch[1].normalWS,       patch[2].positionWS, patch[2].normalWS);    float3 normalWS = BARYCENTRIC_INTERPOLATE(normalWS);    float3 tangentWS = BARYCENTRIC_INTERPOLATE(tangentWS.xyz);    ...    output.positionCS = TransformWorldToHClip(positionWS);    output.normalWS = normalWS;    output.positionWS = positionWS;    output.tangentWS = float4(tangentWS, patch[0].tangentWS.w);    ...}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/Calculate Phong projection offset<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">cornerPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">dot<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">cornerPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Apply Phong smoothing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculatePhongPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedPositionWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ The domain function runs once per vertex in the final, tessellated mesh<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Use it to reposition vertices and prepare for the fragment stage<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">tri<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)] <\/span><span style=\"color: #616E88\">\/\/ Signal we&#039;re inputting triangles<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/The output of the patch constant function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">OutputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The Input triangle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DomainLocation<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The barycentric coordinates of the vertex on the triangle<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculatePhongPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionCS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">TransformWorldToHClip<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float4<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Note that we need to add the normal vector here, and then write it into Vertex and Domain. Then write a function to calculate the coordinates of the center of gravity of $P&#039;$.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"struct Attributes {    ...    float4 tangentOS : TANGENT;};struct TessellationControlPoint {    ...    float4 tangentWS : TANGENT;};struct Interpolators {    ...    float4 tangentWS : TANGENT;};TessellationControlPoint Vertex(Attributes input) {    TessellationControlPoint output;    ...    \/\/ .....\u6700\u540e\u4e00\u4e2a\u662f\u7b26\u53f7\u7cfb\u6570    output.tangentWS = float4(normalInputs.tangentWS, input.tangentOS.w); \/\/ tangent.w containts bitangent multiplier}\/\/ Barycentric interpolation as a functionfloat3 BarycentricInterpolate(float3 bary, float3 a, float3 b, float3 c) {    return bary.x * a + bary.y * b + bary.z * c;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Attributes<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> tangentOS <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TANGENT<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> tangentWS <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TANGENT<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> tangentWS <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TANGENT<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Vertex<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">Attributes<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ .....The last one is the symbol coefficient<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float4<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">normalInputs<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">input<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">tangentOS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ tangent.w contains bitangent multiplier<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Barycentric interpolation as a function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BarycentricInterpolate<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">a<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">b<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">c<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">a<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">b<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">c<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-133.png\" alt=\"\" class=\"wp-image-791 lazyload\"\/><noscript><img decoding=\"async\" width=\"1018\" height=\"794\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-133.png\" alt=\"\" class=\"wp-image-791 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-133.png 1018w, https:\/\/remoooo.com\/wp-content\/uploads\/image-133-300x234.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-133-768x599.png 768w\" sizes=\"(max-width: 1018px) 100vw, 1018px\" \/><\/noscript><\/figure>\n\n\n\n<p>In the original Phong subdivision paper, an \u03b1 factor was added to control the degree of curvature. The original author recommends setting this value globally to three-quarters for the best visual effect. Expanding the algorithm with the \u03b1 factor can produce a quadratic Bezier curve, which does not provide an inflection point but is sufficient for practical development.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-135-1024x334.png\" alt=\"\" class=\"wp-image-793 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"334\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-135-1024x334.png\" alt=\"\" class=\"wp-image-793 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-135-1024x334.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-135-300x98.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-135-768x251.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-135.png 1090w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>First, let\u2019s look at the formula in the original paper.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-141-1024x639.png\" alt=\"\" class=\"wp-image-799 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"639\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-141-1024x639.png\" alt=\"\" class=\"wp-image-799 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-141-1024x639.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-141-300x187.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-141-768x479.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-141.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Essentially, it controls the degree of interpolation. A quantitative analysis shows that when \u03b1=0, all vertices are on the original plane, which is equivalent to no displacement. When \u03b1=1, the new vertices are completely dependent on the Phong subdivision bending vertices. Of course, you can also try values less than zero or greater than one, and the effect is also quite interesting. ~~<em>It doesn\u2019t matter if you don\u2019t understand the mathematical formulas in the original text. I will just use a lerp and make a random interpolation.<\/em>~~<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Apply Phong smoothingfloat3 CalculatePhongPosition(float3 bary, float smoothing, float3 p0PositionWS, float3 p0NormalWS,    float3 p1PositionWS, float3 p1NormalWS, float3 p2PositionWS, float3 p2NormalWS) {    float3 flatPositionWS = BarycentricInterpolate(bary, p0PositionWS, p1PositionWS, p2PositionWS);    float3 smoothedPositionWS =        bary.x * PhongProjectedPosition(flatPositionWS, p0PositionWS, p0NormalWS) +        bary.y * PhongProjectedPosition(flatPositionWS, p1PositionWS, p1NormalWS) +        bary.z * PhongProjectedPosition(flatPositionWS, p2PositionWS, p2NormalWS);    return lerp(flatPositionWS, smoothedPositionWS, smoothing);}\/\/ Apply Phong smoothingfloat3 CalculatePhongPosition(float3 bary, float smoothing, float3 p0PositionWS, float3 p0NormalWS,    float3 p1PositionWS, float3 p1NormalWS, float3 p2PositionWS, float3 p2NormalWS) {    float3 flatPositionWS = BarycentricInterpolate(bary, p0PositionWS, p1PositionWS, p2PositionWS);    float3 smoothedPositionWS =        bary.x * PhongProjectedPosition(flatPositionWS, p0PositionWS, p0NormalWS) +        bary.y * PhongProjectedPosition(flatPositionWS, p1PositionWS, p1NormalWS) +        bary.z * PhongProjectedPosition(flatPositionWS, p2PositionWS, p2NormalWS);    return lerp(flatPositionWS, smoothedPositionWS, smoothing);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Apply Phong smoothing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculatePhongPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BarycentricInterpolate<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">lerp<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Apply Phong smoothing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculatePhongPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BarycentricInterpolate<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PhongProjectedPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">lerp<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Don&#039;t forget to expose in the material panel.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ .shader_TessellationSmoothing(&quot;_TessellationSmoothing&quot;, Range(0,1)) = 0.5\/\/ .hlslfloat _TessellationSmoothing;Interpolators Domain( .... ) {    ...    float smoothing = _TessellationSmoothing;    float3 positionWS = CalculatePhongPosition(barycentricCoordinates, smoothing,      patch[0].positionWS, patch[0].normalWS,       patch[1].positionWS, patch[1].normalWS,       patch[2].positionWS, patch[2].normalWS);    ...}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ .shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">_TessellationSmoothing<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">_TessellationSmoothing<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Range<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0.5<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ .hlsl<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationSmoothing<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Domain<\/span><span style=\"color: #D8DEE9FF\">( <\/span><span style=\"color: #81A1C1\">...<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9FF\"> ) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationSmoothing<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculatePhongPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-139-1024x624.png\" alt=\"\" class=\"wp-image-797 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"624\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-139-1024x624.png\" alt=\"\" class=\"wp-image-797 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-139-1024x624.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-139-300x183.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-139-768x468.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-139.png 1440w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>It is important to note that some models require some modification. If the edges of the model are very sharp, it means that the normal of this vertex is almost parallel to the normal of the face. In Phong Tessellation, this will cause the projection of the vertex on the tangent plane to be very close to the original vertex position, thus reducing the impact of subdivision.<\/p>\n\n\n\n<p>To solve this problem, you can add more geometric details by performing what is called &quot;adding loop edges&quot; or &quot;loop cuts&quot; in the modeling software. Insert additional edge loops near the edges of the original model to increase the subdivision density. The specific operation will not be expanded here.<\/p>\n\n\n\n<p>In general, the effect and performance of Phong subdivision are relatively good. However, if you want a higher quality smoothing effect, you can consider PN triangles. This technology is based on the curved triangle of Bezier curve.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4.2 PN triangles subdivision<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>First, here is the original paper. http:\/\/alex.vlachos.com\/graphics\/CurvedPNTriangles.pdf<\/p>\n<\/blockquote>\n\n\n\n<p>PN Triangles does not require information about neighboring triangles and is less expensive. The PN Triangles algorithm only requires the positions and normals of the three vertices in the patch. The rest of the data can be calculated. Note that all data is in barycentric coordinates.<\/p>\n\n\n\n<p>In the PN algorithm, 10 control points need to be calculated for surface subdivision, as shown in the figure below. Three triangle vertices, a centroid, and three pairs of control points on the edges constitute all the control points. The calculated Bezier curve control points will be passed to the Domain. Since the control points of each triangle patch are consistent, it is very appropriate to place the step of calculating the control points in the Patch Constant Function.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-136-1024x606.png\" alt=\"\" class=\"wp-image-794 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"606\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-136-1024x606.png\" alt=\"\" class=\"wp-image-794 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-136-1024x606.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-136-300x177.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-136-768x454.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-136.png 1038w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>The calculation method in the paper is as follows:<\/p>\n\n\n\n<p>$$<br>\\begin{aligned}<br>b_{300} &amp; =P_1 \\<br>b_{030} &amp; =P_2 \\<br>b_{003} &amp; =P_3 \\<br>w_{ij} &amp; =\\left(P_j-P_i\\right) \\cdot N_i \\in \\mathbf{R} \\quad \\text { here &#039; } \\cdot \\text { &#039; is the scalar product, } \\<br>b_{210} &amp; =\\left(2 P_1+P_2-w_{12} N_1\\right) \/ 3 \\<br>b_{120} &amp; =\\left(2 P_2+P_1-w_{21} N_2\\right) \/ 3 \\<br>b_{021} &amp; =\\left(2 P_2+P_3-w_{23} N_2\\right) \/ 3 \\<br>b_{012} &amp; =\\left(2 P_3+P_2-w_{32} N_3\\right) \/ 3 \\<br>b_{102} &amp; =\\left(2 P_3+P_1-w_{31} N_3\\right) \/ 3, \\<br>b_{201} &amp; =\\left(2 P_1+P_3-w_{13} N_1\\right) \/ 3, \\<br>E &amp; =\\left(b_{210}+b_{120}+b_{021}+b_{012}+b_{102}+b_{201}\\right) \/ 6 \\<br>V &amp; =\\left(P_1+P_2+P_3\\right) \/ 3, \\<br>b_{111} &amp; =E+(EV) \/ 2 .<br>\\end{aligned}<br>$$<\/p>\n\n\n\n<p>Each edge of the formula $w_{ij}$ is calculated twice, so a total of 6 times. For example, the meaning of $w_{1 2}$ is the projection length of the vector from $P_1$ to $P_2$ in the normal direction of $P_1$. Multiplying it by the corresponding normal direction means that the projection vector is $w$ in length.<\/p>\n\n\n\n<p>Let&#039;s take the calculation of the factor close to $P_1$ as an example. The weight of the current position point should be larger. Multiplying it by $2$ makes the calculated control point closer to the current vertex. The reason for subtracting the projection vector is to correct the error caused by the position of $P_2$ not being on the plane defined by the $P_1$\u200b\u200b normal. Make the triangle plane more consistent and reduce the distortion effect. Finally, divide by 3 for standardization.<\/p>\n\n\n\n<p>Next, calculate the average Bezier control point $E$\u200b, which represents the average position of the six control points. This average position represents the concentration trend of the boundary control points. Then calculate the average position of the triangle vertices. Then find the midpoint of these two average positions and add it to the Bezier average control point. This is the tenth parameter required in the end.<\/p>\n\n\n\n<p>To summarize, the first three are the positions of the triangle vertices (so they don&#039;t need to be written in the structure), six are calculated by weight, and the last one is the average of the previous calculations. The code is very simple to write.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"struct TessellationFactors {    float edge[3] : SV_TessFactor;    float inside : SV_InsideTessFactor;    float3 bezierPoints[7] : BEZIERPOS;};\/\/Bezier control point calculationsfloat3 CalculateBezierControlPoint(float3 p0PositionWS, float3 aNormalWS, float3 p1PositionWS, float3 bNormalWS) {    float w = dot(p1PositionWS - p0PositionWS, aNormalWS);    return (p0PositionWS * 2 + p1PositionWS - w * aNormalWS) \/ 3.0;}void CalculateBezierControlPoints(inout float3 bezierPoints[7],    float3 p0PositionWS, float3 p0NormalWS, float3 p1PositionWS, float3 p1NormalWS, float3 p2PositionWS, float3 p2NormalWS) {    bezierPoints[0] = CalculateBezierControlPoint(p0PositionWS, p0NormalWS, p1PositionWS, p1NormalWS);    bezierPoints[1] = CalculateBezierControlPoint(p1PositionWS, p1NormalWS, p0PositionWS, p0NormalWS);    bezierPoints[2] = CalculateBezierControlPoint(p1PositionWS, p1NormalWS, p2PositionWS, p2NormalWS);    bezierPoints[3] = CalculateBezierControlPoint(p2PositionWS, p2NormalWS, p1PositionWS, p1NormalWS);    bezierPoints[4] = CalculateBezierControlPoint(p2PositionWS, p2NormalWS, p0PositionWS, p0NormalWS);    bezierPoints[5] = CalculateBezierControlPoint(p0PositionWS, p0NormalWS, p2PositionWS, p2NormalWS);    float3 avgBezier = 0;    [unroll] for (int i = 0; i < 6; i++) {        avgBezier += bezierPoints[i];    }    avgBezier \/= 6.0;    float3 avgControl = (p0PositionWS + p1PositionWS + p2PositionWS) \/ 3.0;    bezierPoints[6] = avgBezier + (avgBezier - avgControl) \/ 2.0;}\/\/ The patch constant function runs once per triangle, or &quot;patch&quot;\/\/ It runs in parallel to the hull functionTessellationFactors PatchConstantFunction(    InputPatch<TessellationControlPoint, 3&gt; patch) {    ...    TessellationFactors f = (TessellationFactors)0;    \/\/ Check if this patch should be culled (it is out of view)    if (ShouldClipPatch(...)) {        ...    } else {        ...        CalculateBezierControlPoints(f.bezierPoints, patch[0].positionWS, patch[0].normalWS,           patch[1].positionWS, patch[1].normalWS, patch[2].positionWS, patch[2].normalWS);    }    return f;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\">] : <\/span><span style=\"color: #D8DEE9\">SV_TessFactor<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> inside <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">SV_InsideTessFactor<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">7<\/span><span style=\"color: #D8DEE9FF\">] : <\/span><span style=\"color: #D8DEE9\">BEZIERPOS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/Bezier control point calculations<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoint<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">aNormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bNormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">dot<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">aNormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">w<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">aNormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoints<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">inout<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">7<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoint<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoint<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoint<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoint<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">4<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoint<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">5<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoint<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">avgBezier<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    [<\/span><span style=\"color: #D8DEE9\">unroll<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">for<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">6<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #81A1C1\">++<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">avgBezier<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">i<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">avgBezier<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">6.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">avgControl<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">6<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">avgBezier<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">avgBezier<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">avgControl<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">2.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ The patch constant function runs once per triangle, or &quot;patch&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ It runs in parallel to the hull function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PatchConstantFunction<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">InputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Check if this patch should be culled (it is out of view)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #88C0D0\">ShouldClipPatch<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #81A1C1\">...<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">else<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoints<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Then, in the domain function, use the ten factors output by the Hull Function. According to the formula given in the paper, calculate the final cubic Bezier surface coordinates. Then interpolate and expose them on the material panel.<\/p>\n\n\n\n<p>$$<br>\\begin{aligned}<br>&amp; b: \\quad R^2 \\mapsto R^3, \\quad \\text { for } w=1-uv, \\quad u, v, w \\geq 0 \\<br>&amp; b(u, v)= \\sum_{i+j+k=3} b_{ijk} \\frac{3!}{i!j!k!} u^iv^jw^k \\<br>&amp;= b_{300} w^3+b_{030} u^3+b_{003} v^3 \\<br>&amp;+b_{210} 3 w^2 u+b_{120} 3 wu^2+b_{201} 3 w^2 v \\<br>&amp;+b_{021} 3 u^2 v+b_{102} 3 wv^2+b_{012} 3 uv^2 \\<br>&amp;+b_{111} 6 wuv .<br>\\end{aligned}<br>$$<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Barycentric interpolation as a functionfloat3 BarycentricInterpolate(float3 bary, float3 a, float3 b, float3 c) {    return bary.x * a + bary.y * b + bary.z * c;}float3 CalculateBezierPosition(float3 bary, float smoothing, float3 bezierPoints[7],    float3 p0PositionWS, float3 p1PositionWS, float3 p2PositionWS) {    float3 flatPositionWS = BarycentricInterpolate(bary, p0PositionWS, p1PositionWS, p2PositionWS);    float3 smoothedPositionWS =        p0PositionWS * (bary.x * bary.x * bary.x) +        p1PositionWS * (bary.y * bary.y * bary.y) +        p2PositionWS * (bary.z * bary.z * bary.z) +        bezierPoints[0] * (3 * bary.x * bary.x * bary.y) +        bezierPoints[1] * (3 * bary.y * bary.y * bary.x) +        bezierPoints[2] * (3 * bary.y * bary.y * bary.z) +        bezierPoints[3] * (3 * bary.z * bary.z * bary.y) +        bezierPoints[4] * (3 * bary.z * bary.z * bary.x) +        bezierPoints[5] * (3 * bary.x * bary.x * bary.z) +        bezierPoints[6] * (6 * bary.x * bary.y * bary.z);    return lerp(flatPositionWS, smoothedPositionWS, smoothing);}\/\/ The domain function runs once per vertex in the final, tessellated mesh\/\/ Use it to reposition vertices and prepare for the fragment stage[domain(&quot;tri&quot;)] \/\/ Signal we're inputting trianglesInterpolators Domain(    TessellationFactors factors, \/\/ The output of the patch constant function    OutputPatch<TessellationControlPoint, 3&gt; patch, \/\/ The Input triangle    float3 barycentricCoordinates : SV_DomainLocation) { \/\/ The barycentric coordinates of the vertex on the triangle    Interpolators output;    ...    \/\/ Calculate tessellation smoothing multipler    float smoothing = _TessellationSmoothing;#ifdef _TESSELLATION_SMOOTHING_VCOLORS    smoothing *= BARYCENTRIC_INTERPOLATE(color.r); \/\/ Multiply by the vertex's red channel#endif    float3 positionWS = CalculateBezierPosition(barycentricCoordinates,      smoothing, factors.bezierPoints,       patch[0].positionWS, patch[1].positionWS, patch[2].positionWS);    float3 normalWS = BARYCENTRIC_INTERPOLATE(normalWS);    float3 tangentWS = BARYCENTRIC_INTERPOLATE(tangentWS.xyz);    ...}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Barycentric interpolation as a function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BarycentricInterpolate<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">a<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">b<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">c<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">a<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">b<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">c<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">7<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BarycentricInterpolate<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedPositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">4<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">5<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">6<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">6<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">lerp<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedPositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ The domain function runs once per vertex in the final, tessellated mesh<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Use it to reposition vertices and prepare for the fragment stage<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">tri<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)] <\/span><span style=\"color: #616E88\">\/\/ Signal we&#039;re inputting triangles<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/The output of the patch constant function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">OutputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The Input triangle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DomainLocation<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The barycentric coordinates of the vertex on the triangle<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Calculate tessellation smoothing multipler<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationSmoothing<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">ifdef<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TESSELLATION_SMOOTHING_VCOLORS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">color<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">r<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ Multiply by the vertex&#039;s red channel<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">endif<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-134.png\" alt=\"\" class=\"wp-image-792 lazyload\"\/><noscript><img decoding=\"async\" width=\"912\" height=\"510\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-134.png\" alt=\"\" class=\"wp-image-792 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-134.png 912w, https:\/\/remoooo.com\/wp-content\/uploads\/image-134-300x168.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-134-768x429.png 768w\" sizes=\"(max-width: 912px) 100vw, 912px\" \/><\/noscript><\/figure>\n\n\n\n<p>Compare the effects, PN triangles off and on.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4.3 Improved PN triangles \u2013 Output subdivided normals<\/h3>\n\n\n\n<p>Traditional PN triangles only change the position information of the vertices. We can combine the normal information of the vertices to output dynamically changing normal information to provide better light reflection effects.<\/p>\n\n\n\n<p>In the original algorithm, the change of normals is very discrete. As shown in the figure below (above), the normals provided by the two vertices of the original triangle may not be able to well represent the change of the normals of the original surface. We want to achieve the effect shown in the figure below (below), so we need to use quadratic interpolation to obtain the possible surface changes in a single patch.<\/p>\n\n\n\n<p>Since the surface is a cubic Bezier surface, the normal should be a quadratic Bezier surface interpolation, so three additional normal control points are required.<a target=\"_blank\" href=\"https:\/\/www.zhihu.com\/people\/dong-yao-xin-70\" rel=\"noreferrer noopener\">TheTus<\/a>The article has been explained clearly. Please go to the detailed mathematical principles<a target=\"_blank\" href=\"https:\/\/zhuanlan.zhihu.com\/p\/629202115\" rel=\"noreferrer noopener\">Ref10. Link<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-137-1024x779.png\" alt=\"\" class=\"wp-image-795 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"779\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-137-1024x779.png\" alt=\"\" class=\"wp-image-795 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-137-1024x779.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-137-300x228.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-137-768x585.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-137.png 1072w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>The following is a brief introduction on how to obtain the normal direction of the subdivision.<\/p>\n\n\n\n<p>First, get the two normal information of point AB. Then find their average normal.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-138-1024x392.png\" alt=\"\" class=\"wp-image-796 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"392\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-138-1024x392.png\" alt=\"\" class=\"wp-image-796 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-138-1024x392.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-138-300x115.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-138-768x294.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-138.png 1284w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Construct a plane perpendicular to line segment AB and passing through its midpoint.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-143-1024x354.png\" alt=\"\" class=\"wp-image-801 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"354\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-143-1024x354.png\" alt=\"\" class=\"wp-image-801 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-143-1024x354.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-143-300x104.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-143-768x266.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-143.png 1162w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Take the reflection vector of the average normal just taken for the plane.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-140-1024x316.png\" alt=\"\" class=\"wp-image-798 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"316\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-140-1024x316.png\" alt=\"\" class=\"wp-image-798 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-140-1024x316.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-140-300x93.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-140-768x237.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-140.png 1224w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<p>Count each side, so there are three.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-142-1024x432.png\" alt=\"\" class=\"wp-image-800 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"432\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-142-1024x432.png\" alt=\"\" class=\"wp-image-800 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-142-1024x432.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-142-300x127.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-142-768x324.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-142.png 1162w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"struct TessellationFactors {    float edge[3] : SV_TessFactor;    float inside : SV_InsideTessFactor;    float3 bezierPoints[10] : BEZIERPOS;};float3 CalculateBezierControlNormal(float3 p0PositionWS, float3 aNormalWS, float3 p1PositionWS, float3 bNormalWS) {    float3 d = p1PositionWS - p0PositionWS;    float v = 2 * dot(d, aNormalWS + bNormalWS) \/ dot(d, d);    return normalize(aNormalWS + bNormalWS - v * d);}void CalculateBezierNormalPoints(inout float3 bezierPoints[10],    float3 p0PositionWS, float3 p0NormalWS, float3 p1PositionWS, float3 p1NormalWS, float3 p2PositionWS, float3 p2NormalWS) {    bezierPoints[7] = CalculateBezierControlNormal(p0PositionWS, p0NormalWS, p1PositionWS, p1NormalWS);    bezierPoints[8] = CalculateBezierControlNormal(p1PositionWS, p1NormalWS, p2PositionWS, p2NormalWS);    bezierPoints[9] = CalculateBezierControlNormal(p2PositionWS, p2NormalWS, p0PositionWS, p0NormalWS);}\/\/ The patch constant function runs once per triangle, or &quot;patch&quot;\/\/ It runs in parallel to the hull functionTessellationFactors PatchConstantFunction(    InputPatch<TessellationControlPoint, 3&gt; patch) {    ...    TessellationFactors f = (TessellationFactors)0;    \/\/ Check if this patch should be culled (it is out of view)    if (ShouldClipPatch(...)) {        ..    } else {        ...        CalculateBezierControlPoints(f.bezierPoints,           patch[0].positionWS, patch[0].normalWS, patch[1].positionWS,           patch[1].normalWS, patch[2].positionWS, patch[2].normalWS);        CalculateBezierNormalPoints(f.bezierPoints,           patch[0].positionWS, patch[0].normalWS, patch[1].positionWS,           patch[1].normalWS, patch[2].positionWS, patch[2].normalWS);    }    return f;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">struct<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\">] : <\/span><span style=\"color: #D8DEE9\">SV_TessFactor<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> inside <\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">SV_InsideTessFactor<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">10<\/span><span style=\"color: #D8DEE9FF\">] : <\/span><span style=\"color: #D8DEE9\">BEZIERPOS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlNormal<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">aNormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bNormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">d<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">v<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">dot<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">d<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">aNormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bNormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">dot<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">d<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">d<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">normalize<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">aNormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bNormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">v<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">d<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierNormalPoints<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">inout<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">10<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">7<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlNormal<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlNormal<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p1PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">9<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierControlNormal<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">p2PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0PositionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ The patch constant function runs once per triangle, or &quot;patch&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ It runs in parallel to the hull function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">PatchConstantFunction<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">InputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Check if this patch should be culled (it is out of view)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #88C0D0\">ShouldClipPatch<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #81A1C1\">...<\/span><span style=\"color: #D8DEE9FF\">)) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">..<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">else<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">CalculateBezierControlPoints<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">CalculateBezierNormalPoints<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">f<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>And it should be noted that all interpolated normal vectors need to be standardized.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"float3 CalculateBezierNormal(float3 bary, float3 bezierPoints[10],    float3 p0NormalWS, float3 p1NormalWS, float3 p2NormalWS) {    return p0NormalWS * (bary.x * bary.x) +        p1NormalWS * (bary.y * bary.y) +        p2NormalWS * (bary.z * bary.z) +        bezierPoints[7] * (2 * bary.x * bary.y) +        bezierPoints[8] * (2 * bary.y * bary.z) +        bezierPoints[9] * (2 * bary.z * bary.x);}float3 CalculateBezierNormalWithSmoothFactor(float3 bary, float smoothing, float3 bezierPoints[10],    float3 p0NormalWS, float3 p1NormalWS, float3 p2NormalWS) {    float3 flatNormalWS = BarycentricInterpolate(bary, p0NormalWS, p1NormalWS, p2NormalWS);    float3 smoothedNormalWS = CalculateBezierNormal(bary, bezierPoints, p0NormalWS, p1NormalWS, p2NormalWS);    return normalize(lerp(flatNormalWS, smoothedNormalWS, smoothing));}\/\/ The domain function runs once per vertex in the final, tessellated mesh\/\/ Use it to reposition vertices and prepare for the fragment stage[domain(&quot;tri&quot;)] \/\/ Signal we're inputting trianglesInterpolators Domain(    TessellationFactors factors, \/\/ The output of the patch constant function    OutputPatch<TessellationControlPoint, 3&gt; patch, \/\/ The Input triangle    float3 barycentricCoordinates : SV_DomainLocation) { \/\/ The barycentric coordinates of the vertex on the triangle    Interpolators output;    ...    \/\/ Calculate tessellation smoothing multipler    float smoothing = _TessellationSmoothing;    float3 positionWS = CalculateBezierPosition(barycentricCoordinates, smoothing, factors.bezierPoints, patch[0].positionWS, patch[1].positionWS, patch[2].positionWS);    float3 normalWS = CalculateBezierNormalWithSmoothFactor(        barycentricCoordinates, smoothing, factors.bezierPoints,        patch[0].normalWS, patch[1].normalWS, patch[2].normalWS);    float3 tangentWS = BARYCENTRIC_INTERPOLATE(tangentWS.xyz);    ...}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierNormal<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">10<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">7<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">9<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">z<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierNormalWithSmoothFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">10<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatNormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BarycentricInterpolate<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedNormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierNormal<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">normalize<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #88C0D0\">lerp<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatNormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedNormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\">))<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ The domain function runs once per vertex in the final, tessellated mesh<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Use it to reposition vertices and prepare for the fragment stage<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">tri<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)] <\/span><span style=\"color: #616E88\">\/\/ Signal we&#039;re inputting triangles<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/The output of the patch constant function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">OutputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The Input triangle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DomainLocation<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The barycentric coordinates of the vertex on the triangle<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Calculate tessellation smoothing multipler<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">_TessellationSmoothing<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierPosition<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">positionWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierNormalWithSmoothFactor<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BARYCENTRIC_INTERPOLATE<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>There is another problem that needs to be noted. When we use the interpolated normal, the tangent vector corresponding to it is no longer orthogonal to the interpolated normal vector. In order to maintain orthogonality, a new tangent vector needs to be calculated.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"void CalculateBezierNormalAndTangent(    float3 bary, float smoothing, float3 bezierPoints[10],    float3 p0NormalWS, float3 p0TangentWS,     float3 p1NormalWS, float3 p1TangentWS,     float3 p2NormalWS, float3 p2TangentWS,    out float3 normalWS, out float3 tangentWS) {    float3 flatNormalWS = BarycentricInterpolate(bary, p0NormalWS, p1NormalWS, p2NormalWS);    float3 smoothedNormalWS = CalculateBezierNormal(bary, bezierPoints, p0NormalWS, p1NormalWS, p2NormalWS);    normalWS = normalize(lerp(flatNormalWS, smoothedNormalWS, smoothing));    float3 flatTangentWS = BarycentricInterpolate(bary, p0TangentWS, p1TangentWS, p2TangentWS);    float3 flatBitangentWS = cross(flatNormalWS, flatTangentWS);    tangentWS = normalize(cross(flatBitangentWS, normalWS));}[domain(&quot;tri&quot;)] \/\/ Signal we're inputting trianglesInterpolators Domain(    TessellationFactors factors, \/\/ The output of the patch constant function    OutputPatch<TessellationControlPoint, 3&gt; patch, \/\/ The Input triangle    float3 barycentricCoordinates : SV_DomainLocation) { \/\/ The barycentric coordinates of the vertex on the triangle    ...    float3 normalWS, tangentWS;    CalculateBezierNormalAndTangent(        barycentricCoordinates, smoothing, factors.bezierPoints,        patch[0].normalWS, patch[0].tangentWS.xyz,         patch[1].normalWS, patch[1].tangentWS.xyz,         patch[2].normalWS, patch[2].tangentWS.xyz,        normalWS, tangentWS);    ...}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierNormalAndTangent<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">10<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0TangentWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1TangentWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2TangentWS<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">out<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">out<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatNormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BarycentricInterpolate<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedNormalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CalculateBezierNormal<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1NormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2NormalWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">normalize<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #88C0D0\">lerp<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatNormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothedNormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #D8DEE9FF\">))<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatTangentWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BarycentricInterpolate<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">bary<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p0TangentWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p1TangentWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">p2TangentWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatBitangentWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">cross<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatNormalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">flatTangentWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">normalize<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #88C0D0\">cross<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">flatBitangentWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #D8DEE9FF\">))<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">tri<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)] <\/span><span style=\"color: #616E88\">\/\/ Signal we&#039;re inputting triangles<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">Interpolators<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Domain<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">TessellationFactors<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/The output of the patch constant function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">OutputPatch<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">TessellationControlPoint<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The Input triangle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DomainLocation<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ The barycentric coordinates of the vertex on the triangle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">CalculateBezierNormalAndTangent<\/span><span style=\"color: #D8DEE9FF\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">barycentricCoordinates<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smoothing<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">factors<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">bezierPoints<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">patch<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #B48EAD\">2<\/span><span style=\"color: #D8DEE9FF\">]<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xyz<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">normalWS<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">tangentWS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-144-1024x653.png\" alt=\"\" class=\"wp-image-802 lazyload\"\/><noscript><img decoding=\"async\" width=\"1024\" height=\"653\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-144-1024x653.png\" alt=\"\" class=\"wp-image-802 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-144-1024x653.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-144-300x191.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-144-768x490.png 768w, https:\/\/remoooo.com\/wp-content\/uploads\/image-144.png 1386w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>https:\/\/www.youtube.com\/watch?v=63ufydgBcIk<\/li>\n\n\n\n<li>https:\/\/nedmakesgames.medium.com\/mastering-tessellation-shaders-and-their-many-uses-in-unity-9caeb760150e<\/li>\n\n\n\n<li>https:\/\/zhuanlan.zhihu.com\/p\/148247621<\/li>\n\n\n\n<li>https:\/\/zhuanlan.zhihu.com\/p\/124235713<\/li>\n\n\n\n<li>https:\/\/zhuanlan.zhihu.com\/p\/141099616<\/li>\n\n\n\n<li>https:\/\/zhuanlan.zhihu.com\/p\/42550699<\/li>\n\n\n\n<li>https:\/\/en.wikipedia.org\/wiki\/Barycentric_coordinate_system<\/li>\n\n\n\n<li>https:\/\/zhuanlan.zhihu.com\/p\/359999755<\/li>\n\n\n\n<li>https:\/\/zhuanlan.zhihu.com\/p\/629364817<\/li>\n\n\n\n<li>https:\/\/zhuanlan.zhihu.com\/p\/629202115<\/li>\n\n\n\n<li>https:\/\/perso.telecom-paristech.fr\/boubek\/papers\/PhongTessellation\/PhongTessellation.pdf<\/li>\n\n\n\n<li>http:\/\/alex.vlachos.com\/graphics\/CurvedPNTriangles.pdf<\/li>\n<\/ol>","protected":false},"excerpt":{"rendered":"<p>\u6807\u7b7e \uff1a\u5165\u95e8\/Shader\/\u66f2\u9762\u7ec6\u5206\u7740\u8272\u5668\/Displacement\u8d34\u56fe\/LOD\/\u5e73\u6ed1\u8f6e\u5ed3\/Early Cul [&hellip;]<\/p>","protected":false},"author":1,"featured_media":784,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53],"tags":[14,38,37],"class_list":["post-756","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech","tag-shader","tag-tessellation","tag-unity"],"_links":{"self":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/756","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/comments?post=756"}],"version-history":[{"count":3,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/756\/revisions"}],"predecessor-version":[{"id":845,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/756\/revisions\/845"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/media\/784"}],"wp:attachment":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/media?parent=756"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/categories?post=756"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/tags?post=756"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}