Deceit in Depth

文章推薦指數: 80 %
投票人數:10人

If you do not write one, then OpenGL will happily use gl_FragCoord.z as the ... is always written to, no matter what conditional branches your shader uses. DeceitinDepthPrev Chapter 13. LiesandImpostors NextDeceitinDepth Whiletheperspectiveversionlooksgreat,thereremainsoneproblem.Movethetime arounduntiltherotatinggreysphereducksunderneaththeground. Figure 13.6. BadIntersection Hmm.Eventhoughwe'vemadeitlooklikeamathematicallyperfectsphere,itdoesnot actlikeonetothedepthbuffer.Asfarasitisconcerned,it'sjustacircle (remember:discardpreventsdepthwritesandtestsaswell). Isthattheendforourimpostors?Hardly. Partofthefragmentshader'soutputisadepthvalue.Ifyoudonotwriteone,then OpenGLwillhappilyusegl_FragCoord.zasthedepthoutputfromthe fragmentshader.Thisvaluewillbedepthtestedagainstthecurrentdepthvalueand,if thetestpasses,writtentothedepthbuffer. Butwedohavetheabilitytowriteadepthvalueourselves.Toseehowthisisdone, loadupthetutorial(usingthesamecodeagain)andpresstheHkey. Thiswillcauseallimpostorstousedepth-correctshaders. Figure 13.7. DepthCorrectImpostor Thisshaderisidenticaltotheraytracedversion,exceptfortheselinesinthe fragmentshader: Example 13.4. DepthCorrectFragmentShader Impostor(cameraPos,cameraNormal); //SetthedepthbasedonthenewcameraPos. vec4clipPos=cameraToClipMatrix*vec4(cameraPos,1.0); floatndcDepth=clipPos.z/clipPos.w; gl_FragDepth=((gl_DepthRange.diff*ndcDepth)+ gl_DepthRange.near+gl_DepthRange.far)/2.0; Basically,wegothroughtheprocessOpenGLnormallygoesthroughtocomputethe depth.Wejustdoitonthecamera-spacepositionwecomputedwiththeraytracing function.Thepositionistransformedtoclipspace.Theperspectivedivisionhappens, transformingtonormalizeddevicecoordinate(NDC)space.Thedepth rangefunctionisapplied,forcingthe[-1,1]rangeinthefragmentshadertotherange thattheuserprovidedwithglDepthRange. Wewritethefinaldepthtoabuilt-inoutputvariable gl_FragDepth. FragmentsandDepth ThedefaultbehaviorofOpenGLis,ifafragmentshaderdoesnotwritetothe outputdepth,thensimplytakethegl_FragCoord.zdepthasthe depthofthefragment.Oh,youcoulddothismanually.Onecouldaddthefollowing statementtoanyfragmentshaderthatusesthedefaultdepthvalue: gl_FragDepth=gl_FragCoord.z Thisis,intermsofbehavioranoop;itdoesnothingOpenGLwouldnothavedone itself.However,intermsofperformance,thisisadrastic change. Thereasonfragmentshadersarenotrequiredtohavethislineinallofthemis toallowforcertainoptimizations.IftheOpenGLdrivercanseethatyoudonotset gl_FragDepthanywhereinthefragmentshader,thenitcan dramaticallyimproveperformanceincertaincases. Ifthedriverknowsthattheoutputfragmentdepthisthesameasthegenerated one,itcandothewholedepthtestbeforeexecutingthe fragmentshader.Thisiscalledearlydepthtestor early-z.Thismeansthatitcandiscardfragments beforewastingprecioustimeexecutingpotentiallycomplex fragmentshaders.Indeed,mosthardwarenowadayshascomplicatedearlyzculling hardwarethatcandiscardmultiplefragmentswithasingletest. Themomentyourfragmentshaderwritesanythingto gl_FragDepth,allofthoseoptimizationshavetogoaway.So generally,youshouldonlywriteadepthvalueyourselfifyou reallyneedtodoit. Also,ifyourshaderwritesgl_FragDepthanywhere,itmust ensurethatitisalwayswrittento,nomatterwhatconditional branchesyourshaderuses.Thevalueisnotinitializedtoadefault;youeither alwayswritetoitornevermention“gl_FragDepth” inyourfragmentshaderatall.Obviously,youdonotalwayshavetowritethesame value;youcanconditionallywritedifferentvalues.Butyoucannotwritesomething inonepathandnotwritesomethinginanother.Initializeitexplicitlywith gl_FragCoord.zifyouwanttodosomethinglikethat. ForkmeonGitHubPrev Up NextCorrectChicanery Home PurloinedPrimitives



請為這篇文章評分?