![]() ![]() ![]() ![]() ![]() It uses the Flat and Wireframe Shading tutorial as a basis. There's a bunch of subtle constraints that go into this too – for example, all domain positions written by the Tessellator need to have both u and 1-u (and also v and 1-v) exactly representable as float there's a bunch of necessary conditions like this so that Domain Shaders can then produce watertight meshes (this rule in particular is important so that a shared edge AB between two patches, which is AB to one patch and BA to the other, can get tessellated the same way for both patches).This tutorial covers how to add support for tessellation to a custom shader. the same input has to produce the same output, always). What's intentionally not nailed down is the order in which vertices or triangles are produced – an implementation can do what it wants there, provided it does so consistently (i.e. The Tessellator has all kinds of symmetry and precision requirements as far as vertex domain positions are concerned, you can basically expect bit-exact results between the different HW vendors, because the D3D11 spec really nails this bit down. There's the "isoline" patch type, which I didn't go into at all (if there's any demand for this, I can write it up). In short, there's no problems with output buffer management, other than the fact that, again depending on the primitive type, we might need lots of output buffer space which limits the amount of parallelism we can achieve (due to memory/register constraints).Īs usual, I cut a few corners. That's definitely an advantage over Geometry Shaders for lots of Geometry Shaders, it's possible to know statically how many output vertices will be generated (for example because all the control flow leading to emit / cut instructions can be statically evaluated at compile time), and for all of them, there's a guaranteed maximum number of output vertices, but for HS, we have a guaranteed fixed amount of output data, no additional analysis required. If we Hull Shade 16 hulls at a time, we know exactly where the data for each hull will end up before we even start executing the shader. All of this is statically known at compile time no dynamic run-time buffer management necessary. The other nice attribute of Hull Shaders is that, unlike Geometry Shaders, they don't have a variable amount of output data they produce a fixed amount of control points, each which a fixed amount of associated attributes, plus a fixed amount of patch constants. That by itself turns out to be tricky in some places I'll get to that later. All the HW needs to make sure is that it's possible to get watertight meshes, preferably with reasonable efficiency. If you do everything correctly, you'll get a nice watertight mesh, otherwise – well, that's your problem. The hardware doesn't care – it will process each patch by itself. The TFs for the inside of the patch can be chosen freely but if two patches share an edge, they'd better compute the exact same TFs along that edge, or there will be cracks. The basic mechanism is that each patch has multiple tessellation factors (TFs), which are computed in the Hull Shader: one or two for the actual inside of the patch, plus one for each edge. This is a topic all by itself and requires, among other things, great care in the Domain Shader code I'll skip all the details about expression evaluation in shaders and stick with the basics. The solution – which you've already encountered if you've written a Hull or Domain shader – is to make all of the actual tessellation work purely local and push the burden of ensuring watertightness for the resulting mesh down to the shaders. ![]()
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |