YouTube2Text

Mastering Tessellation Shaders in Unity! Easy LoD, Curved Triangles, Height Maps | Game Dev Tutorial — Transcript

by Ned Makes Games · 6,167 words · 1,050 segments · language en · Watch on YouTube

Full transcript

  1. 0:00hi i'm ned and i make games
  2. 0:03in this unity graphics programming
  3. 0:04tutorial i'll introduce you to
  4. 0:06tessellation shaders advanced shaders
  5. 0:08which can subdivide triangles adding
  6. 0:10details and smoothing out blocky models
  7. 0:13use them for automatic level of detail
  8. 0:15procedural models or height map-based
  9. 0:17terrain
  10. 0:18keep watching to learn how to add
  11. 0:20tessellation to any shader and any game
  12. 0:21yourself
  13. 0:23please don't let the length of this
  14. 0:24video scare you off i've prepared time
  15. 0:26stamps for all the sections of this
  16. 0:28tutorial so feel free to skip around
  17. 0:31i want to take a moment to thank all my
  18. 0:32patrons for helping make this video
  19. 0:34possible and give a big shout out to my
  20. 0:36next gen patron croobiedoobydoo
  21. 0:38thank you all so much
  22. 0:40also if you prefer reading tutorials i
  23. 0:42have a written version of this one
  24. 0:44linked in the video description
  25. 0:46this tutorial was tested in unity 2020.3
  26. 0:502021.1 and 2021.2
  27. 0:53if you're using a newer version than
  28. 0:54that check out the video description for
  29. 0:56any changes that you should know about
  30. 0:59also i'll be using the universal render
  31. 1:01pipeline for all the examples in this
  32. 1:02video however none of these techniques
  33. 1:04are urp specific
  34. 1:06the shader graph will not be featured
  35. 1:08here as even in hdrp it does not support
  36. 1:11all the required techniques
  37. 1:13if you're unfamiliar with hlsl shaders
  38. 1:15in urp or otherwise i'm writing a
  39. 1:17tutorial about that so check the video
  40. 1:19description
  41. 1:21this tutorial will explain what
  42. 1:22tessellation shaders are and how to
  43. 1:24write them in hlsl i will demonstrate
  44. 1:27several methods to optimize teslazation
  45. 1:30control the amount of subdivision per
  46. 1:31triangle
  47. 1:32smooth a model's geometry and silhouette
  48. 1:35and add details with height maps and
  49. 1:37procedural techniques
  50. 1:39this tutorial aims to explain the topic
  51. 1:41of tessellation not so much create a
  52. 1:43finished shader
  53. 1:45nevertheless i have provided an example
  54. 1:47shader in the video description with
  55. 1:49most of the topics in this video
  56. 1:50implemented
  57. 1:53as i mentioned earlier
  58. 1:54this tutorial is more advanced and we'll
  59. 1:56expect you to know how to write shaders
  60. 1:58in hlsl
  61. 2:00in addition it will make use of vector
  62. 2:02math so brush up on vector dot products
  63. 2:04and cross products as well as vector
  64. 2:06projection and reflection
  65. 2:11in mathematics teslazation is the
  66. 2:13process of fitting shapes together to
  67. 2:15form a larger surface
  68. 2:18however in graphics programming it
  69. 2:19usually refers to subdividing a shape
  70. 2:21into smaller pieces
  71. 2:23tessellation shaders do just that if you
  72. 2:25put a mesh in the gpu will subdivide all
  73. 2:28of its faces adding many more vertices
  74. 2:30now why is this useful well you can take
  75. 2:33these extra vertices and move them
  76. 2:34around smoothing out jagged low poly
  77. 2:37edges and adding fine position details
  78. 2:39not possible otherwise
  79. 2:41this enables a kind of reverse workflow
  80. 2:43for lod where you can create low poly
  81. 2:46models and use teslazation to add
  82. 2:48complexity testilization is also great
  83. 2:51for terrain
  84. 2:52you can use a flat mesh and tessellate
  85. 2:54it adjusting heights with a height map
  86. 2:56this allows you to adjust the shape
  87. 2:58using only a texture and render high
  88. 3:00detail only where the camera can see it
  89. 3:03generate a height map procedurally to
  90. 3:05visualize mathematical surfaces like
  91. 3:07sdfs or easily animate a mesh
  92. 3:11keep in mind that tessellation shaders
  93. 3:13do have a hefty performance cost the
  94. 3:15good news is that they're generally
  95. 3:17cheaper and have better hardware support
  96. 3:19than their cousins geometry shaders plus
  97. 3:22they do allow you to keep your mesh
  98. 3:23assets simpler which can help with
  99. 3:25batching if you're worried about
  100. 3:27performance be sure to test things out
  101. 3:29before committing to testilization
  102. 3:32okay so how do you add teslazation to a
  103. 3:35shader teslazation shaders have two
  104. 3:37additional programmable stages similar
  105. 3:39to the vertex and fragment stages we're
  106. 3:41all used to
  107. 3:42these are called the hull and domain
  108. 3:44stages they run in between the vertex
  109. 3:47and fragment stages and together with an
  110. 3:49unprogrammable stage called the
  111. 3:51tessellator control how the mesh is
  112. 3:53subdivided and refined
  113. 3:55let's take a look at the structure of
  114. 3:56these functions and then see how to add
  115. 3:58them to your shader code
  116. 4:00the whole function receives data in the
  117. 4:02form of patches which are simply lists
  118. 4:05of vertices
  119. 4:06what relation these vertices have to one
  120. 4:08another is configurable however in this
  121. 4:10tutorial i'll always stick to triangles
  122. 4:13so this patch is an array of three
  123. 4:15vertices that make up a triangle on the
  124. 4:16mesh the array contains output data from
  125. 4:19the vertex function corresponding to
  126. 4:21each vertex
  127. 4:22besides the patch the whole function
  128. 4:24also receives an index specifying which
  129. 4:27vertex in the patch the whole function
  130. 4:29must output data for it runs once per
  131. 4:31vertex in the patch and can look at all
  132. 4:33the other vertices in the patch to
  133. 4:35produce a new data structure for later
  134. 4:37on in the chain the whole stage is
  135. 4:39unique in that it also has another
  136. 4:41function that runs in parallel the patch
  137. 4:43constant function the separate function
  138. 4:46runs once per patch so it's very useful
  139. 4:48to calculate data that's shared between
  140. 4:50vertices of a triangle it also must
  141. 4:52output tessellation factors which
  142. 4:54determine how many times to subdivide
  143. 4:56the patch we'll talk about these
  144. 4:58extensively later on so to summarize the
  145. 5:01whole stage is made up of two functions
  146. 5:03the whole function and the patch
  147. 5:05constant function they receive a patch
  148. 5:07which is a collection of vertices
  149. 5:09usually forming a triangle
  150. 5:11the whole function runs once per vertex
  151. 5:13in the patch and the patch constant
  152. 5:15function runs once per patch and must
  153. 5:18output tessellation factors
  154. 5:20next up the non-programmable stage
  155. 5:23called the tessellator runs this takes
  156. 5:25patch data and the tessellation factors
  157. 5:27generating during the whole stage to
  158. 5:29subdivide each patch
  159. 5:31the tessellator generates something
  160. 5:32called barycentric coordinates for all
  161. 5:34the vertices of this new mesh
  162. 5:36barycentric coordinates are an easy way
  163. 5:38to describe a point inside of a triangle
  164. 5:41any point can be calculated as a
  165. 5:43weighted average of the three corner
  166. 5:44points and barycentric coordinates are
  167. 5:46the weights in that formula
  168. 5:48they're given as a float3 vector and the
  169. 5:50three components always sum to one
  170. 5:53besides position we can also use
  171. 5:55barycentric coordinates to calculate
  172. 5:56normals uvs or anything else that varies
  173. 5:59based on the triangle corners
  174. 6:02this brings us to the second
  175. 6:03programmable stage involved in
  176. 6:04teslalization the domain stage it
  177. 6:07consists of one function the domain
  178. 6:09function which runs once per each vertex
  179. 6:12on the tessellated mesh its job is to
  180. 6:15output the final data for the mesh and
  181. 6:17to do so it receives the barycentric
  182. 6:19coordinates for vertex and its
  183. 6:21originating patch this includes all of
  184. 6:23the data generated by the whole function
  185. 6:25and the patch constant function the
  186. 6:26domain function is where a lot of your
  187. 6:28logic will go most of what you'd usually
  188. 6:30put in the vertex stage should be
  189. 6:32calculated here instead including clip
  190. 6:34space positions crucially you can
  191. 6:36reposition vertices in the domain stage
  192. 6:39something that's essential for most of
  193. 6:40tessellation's use cases
  194. 6:43if you have a geometry function it would
  195. 6:45run next after the domain stage but
  196. 6:47usually the rasterization and fragment
  197. 6:49stages run next
  198. 6:50to summarize the vertex stage runs first
  199. 6:53the whole stage receives information
  200. 6:55about triangles on your mesh called
  201. 6:57patches and decides how to subdivide
  202. 6:59them the test later does the heavy
  203. 7:01lifting subdividing the mesh while the
  204. 7:03domain stage prepares vertices in the
  205. 7:05tessellated mesh for the fragment stage
  206. 7:07deciding where each vertex should appear
  207. 7:10on the screen
  208. 7:11now we know what the hull and domain
  209. 7:13functions do let's add them to a simple
  210. 7:15shader you can register hole and domain
  211. 7:17functions similarly to the other
  212. 7:18programmable stages using a pragma
  213. 7:21directive note that tessellation shaders
  214. 7:23require shader target 5.0 so adjust that
  215. 7:26too or unity will give you an error the
  216. 7:29vertex function is pretty plain now it
  217. 7:31simply converts positions and normals to
  218. 7:33world space the output structure will be
  219. 7:35fed into the whole stage and can contain
  220. 7:38basically any data that you'd need later
  221. 7:40on in the pipeline notably the position
  222. 7:42semantic is forbidden in this structure
  223. 7:45so use the internal test pause semantic
  224. 7:47instead
  225. 7:48the whole shader signature looks like
  226. 7:50this it has several attribute-like tags
  227. 7:53the domain determines the input patch
  228. 7:56type while the output topology and
  229. 7:58output control points determine the
  230. 8:00output patch type
  231. 8:01again we're always going to use
  232. 8:03triangles in this tutorial so these will
  233. 8:05all remain the same
  234. 8:06the patch constant function attribute
  235. 8:08registers the patch constant function
  236. 8:11and the partitioning attribute tells the
  237. 8:13test later which algorithm to use to
  238. 8:15subdivide triangles keep this one in
  239. 8:17mind for later
  240. 8:19the function itself receives the input
  241. 8:21patch using the special construct the
  242. 8:23vertex function output structure and
  243. 8:25number of vertices in the patch go
  244. 8:27inside the angle brackets
  245. 8:29you can access each structure in the
  246. 8:31patch like you would an array
  247. 8:33the hole function also receives the
  248. 8:35vertex index with the sv underscore
  249. 8:37output control point semantic it signals
  250. 8:40which vertex in the patch to output data
  251. 8:42for finally don't forget to set the
  252. 8:44return structure type in this example
  253. 8:46it's the same as the vertex output
  254. 8:48structure type but it could be unique
  255. 8:51there's no required fields in this data
  256. 8:53but once again use internal test pose
  257. 8:55instead of position in this example the
  258. 8:57hull function body is extremely simple
  259. 9:00only returning the correct vertex inside
  260. 9:02the patch
  261. 9:03the patch constant function has a much
  262. 9:05simpler signature it also receives the
  263. 9:08input patch and outputs its own data
  264. 9:10structure
  265. 9:11this structure should contain the
  266. 9:12tessellation factors specified per edge
  267. 9:15on the triangle using the sv test factor
  268. 9:17semantic edges are arranged opposite of
  269. 9:20the vertex with the same index in other
  270. 9:23words edge 0 lies between vertices 1 and
  271. 9:262.
  272. 9:27there's also a center tessellation
  273. 9:29factor tagged with the sv inside test
  274. 9:32factor semantic
  275. 9:33soon we'll visualize how all these
  276. 9:35factors affect the final tessellation
  277. 9:37pattern but for now realize that the
  278. 9:39edge factor is the number of times an
  279. 9:41edge will subdivide and the inside
  280. 9:43factor squared is roughly the number of
  281. 9:45times a new triangle will be created
  282. 9:48the patch constant function can also
  283. 9:50output other data but it must be tagged
  284. 9:52with a semantic like always
  285. 9:55this special bezier pose semantic is
  286. 9:58useful since it can take the form of a
  287. 10:00float3 array
  288. 10:01later we'll use this output control
  289. 10:03points for a bezier curved based
  290. 10:05smoothing algorithm but you can use it
  291. 10:07to store anything you need
  292. 10:10with that we're done with the whole
  293. 10:11stage let's move on to the domain stage
  294. 10:14the domain function also has a domain
  295. 10:16attribute which should match the whole
  296. 10:17function's output topology triangles in
  297. 10:20this case
  298. 10:21as arguments it receives the output of
  299. 10:23the whole function arranged into a patch
  300. 10:26as well as the output from the patch
  301. 10:27constant function
  302. 10:29finally it receives the barycentric
  303. 10:31coordinates of the vertex to work with
  304. 10:33tagged with sv underscore domain
  305. 10:35location
  306. 10:37the output structure is very similar to
  307. 10:40what you'd output from a vertex function
  308. 10:42it should contain the clip space
  309. 10:44position as well as any fields the
  310. 10:46fragment function needs for lighting
  311. 10:48also notice the barycentric interpolate
  312. 10:50macro it's really handy to interpolate
  313. 10:53any property in the patch structure
  314. 10:55using barycentric coordinates
  315. 10:58and that's it for the general structure
  316. 10:59of a tessellation shader let's take a
  317. 11:01closer look at partitioning modes and
  318. 11:03tessellation factors
  319. 11:05in the video description i've created a
  320. 11:07simple tessellation shader so you can
  321. 11:09test all this stuff out it has a
  322. 11:11property to assign tessellation factors
  323. 11:13as well as one to switch between
  324. 11:15partitioning modes using a keyword
  325. 11:17create a material for it and add it to
  326. 11:19the mesh
  327. 11:20to visualize the tessellation be sure to
  328. 11:22set the scene render mode to shaded
  329. 11:24wireframe and then play around with the
  330. 11:26factors
  331. 11:28you'll see that the edge factor
  332. 11:29corresponds to roughly the number of
  333. 11:31times edges will be subdivided while the
  334. 11:34inside factor adds complexity to the
  335. 11:36center
  336. 11:37also notice that setting any factor to 0
  337. 11:39or less will cause the mesh to disappear
  338. 11:42this will become important later
  339. 11:45now try setting the factors differently
  340. 11:46for each edge
  341. 11:48when we try more complicated algorithms
  342. 11:50it will be important that edges on
  343. 11:51adjoining triangles have the same
  344. 11:53tessellation factor if not you can get
  345. 11:55little holes in the mesh where the
  346. 11:56vertices don't match up to ensure that
  347. 11:58this doesn't happen try to restrict edge
  348. 12:01factors to depend only on vertices
  349. 12:03connected to that edge
  350. 12:05you may have also noticed some commented
  351. 12:07out properties in the shader uncomment
  352. 12:09these and change their patch constant
  353. 12:11function slightly to this
  354. 12:14is your mesh flickering even with
  355. 12:16positive factors why
  356. 12:18there's an oddity with the way the
  357. 12:20shader compiler handles tessellation
  358. 12:22factors
  359. 12:23in a bid to speed things up the compiler
  360. 12:25sometimes splits the patch constant
  361. 12:27function and calculates each factor in
  362. 12:29parallel
  363. 12:30this sometimes causes weird issues
  364. 12:33if you look at the frame debugger you'll
  365. 12:35see that the compiler stripped our two
  366. 12:37edge factor properties from the shader
  367. 12:39making them always equal to zero you can
  368. 12:41fix this by using a vector property with
  369. 12:43each component specifying one edge's
  370. 12:45factor so the compiler simply can't
  371. 12:48strip out anything in general if your
  372. 12:51tessellation factors are acting strange
  373. 12:53try rewriting this section of the patch
  374. 12:55constant function
  375. 12:58moving on to partitioning the modes are
  376. 13:00all pretty interesting
  377. 13:02the integer mode divides a number of
  378. 13:04times equal to the ceiling of the
  379. 13:05tessellation factor it has a generally
  380. 13:08nice pattern
  381. 13:13if you need tessellation factors to
  382. 13:14smoothly transition the fractional odd
  383. 13:17and fractional even modes will handle
  384. 13:19that they're so named because they can
  385. 13:21only fully subdivide on either odd or
  386. 13:23even numbers which is easier to
  387. 13:25understand when you see them in motion
  388. 13:29a quirk of the fractional even mode is
  389. 13:31that it always subdivides at least once
  390. 13:34since 2 is the lowest factor that it can
  391. 13:36handle
  392. 13:44the last pow2 mode seems to be identical
  393. 13:47to integer mode at least on my machine
  394. 13:50i would have guessed that it only
  395. 13:51subdivided when the factor is a power of
  396. 13:53two
  397. 13:54let me know how it works for you
  398. 14:00tessellation can be expensive but there
  399. 14:02are a few ways that we can speed it up
  400. 14:04since tessellation happens before the
  401. 14:06rasterization stage it cannot take
  402. 14:08advantage of the automatic frustum and
  403. 14:10winding culling that happens there
  404. 14:12thankfully we can implement it ourselves
  405. 14:14and avoid tessellating triangles that
  406. 14:16will just be thrown out later
  407. 14:19it's easy to call a triangle in the
  408. 14:20patch constant function just set the
  409. 14:22tessellation factors to zero and the
  410. 14:24tessellator will just ignore that patch
  411. 14:27first let's tackle frustum culling where
  412. 14:30we test each point of the triangle to
  413. 14:31see if it's out of bounds of the view
  414. 14:33frustum
  415. 14:34to do that we can use clip space
  416. 14:36positions of the triangle corners
  417. 14:39be sure to calculate it in the vertex
  418. 14:40function and pass it to the whole stage
  419. 14:44above the patch constant function write
  420. 14:46this function to test if a patch should
  421. 14:48be called passing the clip space
  422. 14:50positions of the triangle just return
  423. 14:52false for now
  424. 14:53above that write is out of bounds to
  425. 14:55check if a point is outside the bounds
  426. 14:57defined by upper and lower vectors and
  427. 15:00should frustum call to calculate these
  428. 15:02bounding vectors
  429. 15:04in clip space the w component of the
  430. 15:06position contains the outer bounds of
  431. 15:08the viewing frustum the camera viewable
  432. 15:11area so we can use that to calculate the
  433. 15:13bounding vectors the logic slightly
  434. 15:16differs between graphics api since some
  435. 15:18anchor the viewing preston at 0 and some
  436. 15:21at negative w
  437. 15:22luckily unity provides a constant with
  438. 15:24the correct value
  439. 15:26returning to should clip patch calls
  440. 15:29should frustum call on each point if
  441. 15:31they're all true the triangle is
  442. 15:33entirely outside the viewing area and
  443. 15:35should be called
  444. 15:37moving on to winding culling which is
  445. 15:39also called back face culling we need to
  446. 15:41calculate which side of the triangle is
  447. 15:43facing the camera culling only if the
  448. 15:45back side of the triangle is visible do
  449. 15:48that by calculating a normal vector for
  450. 15:50the plane containing the triangle and
  451. 15:52testing if it's roughly pointing towards
  452. 15:54the camera
  453. 15:55to find the normal vector we need two
  454. 15:57vectors tangent to the plane vectors
  455. 15:59pointing between the three triangle
  456. 16:00corners will do nicely their cross
  457. 16:02product is the normal
  458. 16:04and since we're working in clip space we
  459. 16:06need to normalize the position and apply
  460. 16:09perspective by dividing by the w
  461. 16:11component of each
  462. 16:12this gives roughly screen space
  463. 16:14positions
  464. 16:16use a dot product of the view direction
  465. 16:18and the triangle normal to find out if
  466. 16:20they're roughly pointing in the same
  467. 16:21direction
  468. 16:23since the camera points along the z-axis
  469. 16:25in clip space we can simplify all this
  470. 16:27to a comparison of the normal's
  471. 16:29z-coordinate
  472. 16:31i did say that the camera points along
  473. 16:32the z-axis but which way
  474. 16:35it turns out this depends again on your
  475. 16:37graphics api
  476. 16:38usually the view direction is in the
  477. 16:40negative z direction however this is
  478. 16:42flipped in opengl
  479. 16:44use this keyword to apply the correct
  480. 16:46comparison either way
  481. 16:47[Music]
  482. 16:48finally in should clip patch call should
  483. 16:51backface call as well
  484. 16:53then in the patch constant function if
  485. 16:55should clip patch returns true set all
  486. 16:58edge vectors to zero
  487. 17:01back in unity you might notice that the
  488. 17:03shader culls some faces of your mesh
  489. 17:05when it shouldn't even if you don't see
  490. 17:07that now you certainly will later on
  491. 17:09when adding vertex displacement
  492. 17:11add some leeway to these calculations by
  493. 17:14introducing frustum and winding cold
  494. 17:15tolerance properties
  495. 17:18for frustum culling add the tolerance to
  496. 17:20each bound while for winding culling
  497. 17:22compare the normal z-axis with a
  498. 17:24tolerance instead of zero
  499. 17:27adjust these properties as needed while
  500. 17:28you're adding features
  501. 17:33another way to optimize tessellation is
  502. 17:35to lower factors when and where a mesh
  503. 17:37doesn't need to be subdivided
  504. 17:39there are a few ways to go about this
  505. 17:42say we're working with a mesh that has
  506. 17:43some large faces but many smaller ones
  507. 17:46we really only need to tessellate the
  508. 17:48large faces
  509. 17:49one way to do this is to calculate
  510. 17:51tessellation factors proportionate to
  511. 17:53the edge length
  512. 17:55above the patch constant function define
  513. 17:58this function to calculate the
  514. 17:59tessellation factor for an edge bound by
  515. 18:01two vertices pass the world space
  516. 18:04position of each vertex as well as a
  517. 18:06scale and bias value set the factor to
  518. 18:08the scale plus the bias making sure that
  519. 18:11the result is never less than 1 so it
  520. 18:13doesn't get cold
  521. 18:15this creates a constant edge factor
  522. 18:17now to add world space edge length set
  523. 18:20the factor to the distance between the
  524. 18:21vertex positions divided by the scale
  525. 18:24in this scheme the edge subdivides
  526. 18:26aiming to keep the divided edge lengths
  527. 18:28roughly equal to the scale value add
  528. 18:31shader properties for the scale and bias
  529. 18:33values and back in the patch constant
  530. 18:35function call this new function for each
  531. 18:38edge factor passing in the new
  532. 18:39properties and the appropriate vertex
  533. 18:41positions
  534. 18:43remember edges are arranged across from
  535. 18:45the vertex sharing its index in the
  536. 18:47array
  537. 18:48the inside factor should be an average
  538. 18:50of all the edge factors
  539. 18:52this code worked just fine for me but if
  540. 18:54the compiler is not playing nice and
  541. 18:56you're seeing inconsistent edge factors
  542. 18:58just call edge tessellation factor again
  543. 19:00instead of using previously cached
  544. 19:02values
  545. 19:08alright neat
  546. 19:09but maybe we can test light based on an
  547. 19:11edge's length in screen space
  548. 19:14due to culling we already have the clip
  549. 19:16space positions so it shouldn't be so
  550. 19:18difficult to do
  551. 19:20in edge tessellation factor add
  552. 19:22arguments for each vertex's clip space
  553. 19:24position then calculate the factor by
  554. 19:27using clip space positions instead of
  555. 19:29world space positions
  556. 19:31make two adjustments
  557. 19:32first apply perspective by dividing the
  558. 19:35positions by their w component next
  559. 19:38multiply by underscore screen params.y
  560. 19:41which contains the height of the screen
  561. 19:43in pixels
  562. 19:44now we can specify the scale in pixels
  563. 19:46which just makes sense for screen space
  564. 19:49in the patch constant function pass the
  565. 19:51clip space positions along with the
  566. 19:52world space positions
  567. 19:55this looks good too but sometimes not
  568. 19:57quite right
  569. 19:59what if we use the distance to the
  570. 20:00camera somehow to help things out
  571. 20:03in edge tessellation factor find the
  572. 20:06length in world space between the two
  573. 20:07vertices then calculate the distance
  574. 20:10from the center of this edge to the
  575. 20:11camera the camera position is different
  576. 20:14in the various render pipelines but you
  577. 20:16can use this function to get its
  578. 20:17position in urp
  579. 20:19divide the length by the scale
  580. 20:21multiplied by the distance to the camera
  581. 20:23which effectively lowers the scale when
  582. 20:25close to the screen
  583. 20:27i prefer the effect with a quadratic
  584. 20:28curve but it's up to you
  585. 20:31i found that this approach gives me the
  586. 20:33best results but your mileage may vary
  587. 20:36you can use a keyword to switch between
  588. 20:38algorithms if you'd like
  589. 20:39so these heuristics try to guess the
  590. 20:41appropriate tessellation factors for
  591. 20:43your mesh but if you have an idea of how
  592. 20:46the mesh should tessellate yourself try
  593. 20:48storing tessellation factor multipliers
  594. 20:50in the mesh's data this is useful if you
  595. 20:52have an area with large flat faces where
  596. 20:55you'll never need to add detail
  597. 20:57for demonstration purposes i'll store
  598. 20:59these multipliers in the green channel
  599. 21:01of the meshes vertex colors but you can
  600. 21:04use text cords or anything else
  601. 21:06in blender or your modeling program of
  602. 21:08choice paint the area that you don't
  603. 21:10want to tessellate black
  604. 21:13in your shader pass the vertex colors
  605. 21:15down to your whole input structure
  606. 21:18in the patch constant function calculate
  607. 21:20a multiplier for each edge by averaging
  608. 21:22the green channel of connecting vertices
  609. 21:24and then pass it as a new multiplier
  610. 21:26into the edge tessellation factor
  611. 21:28function
  612. 21:29multiply that into the final calculation
  613. 21:33then check it out in unity
  614. 21:39here's another useful technique to use
  615. 21:41with some type of deforming force field
  616. 21:43or sdf
  617. 21:45in this example i deform a plane based
  618. 21:47on proximity to these little spheres
  619. 21:50i know that if the vertex is far enough
  620. 21:52away from all the spheres it doesn't
  621. 21:53deform so we don't need to tessellate
  622. 21:56connected triangles for now just ignore
  623. 21:58the actual deforming logic that will
  624. 22:01come later in the tutorial focus on
  625. 22:03calculating the tessellation factors
  626. 22:06in your patch constant function evaluate
  627. 22:09the deformation amount for each vertex
  628. 22:11if it results in a deformation then we
  629. 22:13should pass a multiplier of one
  630. 22:15otherwise past zero
  631. 22:21[Music]
  632. 22:23an easy way to add detail to a mesh is
  633. 22:26through high resolution textures
  634. 22:28for instance normal maps vary normal
  635. 22:30vectors per pixel which affect the
  636. 22:33apparent shape of a surface however this
  637. 22:35technique does not really change any
  638. 22:37mesh geometry nowhere as is more
  639. 22:39apparent than on a mesh's silhouette
  640. 22:42zoom up close and even 4k textures can't
  641. 22:45hide a jagged and pointy edge
  642. 22:47in this section i'll describe a few
  643. 22:49algorithms to smooth mesh geometry out
  644. 22:52using tessellation all of these
  645. 22:54strategies involve offsetting vertexes
  646. 22:56in the domain function
  647. 22:59through simple barycentric interpolation
  648. 23:02all new vertices are limited to the
  649. 23:03original triangle's plane however what
  650. 23:06if we use the corner's normal vector to
  651. 23:08construct a curved triangle
  652. 23:10the simplest technique to achieve this
  653. 23:12is called phong tessellation
  654. 23:14you might have heard of phong shading
  655. 23:16which is the smooth shading technique of
  656. 23:18linearly interpolated normal vectors
  657. 23:20fong tessellation tries to recapture
  658. 23:22that simplicity and efficiency while
  659. 23:24positioning tessellated points
  660. 23:27it works like this
  661. 23:28first calculate the flat very
  662. 23:30centrically interpolated position for a
  663. 23:32point
  664. 23:33then imagine three tangent planes
  665. 23:34emanating from each triangle corner
  666. 23:36normal to their respective normal vector
  667. 23:42next project the flat position onto each
  668. 23:45of these planes which is equivalent to
  669. 23:47finding the nearest point on that plane
  670. 23:50finally compute the barycentrically
  671. 23:52interpolated position again using these
  672. 23:54new projected points
  673. 23:57the math behind this isn't too
  674. 23:59complicated we already know how to deal
  675. 24:01with barycentric coordinates and to
  676. 24:03project a point onto a plane find the
  677. 24:05difference between the point and any
  678. 24:07other in the plane the triangle corners
  679. 24:09will work for this
  680. 24:10then project that vector onto the
  681. 24:12plane's normal vector and subtract the
  682. 24:14result from the original point here's
  683. 24:17the algorithm for fong tessellation in
  684. 24:19full
  685. 24:20now add this to your domain function
  686. 24:22make sure to use this new adjusted
  687. 24:24position when calculating clip space
  688. 24:28try it out on a model at first it may
  689. 24:30look a little too puffed up that's
  690. 24:32pretty common with fong tesselization we
  691. 24:34can improve this by adding a smoothing
  692. 24:36factor property
  693. 24:38interpolate between the flat position
  694. 24:40and the fong tessellated position using
  695. 24:42this
  696. 24:44factor which helps quite a bit
  697. 24:51[Music]
  698. 24:52some models may need a little touching
  699. 24:54up as well
  700. 24:56if your model has sharp edges try adding
  701. 24:59edge loops very close to the sharp edge
  702. 25:02making long thin faces
  703. 25:04looking at the font tessellation
  704. 25:06algorithm you can see why this works if
  705. 25:08the normal vectors of each vertex are
  706. 25:10very close to parallel the font position
  707. 25:13will be very close to the flat position
  708. 25:14as well
  709. 25:16another technique you can try is baking
  710. 25:18smoothing factors into your mesh's data
  711. 25:20for example in the red channel of its
  712. 25:22vertex colors
  713. 25:24simply paint the red channel black in
  714. 25:26areas that you don't want to bend
  715. 25:28pass the vertex colors all the way down
  716. 25:30to the domain function calculate the
  717. 25:32barycentric interpolation of the red
  718. 25:34vertex color channel and multiply that
  719. 25:37with a smoothing factor
  720. 25:38[Music]
  721. 25:40fong testosterone gives pretty good
  722. 25:42results and is also pretty cheap all
  723. 25:44things considered however if you need
  724. 25:46higher quality smoothing there's another
  725. 25:48option p in triangles
  726. 25:50this technique construct curved
  727. 25:52triangles similar to bezier curves it's
  728. 25:55quite a bit more expensive than the fong
  729. 25:57method but let's try it out
  730. 25:59we can save a lot of time by
  731. 26:01pre-computing bezier control points for
  732. 26:03use when positioning tessellated points
  733. 26:05in the domain function
  734. 26:06control points are constant per triangle
  735. 26:09so the patch constant function is
  736. 26:11perfect for this use we'll need 10
  737. 26:13control points the triangle corners
  738. 26:16a pair along each triangle edge
  739. 26:19and one in the triangle center
  740. 26:21let's take a look at calculating each
  741. 26:23control point
  742. 26:24the corners remain as they are they'll
  743. 26:26help ensure that the triangle never
  744. 26:28escapes its original position too much
  745. 26:31for the edge pairs use a similar
  746. 26:33algorithm to fong tesselization take
  747. 26:36this point one third along the edge from
  748. 26:38corner a to b to calculate its position
  749. 26:41first project b onto the plane defined
  750. 26:44by a's normal then take the average of
  751. 26:47this new point in a waiting a twice
  752. 26:50for the other point on the edge do the
  753. 26:52same operation mirroring a and b
  754. 26:56then continue with the other two edge
  755. 26:58pairs
  756. 27:00finally for the center point find the
  757. 27:02average of all of these new edge pair
  758. 27:05control points which i'll call e
  759. 27:07as well as the average of the triangle
  760. 27:09corners i'll call t
  761. 27:11the center control point is e plus the
  762. 27:14difference of e and t halved which gives
  763. 27:17a nice rounded center
  764. 27:20using these control points it's possible
  765. 27:22to compute any point on this bendy
  766. 27:24triangle using barycentric coordinates
  767. 27:27this is a formula which looks similar to
  768. 27:30a cubic bezier curve formula notice how
  769. 27:32the barycentric coordinates appear in
  770. 27:34terms with their corresponding corners
  771. 27:37the center point being an even
  772. 27:39combination of all three
  773. 27:41if you'd like to learn more about bezier
  774. 27:42curves i've linked some excellent
  775. 27:44resources in the video description
  776. 27:46[Music]
  777. 27:48to program all this store the control
  778. 27:50points in the patch constant output
  779. 27:52structure using the bezier pose semantic
  780. 27:55tag a seven element float3 array with it
  781. 27:58in the patch constant output struct
  782. 28:00why only seven well the patch already
  783. 28:02contains a triangle corner position so
  784. 28:04there's no reason to waste memory with
  785. 28:06them
  786. 28:06this function calculates the bezier
  787. 28:08control points using the algorithm
  788. 28:10described earlier call that in the patch
  789. 28:12constant function but only if the
  790. 28:14triangle isn't culled
  791. 28:16calculate the final point in the domain
  792. 28:18stage this function implements the
  793. 28:20bezier curve calculation using the
  794. 28:22control points from the whole stage i've
  795. 28:24also added an interpolation between the
  796. 28:26curved position and the flat position
  797. 28:28like we did with fong tesselization
  798. 28:30substitute this function for fong
  799. 28:32tesselization in your domain function
  800. 28:34[Music]
  801. 28:36back in the scene editor you'll see that
  802. 28:38this does give really good results
  803. 28:40usually slightly cleaner than fong
  804. 28:42teslazation it's up to you if the added
  805. 28:44complexity is worth it
  806. 28:46throughout all this we haven't touched
  807. 28:48normal vectors at all interpolating
  808. 28:50normal vectors linearly is usually okay
  809. 28:53but if your mesh has many divots and
  810. 28:55inflections shading might be improved by
  811. 28:58interpolating normals differently
  812. 29:00perhaps quadratically we'll use another
  813. 29:02bezier curve-like algorithm for this
  814. 29:04at first it might seem strange to use a
  815. 29:07bezier curve for normal vectors but as
  816. 29:09long as we normalize the final results
  817. 29:11it will work just fine
  818. 29:13quadratic bezier curves only need three
  819. 29:16control points so you only have to
  820. 29:18compute one on the middle of each
  821. 29:19triangle edge
  822. 29:21again the triangle corners will retain
  823. 29:23their original normal vectors to compute
  824. 29:25a control vector for the point halfway
  825. 29:28between the corners a and b follow these
  826. 29:30steps
  827. 29:31first find the average normal of a and b
  828. 29:33second construct a plane perpendicular
  829. 29:36to the edge connecting a and b
  830. 29:38finally reflect the average vector
  831. 29:40across this plane
  832. 29:42notice that when the normals are similar
  833. 29:44but slanted relative to the triangle
  834. 29:46plane the control normal points in the
  835. 29:48opposite direction this will create
  836. 29:50bumpy shading as if the surface is
  837. 29:52warping
  838. 29:53calculate the control vectors for the
  839. 29:55remaining edges
  840. 29:58[Music]
  841. 30:02to add this algorithm to your shader
  842. 30:04first add three more slots to the bezier
  843. 30:06control point array
  844. 30:08then call this function in your patch
  845. 30:10constant function which implements the
  846. 30:12formula explained before
  847. 30:14in your domain function calculate a
  848. 30:16quadratic bezier formula similarly to
  849. 30:18the position
  850. 30:20apply the smoothing factor to
  851. 30:21interpolate with the flat normal and be
  852. 30:23sure to normalize the final result
  853. 30:27there's one other thing to consider with
  854. 30:28all this the tangent vector it must
  855. 30:31always be perpendicular to the normal
  856. 30:33but if we change the normal vector it
  857. 30:35might not be
  858. 30:36to fix this find the barycentrically
  859. 30:38interpolated tangent vector and then
  860. 30:40take its cross product with the
  861. 30:42barycentrically interpolated normal
  862. 30:45then take that vector's cross product
  863. 30:47with the smooth normal the resultant
  864. 30:50tangent vector is once again orthogonal
  865. 30:52to the normal vector as well as the
  866. 30:54original meshes by tangent
  867. 30:57this should preserve tangent space
  868. 30:59nicely
  869. 31:02and that brings us to the end of this
  870. 31:03section on silhouette smoothing and
  871. 31:05bezier triangles
  872. 31:06this is a real magic behind teslazation
  873. 31:09and it makes it a powerful tool when
  874. 31:11combined with appropriately designed
  875. 31:12models
  876. 31:14experiment with all this and see what
  877. 31:16you can create
  878. 31:23another of teslazation's most common
  879. 31:25uses is adding extra geometric details
  880. 31:28to a mesh
  881. 31:29say you have a rough surface with mini
  882. 31:31bumps traditionally an artist would use
  883. 31:33a normal map to approximate the lighting
  884. 31:34for such a bumpy surface
  885. 31:36the model itself is not actually bumpy
  886. 31:39as you can clearly see if you view the
  887. 31:41surface's profile or shadow
  888. 31:43with teslazation however it's possible
  889. 31:46to modify the mesh to more closely
  890. 31:48resemble a complex surface
  891. 31:50the most common way to do this is using
  892. 31:52a height map
  893. 31:53also known as a bump map these grayscale
  894. 31:55textures encode height offsets in its
  895. 31:58color data
  896. 31:59the idea is simple read a height from
  897. 32:01the texture and offset vertices along
  898. 32:03their normal vectors by this height to
  899. 32:06implement that in a shader add a texture
  900. 32:08property for the height map and then
  901. 32:10sample it in the domain function
  902. 32:12remember sample texture 2d is only
  903. 32:14available in the fragment stage because
  904. 32:17it uses partial derivatives use sample
  905. 32:19texture 2d lod here accordingly you can
  906. 32:22turn off mipmaps for height maps used
  907. 32:24this way
  908. 32:26regardless add the sampled value to the
  909. 32:28vertex's world position by using it to
  910. 32:30scale the normal vector you can combine
  911. 32:33this with the smoothing techniques
  912. 32:34discussed above or just use the flat
  913. 32:37interpolated position in normal either
  914. 32:39way the algorithm is really that simple
  915. 32:42add an altitude property to adjust the
  916. 32:44height
  917. 32:45you might notice that if you use a
  918. 32:46height map without a matching normal map
  919. 32:49the mesh will look quite flat
  920. 32:51this is because the height map does not
  921. 32:53affect normal vectors
  922. 32:55although i would still recommend using a
  923. 32:57normal map it is possible to calculate
  924. 32:59lower quality tangent space normals from
  925. 33:02the height map alone
  926. 33:04in this case turn mipmaps back on for
  927. 33:06your height map since we'll sample it
  928. 33:08again in the fragment stage
  929. 33:11in the shader add this variable which
  930. 33:13holds the size of one texel or pixel on
  931. 33:16a texture in uv units make sure that the
  932. 33:19name matches a texture in your shader
  933. 33:20and unity will automagically calculate
  934. 33:23and set it for you then write this
  935. 33:25function which samples the height map in
  936. 33:27each neighboring pixel around a given uv
  937. 33:30coordinate from this we can calculate a
  938. 33:32tangent space normal with a little
  939. 33:34algebra divide the change in height of
  940. 33:36pixels across from one another with the
  941. 33:38change in uv space this gives us the
  942. 33:41slope in the u and the v directions
  943. 33:42which correspond to the x and y
  944. 33:44components of the tangent space normal
  945. 33:47multiply these with a scaling factor to
  946. 33:49adjust the overall strength of this
  947. 33:51improvised normal map
  948. 33:53and then normalize the final result
  949. 33:55convert this to world space like any
  950. 33:57other tangent space vector
  951. 34:00you'll probably need to adjust the
  952. 34:01normal strength until you get something
  953. 34:03that looks good and even then you might
  954. 34:05notice that these normals are not quite
  955. 34:07as detailed as a normal map it can't
  956. 34:09really be helped without taking more
  957. 34:11texture samples and that really starts
  958. 34:13to add up
  959. 34:14for this reason only use this technique
  960. 34:16if you're in a pinch there are many
  961. 34:18tools online which you can use to
  962. 34:19generate normal maps from a height map
  963. 34:21anyway
  964. 34:23height maps can also take the form of a
  965. 34:24function like purlin noise or an sdf in
  966. 34:28these cases evaluate the height function
  967. 34:30instead of sampling a height map
  968. 34:32here we're forced to calculate a normal
  969. 34:34vector and it can be a little tricky to
  970. 34:36figure out the math it differs per
  971. 34:38function but on the plus side they're
  972. 34:40often mathematically exact
  973. 34:43in this example i created a height map
  974. 34:45from perlin noise this has well-defined
  975. 34:47partial derivatives so i was able to
  976. 34:49calculate the normal vector like this
  977. 34:52if you scale the noise in any way be
  978. 34:54sure to also scale the resulting normal
  979. 34:56vector just remember that normals must
  980. 34:58be scaled inversely to geometry meaning
  981. 35:01divide instead of multiply
  982. 35:05you could calculate the normal along
  983. 35:06with the position in the domain function
  984. 35:08and then use that interpolated value in
  985. 35:10the fragment function
  986. 35:12however you can also just calculate the
  987. 35:14normal in the fragment function which
  988. 35:16gives a nicer more detailed result
  989. 35:19in this other example i created a simple
  990. 35:21sdf or distance function from points
  991. 35:24centered on these three little spheres
  992. 35:26when the sdf passes a threshold at any
  993. 35:29point on this mesh i deform the point
  994. 35:31backwards
  995. 35:33to calculate the normal in this
  996. 35:34situation i had to use another trick
  997. 35:38create two new points offset slightly
  998. 35:40from the original point along its
  999. 35:42tangent and by tangent vectors
  1000. 35:44calculate the sdf at all three points
  1001. 35:47and then apply the offsets
  1002. 35:49form a triangle with these deformed
  1003. 35:51points and calculate the normal vector
  1004. 35:53of the plane containing it using the
  1005. 35:55cross product this gives something nice
  1006. 35:57for lighting
  1007. 35:59this method usually is quite good for
  1008. 36:01continuous functions determined solely
  1009. 36:03by position so keep that in mind
  1010. 36:10as you can see teslazation is a
  1011. 36:13complicated subject but it opens up many
  1012. 36:15doors in the world of graphics
  1013. 36:16programming
  1014. 36:18although it can be expensive well-placed
  1015. 36:20teslazation can really polish up your
  1016. 36:22models and give your game that final
  1017. 36:24push over the finish line
  1018. 36:26i hope i've shown off a lot of
  1019. 36:27interesting uses for teslazation
  1020. 36:30including advanced culling per triangle
  1021. 36:33math
  1022. 36:34smooth silhouettes level of detail
  1023. 36:36quadratic normal vectors real height
  1024. 36:39maps and procedural geometry
  1025. 36:41personally i'll be using teslazation for
  1026. 36:44level of detail and wind effects in my
  1027. 36:46upcoming grass system
  1028. 36:48if you liked this tutorial and you'd
  1029. 36:50like to watch more like it please
  1030. 36:51consider subscribing to my channel i
  1031. 36:54want to take another moment to thank all
  1032. 36:55of my patrons for helping make this
  1033. 36:57video possible and give a big shout out
  1034. 36:59to my next gen patron creepy dooby doo
  1035. 37:02thank you all for your support
  1036. 37:04it means a lot to me
  1037. 37:05if anyone would like to download all the
  1038. 37:07example shaders from this tutorial and
  1039. 37:09all of my other tutorials in fact
  1040. 37:11consider joining my patreon
  1041. 37:13you can also really help me out by
  1042. 37:15liking this video and leaving a comment
  1043. 37:18did you learn anything in this tutorial
  1044. 37:20how do you want to make use of
  1045. 37:21teslazation in your project let's chat
  1046. 37:23about it
  1047. 37:24thanks so much for watching and make
  1048. 37:26games
  1049. 37:32[Music]
  1050. 37:46you

About this transcript

This page contains the full transcript of Mastering Tessellation Shaders in Unity! Easy LoD, Curved Triangles, Height Maps | Game Dev Tutorial by Ned Makes Games, generated from the public captions YouTube serves with the video. The transcript has 6,167 words across 1,050 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.