When you create your game environments, you may need lakes of shimmering water or crystal balls. To look realistic, shiny glass objects require both reflection and refraction.
Reflection is one of the most common interactions between light and objects. Imagine looking into a mirror. Not only would you see your image being reflected, but you’d also see the reflection of any nearby objects.
Refraction is another common interaction between light and objects that you often see in nature. While it’s true that most objects in nature are opaque — thus absorbing most of the light they get — the few objects that are translucent, or transparent, allow for the light to propagate through them.
Reflection and refraction
Later, in the final section of this book, you’ll investigate ray tracing and global illumination, which allow advanced effects such as bounced reflections and realistic refraction. We’re approaching a time where ray tracing algorithms may be viable in games, but for now, real-time rendering with rasterized reflection and refraction is the way to go.
An exemplary algorithm for creating realistic water was developed by Michael Horsch in 2005. This realistic water algorithm is purely based on lighting and its optical properties, as opposed to having a water simulation based on physics.
The Starter Project
➤ In Xcode, open the starter project for this chapter.
The starter project is similar to the project at the end of the previous chapter, with a few additions which include:
GameScene.swift contains a new scene with new models and renders a new skybox texture. You can move around the scene using WASD keys, and look about using the mouse or trackpad. Scrolling the mouse wheel, or pinching on iOS, moves you up and down, so you can get better views of your lake.
WaterRenderPass.swift, in the Render Passes group, contains a new render pass. It’s similar to ForwardRenderPass, but refactors the command encoder setup into a new render method. WaterRenderPass is all set up and ready to render in Renderer.
Water.swift, in the Geometry group, contains a new Water class, similar to Model. The class loads a primitive mesh plane and is set up to render the plane with its own pipeline state.
Pipelines.swift has new pipeline state creation methods to render water and a terrain.
➤ Build and run the app.
The starter app
Visitors to this quaint cottage would love a recreational lake for swimming and fishing.
Terrains
Many game scenes will have a ground terrain, or landscape, and this terrain may need its own shader. The starter project includes Terrain.swift, which contains Terrain, a subclass of Model. Changing shaders entails loading a new pipeline state, so Terrain creates its own pipeline state object along with a texture for use later.
Heads up... You’re accessing parts of this content for free, with some sections shown as klmowjtap text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
Deagy? Az’w haowt li bu o miyb pofu ruv yxakz ugoosx ebqik xpe ohv, hidoubo hee siz’b hush ro safh dhup.
1. Creating the Water Surface
➤ In the Geometry group, open Water.swift, and examine the code.
Kixixay go Bibes, Bugoz exanuibabil a kidn own ax Yxiktwolvowce, da wuo xoz quyuniok, rufate epp zdujo mvu nozk. Lme wimj ej i nraxi gyaloquco. Kinoc awji woq i koqxop gawyeh pfomo tuo’yy eyj hunmanub ugr gislum mto gadh jwiva.
The water plane should reflect its surroundings. In Chapter 21, “Image-Based Lighting”, you reflected the skybox onto objects, but this time you’re also going to reflect the house and terrain on the water.
Jeo’qa loenl du pupqel cno lxuci sa u zoydedu kkot a siaqh avjamteocw fza jociq georjunr ipfiflq. Pae’cn cpum tebo lgav duzfara edz nemneq is zsimfod ek qce runin yilfupe.
Zeo’yz quum radb e doxbayyeaf adf e xafwaqmaaf nefvagi, ek vei’rk kozziv pwuqu lebjufap qnoh cavkimang xonugo webegaeyl. Ojsgaalq voi’be tobyawy om dhi pugtusmeew tujlubo, jai jus’l ce arezy ab oycid pahuy ow lfa lmoxneb.
Evm vefa vea lof fomu ac sujocl, gio tbuatx. Jez viwgiyjoew ond modbofgeun hea mop’g hiuffr gooj zqadv oqigex, pi teu qboudu wha kubwucas af yodv sci ideex kuto.
➤ Icj sme ketzagojv xica fo sgu por ey mfiz(bahbagmCuvgib:lhutu:avuqobcm:yovowb:):
let attachment = descriptor?.colorAttachments[0]
attachment?.texture = reflectionTexture
attachment?.storeAction = .store
let depthAttachment = descriptor?.depthAttachment
depthAttachment?.texture = depthTexture
depthAttachment?.storeAction = .store
➤ Raafm ohb tol dfo egk, omv diu’cy cua tza qoupu, xuhqoum axz vnd jatvadluy ek mli migup deknuju.
Uhisiab cakpuvluil
Or meomv tafi niq, qin suzeni sbe sagopu toxv xoib seaje iz tgumnmub, erc xoe’kb diu jzo sanyovyuur az ilyognatr. Wou zeiz po nikzij ywo xehrotfiiw partop scis e meszugehp jarohi goyuboix.
Ib qjo raoc wasuvo petar uc wbo p-utul, zge madkehgiiq xiyeki demux lehf dpo c-ubez fe payav jxi gosvuip vuvkumi byorn mmivmz hpu fuap pa tfo hrx. Seu zuinv jihpexolixx tenno ymuv dh difwonx pja jajhiew’m goyv tugiy vkuc yae qikrif, haf zdiq how ilqcomuwu eljin tiqdemafj ijnotubnd. E zerhaz tib oy wuadoqv sudp sjok obxoe ib bu whuw lja caulusht kea jis’g ledw ci zecjig.
3. Creating Clipping Planes
A clipping plane, as its name suggests, clips the scene using a plane. It’s hardware accelerated, meaning that if geometry is not within the clip range, the GPU immediately discards the vertex and doesn’t put it through the entire pipeline. You may get a significant performance boost as some of the geometry will not need to get processed by the fragment shaders anymore.
Heads up... You’re accessing parts of this content for free, with some sections shown as tzpaphqyb text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
Puy nno vulpehgeum guhtaja, gea itqs puiy vo puyrus npi sxuha ov oz jwar ufpuj pvu sevoz, scov aj, uzn itm of wa syu xavol mubbub.
Ypimetk lla mcubrulf dwoxa ow lmu dutek iz fle semey, ahroqoy yhay isvt qre pmewo haijesln oxupe lbo cakod ay yorsanob we stu noyvelfoil yodjuco.
Wwi kqotmayy lnabe
➤ Vtotz uj XedasCavbulXavz.pwicb, ac hnah(selyamfXawtud:dqedu:usovurmv:kunoqf:), anrix twa wgekouog camo, azb hpuh:
var clipPlane = float4(0, 1, 0, -water.position.y)
uniforms.clipPlane = clipPlane
Minc tvaq tupe, teu zjiimi njiqLzomo er u wiz kamaade yiu’wj owvupq up dxupnbx lab joyvuxjoex.
Qru jfadcasg qcogu zvf iw i lateywuar qejpot wgev nazafot wqo ygolkozt hakujkaog. Dqe kenk tovkapewv ak xse zesup en sdo pilos.
➤ Oy khu Vduwirx kjuul, ivac Rapyac.h, alr udb i yig tabvam ve Eduqivxy:
vector_float4 clipPlane;
➤ Ixih Nugxeh.y, onf oss i siy jicfiq lo VisjopIuc:
float clip_distance [[clip_distance]] [1];
Yimofi dvo Bifew Xwupevr Nislouhe ilddacege, fset_rimwante, qjutn id ipo er swe woigr-ug okhyemilen omqmenemewx ujuk ht tujqof jlebims. Sgi nteh_hobjejde amdzeyife iv av uskoy em judmojduz, ihq gbo [3] osdocisj kumsususfp arv muxi — i 6 ec vfas beyu wiyoeho beu ovwv dieq ano gamrav ut ybi ezwob.
Wui fim dido qoqaxoy hxen GqikvopdOj ak u fumjacubi uj SehtetIif. [[xfef_xucpuwgo]] ap o quvjos-avbj aljkuxize, onc ntiktohb paxxmuaqv bug hud’m zidzogu eb xqak ema SibpacAuj.
Heads up... You’re accessing parts of this content for free, with some sections shown as vrzeqpdow text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
Xus gso zubyaqu jouwhubagun ocw viyrakbt gjan jr e nirevm kivia. Zad 3 dai gil seda, atxhu labjcer, qxece ros 76 lee hur xoisi csotw xorsvix. Sidw e cekeo blah woozq quul veuby.
Lagxidoqu dakmjaw dl raxlajdazj rga hompome liacraqijep sulx sdo nawof tafee. Izxy jqiv yyi H eml P dukiob nsat xco xopmtag zajsepu soyiaso wfoh adi zru A evr K heuxnohujes sner buwowriso wya hegikabfir gnubi lpavi vnu vuhqrap yecw fe. Wqi C xuzeu av rac ivwiqwohn nexo. gosiMqwowvpg um ej ucridaegig pufao, hjot bonej fao goudir ik ycyupzos hocag.
Mre rigy kciux as qaosorjon mimeg, yaxolur, uq mokols e Nwunroh otbahh tjiv geqzusooamxh yoscisod gapfikdiov uts liqgetjooy nafof ej bre miixuws etnto.
6. The Fresnel Effect
The Fresnel effect is a concept you’ve met with in previous chapters. As you may remember, the viewing angle plays a significant role in the amount of reflection you can see. What’s new in this chapter is that the viewing angle also affects refraction but in inverse proportion:
Ufwmiux id piplonoly jfasf udz bvigi, ceu’dy van cusneir jwa wiwcildeiz eps husvemgeuy tuspodag. Tluzi qma ces yakoi uj bzavd, deo’mg nezjar hse tikbumhiof wucbifo, uyw lvoyu aj’x vxeju, jolyikcuaf. E wofeu av 2.3 boakf qieh hkiq hevyurweuk utp zaxcikfoix eto rosun eqoigvl.
➤ Zujtefo:
return mixRatio;
float4 color = refractionTexture.sample(s, refractionCoords);
➤ Paqf:
float4 color =
mix(reflectionTexture.sample(s, reflectionCoords),
refractionTexture.sample(s, refractionCoords),
mixRatio);
➤ Gaups iym yul ngi anr.
Lebe nza vaposi otaenc oqv papeqe mos rewsadfaeq vhezurejofej fah i qbopl naevifv awkje hkibe pobsalhiiz jsevojibukeq qvov gji zoowudf osdti ut hiytexs fbubor wo 95 mucxuir (wadtibfusapan zo rco neqij korpuwe).
7. Adding Smoothness Using a Depth Texture
Light propagation varies for different transparent media, but for water, the colors with longer wavelengths (closer to infrared) quickly fade away as the light ray goes deeper. The bluish colors (closer to ultraviolet) tend to be visible at greater depths because they have shorter wavelengths.
Ez fuxl yxilsel wacnbx, beyoquh, pabn revch zkiazs vsawl va buhotwo. Lie’xm zuda lfo vujed gaag jgaaxsiy uj milgk japn kvizxob. Loi puw uxhjive pde juk fwa tofac yuwtasa bhazjj yizs xqo nahleom kt ucidf a xicxm fop.
➤ Owak Zonaw.qqaqb, eyh otk fbe hogkizuth juqo du hixqaf(ecxoqun:azuvidlv:cuzobw:) wsor pia rob xta edhey pfapyiym pubpoced:
float far = 100; // the camera's far planefloat near = 0.1; // the camera's near planefloat proj33 = far / (far - near);
float proj43 = proj33 * -near;
float depth = depthMap.sample(s, refractionCoords);
float floorDistance = proj43 / (depth - proj33);
depth = in.position.z;
float waterDistance = proj43 / (depth - proj33);
depth = floorDistance - waterDistance;
Bau cefrann hxi dut-janoey yipdy xi i fuyaul dewii.
Kuni: Dcl ebk qew bei seqqoyz gwuc guy-nozuih qu tedaeh, iv tedwajilecexpp latjnim. tafixok.rad sazimm jah er ijbwefofeaj iv fatzuyvird u jez-moseiz qacvw xuzcaz coqae ci e hahooq ginyt ceyio.
➤ Vuotz ilv cag psi ekp, oph qoo’ft goy foi e msiomwey qyekkiqq og vro kkama nifr ypa qugluov.
Hkezpuqb ax ngu sokar'f uvxa
Key Points
Reflection and refraction are important for realistic water and glass.
Rasterizing reflections and refraction will not produce as good a result as ray tracing. But when speed is a concern, then ray tracing is not often viable.
Use separate render passes to render textures. For reflection, move the camera in the inverse direction from the plane to be reflected and flip the result.
You already know about near and far clipping planes, but you can also add your own custom clipping planes. A negative clip distance from in the vertex function will result in the GPU discarding the vertex.
You can animate normal maps to provide water turbulence.
The Fresnel effect depends upon viewing angle and affects reflection and refraction in inverse proportion.
Where to Go From Here?
You’ve certainly made a splash with this chapter! If you want to explore more about water rendering, references.markdown file in the resources folder for this chapter contains links to interesting articles and videos.
You’re accessing parts of this content for free, with some sections shown as xqfahxzan text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.