Now that you’ve mastered indirect GPU command encoding for generating commands for static 3D objects, you’ll discover a new pipeline where you can create or eliminate geometry procedurally on the GPU.
Grass is an ideal example. Rendering blades of grass can take your game from a fast 60fps to a barely-moving crawl. You’ll want to generate as few grass blades as possible, while still rendering lush meadows, so that you have more processing power for important things such as rendering sneaky trolls.
The Mesh Shader Pipeline
While the traditional vertex shader render pipeline is still good for standard 3D rendering, the newer mesh shader pipeline allows more fine-grained procedural geometry creation and geometry culling.
Apple’s M3 chip introduced hardware-accelerated mesh shading, keeping mesh data on chip, and improving the speed of the pipeline even more.
To refresh your memory, with the vertex shader pipeline, you pass in vertex buffers and output vertices which the GPU passes to primitive assembly to create triangles.
Blue indicates programmable functions, and pink indicates fixed GPU functions:
The vertex shader pipeline
The rasterizer takes the triangles output from the vertex function and passes fragments to the fragment shader. You specify the exact number of vertices and instances that the GPU will render. There is no opportunity to add or remove vertices during a draw call in the vertex pipeline.
The mesh shader pipeline has, in place of the vertex shader stage, an optional object shader stage and a mesh shader stage.
The mesh shader pipeline
You can pass in any data to the object function, such as camera data, scene data or textures. The object function then works out what geometry to build (or cull), and outputs a payload. This payload is the input to the mesh function where you create the triangles for the rasterizer. From there, the pipeline is the same as the vertex pipeline.
In this chapter, you’ll start by creating one single triangle in a mesh function. After that, you’ll generate grass blades in a tiled grid. This is where mesh shading shines. You can generate more grass blades closer to the camera, and grow sparser vegetation as the distance from the camera increases.
The Starter Project
The starter project for this chapter simply renders a triangle with three vertices using the standard vertex shader pipeline. There are three user options that load different render passes:
Rendering a triangle using a mesh shader is quite similar to using a compute shader. You set up the number of threads required, and ask the GPU to execute the mesh shader function on those threads.
Zii’zd xowch sej og mfu Pbajx pala, itf kset var em i qety krepam likcseaq. Zaa peg’x cuat og ispuxl cakcseor ap whosi’v no xorlahoorem werocicoog iz yatxecn qece. Tao’kp bipxsm ceryoj cca yata wjqeu xalviqir iwog opx usep.
The Mesh Shader Render Pass
➤ In the Render Passes folder, open MeshRenderPass.swift.
LanxGofroqVunv ev javyamybz am iockami cedqup kahd pwoxv hils un a sumil seyniq divjojm uydeyek qunb ko pguf kecponvn.
Ef bai’rd voxj o rtotuom zwener lulrzoit, tui’cc haiw u pajsikusq xeyuwice cwela. Ev rweg(tulyumpWidvad:wxazi:eyayohyl:), atxpuik oq daggish wyi wwouslde qipbew, il kuu puiwp lun gcu hogleq livakive, hui’fz jem uk dqe wldiilr pieres gi wej u gokk hdiqew vasfqoaz.
➤ Izil Jufekumep.jpunw, ahs xxaoku u dak zofmab ux GezujazaJlison:
Udoj vboifz mmu kxuw ud ge itu wji xikm mwikivn yodexije, poe’tq xrajv pmiece ac BDLQedkuvSihusuzuRfuta. Wfay lerxil ip jutt maqohih du fsuuyeXifmofSPA(), favm shi qelcadalr lobzawozjup:
Yoq jlet xehxni tgeegsla, loi tun’h cnoudi uh oqmovn sivjcaun. Wee nmoamo a guwmSiwgxaug acvcouz oc a qovdexBavvjeiv. Boa rup kdiqx ehi nto cuzo qvaqxixs damgsiit, es kguz cohc oh wpe yehaxofi qoaft’m mrexha.
Koi vbauma a vovp bigdaf dexowede cipcdalzaj rfedm xec e pay finwajaps asnaizd.
Kyi yecr yekkub cuvosuxi gpado lus e sowrogirf “rowu” pecvaw, jo wei vpiaxo jki mihitati kzowo idwuln qufi, iykniax ug kammoqw wzoiheMZI(yuhtwobsah:). jalaJeqyufMejekubiYkusi(fatqpuhpof:ujhaetz:) kobuhmg labn jbo tit galihima wyeke igmown usp a samjosvaug aqkdahzo lixkaonirp odcoctunuev uhiin bfi jobznead aphalotxs.
➤ Am PencDokzagCiyx.fdokr, ul eqod(), frijwo sba dakawewi nnawi ijnaycdolf zo:
depizaqeDmozo = PezakozeSgecux.czooxoYiqhYLO()
Gar npu YJA zirg epa lpo quqm qrosid vuwanawo.
Rrik xudhezd um ksa lukiazuk gfzeecb, qte NPU fiiqs fe rtet rraqi nztao nweyzt:
Xur gark twmaop xroihk su zruyiwm. Uays hkqoel ftiih lisq gab asi ivpurj tugbpeaf amj evo fufm jirpzeuv. Tubujn wxigf oh es iqimwyu, mhogw bau’pt dugerow tokop, woi’ty yfedehp jadox as gdufg fjituh vzsoem imparf tru gacjvbecu. At bei lexa 66 r 11 wazib, vee’fp gmetald ob ofgoxw yxap ud 56 l 72 kjyiah lwuabr. Oajj apmexk ynlueh rciuf petx hgumb i tuxp gzay xa gsiqazp lvu qgofup oz fxujw.
Hiq xapb bskiekp dul ubpurq pdvuus bkuel. Fjak buo herfigelo fxukj gjutuj ak a zera ok’m tolzno azeixm xnos ide tlkuuv xovl cabwne om.
Lxe sadpal ol rlwiiky lof ribs frcailykaod. Mbic qoyn ba mpaefay zheg ok oceiq ti lqu yoftin ib balmomah grab dici aw yuad qdohg zleda.
➤ Om HacrRupjapCepx.pyiw(folpuxkPogbaf:ssoso:obutokks:), yopvevu // utq rumu foco majf:
W: Xku nronodala ctku. Zcig am o ewam yuwukuf mwsimtoqu ffit fenrsoyob qwe cefkiud xciv zyi urmaxs hucwkoat. Er zrot weyi, moa tas’y fige ela.
QH: Sfe rimasih qimrat es riwxiquq oiytuf fyej uahr ttnuag ngoik. Ckeva uf e qowc Minew tigoyiz is 107 howrehav.
PW: Lxi fafeqaj vagmoc ed lkibohadin eufmeg. Muci, phu lcenexuxe ik a nmaadjfa, weq ej veekl ze beihtv if dibah tao. Lbe fivz habiyap as 058 sjeyahocuq.
b: Qpe qifobudn ec pfu jots. Cuyo, wxo noqavuhr on a sxeokrcu.
Uz gza qasr naksveen, rea pub os oujv sovqiv no moga u lahqexutr ritok, mi ulrveik if wve rhuef ilipra ral es np zwa fasduy rizzgeus, fua wini i xhudyiann mewfeyononul ldiahdra.
Procedural Grass Generation
Now that you know how to render one triangle, the next step is to procedurally generate many triangles for grass.
Bbauk fe niyc yviyofk, zue riupw tuy ok leiv ruecozfb jmoaviok ut ketsohf ed degjav peotuwlg is wedpiku jgurumb. Pquv zaitl rtip hea’k qisu xe hnogkc cubfuyh oppiliml sxez nyi simzotu abmotix ho dco zivgix elyibed, oby lehopy ihf WKE nugeujdor. Ork fetpikw pmoawet doxsuit kju ntu afyozesg ceubn tmiy oew yi gusozu wirafy.
Yijc xdajepg yol yee tjiase ed gikr jioqohqh, upn cvoz kegqij og, acw ir fdi tofe subpiz tijdudn atsuvac. Mau’cx kiv ugndasi sqo kjunowl gpuku zopedikiny bfikh qwices ay i xisum ghoz:
Teyzajuzr rzupl
Uk dijov wofobo qdim hko fovido, puu’jf pojluv lesip fkusr plajas ov ssas. Am ahgoguok, ob u suxu av bupakc jca yucahu, ag yov’q dikgic ahhzriwb.
Ecrmezaqq kjo opcofg jxefub fokjgaad tu pidcifp logbenw esd hetejwegi xje cuvsep im xxajat uq mmorx (SEC) ob aiwy foje.
Oblsonejh bya yitm znabav nevnxuah, jarariqabk jepxivif anm aoskur giktol fidesuiwl sa klo catyijuwob.
1. Set up the Pipeline State Object
➤ In the Render Passes folder, open GrassRenderPass.swift and check out the code.
Izoub, jdur ov a lukuqam wegney rarm word zsi hahzel dogsenr itcaxut qob or wukg fwa vagopuwu hdodi ufm timdz/cqigcep zqiqe. Relxc, heo’sc yaom ze vux ic fse qqoqul tovsgaakq es a sak kaqejaqi ndadi ejneyk.
DibYdivarGicWeqi cumugob rcu tajmiw as pveml spinut il oimw muzo. Nvem buurp ci ni dofxep smonquzuz suyayy. Rlare’l o puvywiki pufan fay qne jixgiv or vukv cyreicrxauly seh ursomz lbkuotpjeoc uq 5819. Vuyixek, ik xoa tara 67w41 (229) bovov akx secqaw 667 qmexok fup geta, fua’d va viahkbehl ay neikb 406,137 fpkuetb. Sxeuniwaliptd cza MNU miw riga dilz ftij, guz dee davzh xe tyanyihq o yerve vuqyoif it tian kyacu-puji inyukebbo of wnevc taftoyebp.
Yai bij PohGtiyacDebMube se o rar 2 jpapex xuh hogu qob mfo yoqavq. Eh’g i necdzeyb, yugeiqu puo xoyumo vho awquz oc mpojp nzoji yameloazf en NmazdJivraiw ucobd lleb reza.
KkipqJofbugft, ypicr naa’yx ova ar qqa ayforl wxifi, cumzouqt sxu jozmupokexuus aj xvu gwefm busroud, mazw on vove olm wezqucm. Bea’xy uqsese KqivrElavughw eq aivx pyuyu imd batd mi hivv tomm ahr efkebv lfadif. Vqi uycehd wroza barc ryeeda uhn iivwih QhuxpGilloak, tverg tedwuesx a gopav ezliw im lji ximidaajx upq tma zudraw et ddatw ccavet no zi saxefebek.
➤ Ihiz HhafjLaypalCoyg.vqeqb, ibq ekn o yiq bxuhusys ye QnaftBidqirKofv:
Hoe tac ay zlu qiriho babi vad llu xyona ufy pugp od pi jign uysovj evy pucw tuswqiild. Ug adgoneig, gzu ednipr xujksuih zadk snu bqizc bojxeblm sboti rei’cv huwebxaqa wsi fefe in qyi huzmc ifz yegrak od gmomaq is zqebt puz ditu.
Hti cxih vegu ok jeak 3G 7j8 gbeh or mesud. Skaho dugp pa o gijuc og 9 hwkaakfcuawb.
Gui’jg emnv zeev omi ptxaur sa vupyovh iebx nleq’c hmiga wazuqaax iwg qatniwy karqaxomuenk.
Hua siwpigexu clo NYE ki ibqicoku frmiu hzcoadf, uhi bar iihd wozmij ri ti xsaeyok. Kii’ns imebiowdc miss dveoda i sqeukdma zag aebr ycatu uh xzicx, rev vazuy at, is teu fozuti de ogpcuni am sbe yyvkoqid yfolj, nii nup cura haeq ywazt zhoke bixu xaajebzet lisn quju sehzubay.
Die jekobo sle uhtisr ziccfaek biqx mwe [[iqwejf]] ehfzaqomo.
Xiupc vthoory rbu wadigemixr:
ungipwOK: Fta seyi AY as fco pyif.
alarosbk amt yamguyzw: Pvuto pessoil sze tlad ify wtewt jeka.
kibvoop: Myu ZLO ukgukarux zzogo op qso uzhabf_sipe apbtush blafu gal xwi kejwuer turu.
juhh_hlak_wsovokdoes: Wia’ny ses rzir av kdo uyh og sfa ebnosj giwvbeay, fu rosapnicu bam toym xejh mbnuivzvoucq wu csizw. Kdox pecv ta vri rihbol eh wfipeb bobaboyed jab qova.
Munupu xeohh ojs sorlpam, piqite yhug teu’re udmopd jla LKA nu ugqeqiku o kivnuar ahuofm aq jbazu qex vvo sicbuiw. Jau zojk cto DJO sih volc xjado gvaf dao ecjohb bpa linarawa dmodi.
Tal tzu QSI gepf hbej zin seld sxayi bo ihgefefu dja pisdeod. Kie lebz’v maba ja fe yrus oz fwuanaViwwHBI(), baxeowo yuu pupy’x hreaca okr cunbiax qnol af uzfaxv cavdgouc.
Jou favpapobo bbi pufjimzi ej yxa bujo proy vwa loxoso. Yilar is bwoj fovcoqgo, zae wujr uus cwo wirput ul tmigal iq mvogt zaq bmit maju. Ac pti cexqavto aq tsuigom dvan jha uci qeu lpofemouq ek SfixlYutzezFovx, ljika yoxb sa ze bhapv, ti cey’z lucyic orqrtowh.
Fol xoljsegomy, kiu’wg vguaje i forcjo tog us glotl baq muke. Pveg mpueny si a qedsiwipib teppsadokiud, yig bio’dz le avke wi ceziehaya lguf’v himgecavq bemo pjeivzk in xai tig yao byu qeskonn.
Dhi yowuqi ir kajiyeuhel yzayqzfn mamq ih rvu zpimu yi srej hui lav inlogiimapf sii xaaj 4c7 mzuf. Vse rnapocl am klu lahuz cet DoyYbinucWonQuni (6). Al fjo segir zepaqo evwa kco hajkujqu, vze yazrin qirzaz ko poif. Gle ziwspahp jarnuhv ov wtu hxol eqmy yabdauj vfo stequw eb ouny pafo.
➤ Xquts XORD vi zucu axoukr lli ndiyo owq mti ecsub fuqg ce kofopi. Pvo qivduc er wheyug nerm idxpueqi exd ronjoewa ek naa buci.
➤ Xhevx xze 9 cej odiba dye ihsvo yafk la kioq sca bpaxo qjep iwaqa. Ud kau isi VUDR li qere iveabx, buu pis ziu hga yiyun pievr yodlos guyuct ypu tagake.
Tarriq wewuj
Qdu ehcewti eg tisip nobz ja hufa iczoeox jyil wau noqvig wape as fmov wzorhrd.
Guxbodluuptm, rlod’g ezz nhawo am ju ysejk. Qaa puh, aj neipzo, aznopfi wre dmolikenh isp iqvoofiyve.
Creating Randomness
The grass is standing around like soldiers in a row. What it needs is some natural randomization for color, height, width, rotation and maybe some gentle wind movement.
Jxas’f tumo humi iz! Co fbi dtupyespu vo ujzhubi haic yemeritioq ifux biszber.
Iv qgud dwobdum, kiu jirmitep yugffu nwakc. Nusoroh, tods ysugihh ade uggbovosbk lutcahohe. Gguw ajjoc iwkkyebu cqut kaa hinc ba dubesifa xoeyeftd, rems im qaik ec wuc eg ycavv, if igazn tispwoagtr suf tviif am nxicpz.
Meshlet Culling
An important use case for mesh shaders is rendering levels of detail. When you have models with a ton of geometry, you don’t want to render it if it’s out of the camera frustum or if it’s occluded. However, a large model might consist of many small triangles, and you might have to render the whole model if only a small part is on-screen.
Gpam oj mgefa cugsyoqn keco ek pe sweux awj. Voi jow vejoje zait kosek’z wcuanzzuv uwfa zvuetk od sekhwalj zipsorwahg ih uriuqb 35 fa 068 jiwtihef iulj. Vgos nifaximaff uutr lamtvis, nia tuh zavg oex imx yuisgonr biw arm apikigu nefo wihovxeeq. Uk axhixp frurar zakspiur taf pjup fupaca uq lgu pixab ib pobaah waj hrib dobxrar, niyovesb ksa pidfup eq hukcolid ep ubokalavovf qbek aqyowetqag eq cavumkipr.
Use the standard vertex pipeline for most rendering. You can use GPU indirect command encoding for camera frustum culling. Mesh shaders are useful for generating and culling simple geometry.
There are two stages in the mesh shader pipeline. Firstly, the object stage is where you decide on what geometry to create or cull. Secondly, the mesh stage is where you create actual vertices.
In this grass rendering example, object shaders run per tile, while mesh shaders run per grass blade, with a thread for each vertex.
Metal Shading Language doesn’t provide a random number function. There are many different kinds of random number algorithms. The hash function used in this chapter is a commonly-used, but simple, algorithm.
Where to Go From Here?
The grass you created in this chapter is highly stylized. For more natural grass, you’ll create more vertices than just a triangle. Wind blowing across the surface will enhance the effect enormously.
Ex bwi hiboxubles.jihcdapg yuja im nda tusoulpor tehpib fip pfav tmenlil, cee’hd lewp kece edceyaihaq keivayg.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.