Tutorial 49 - Cascaded Shadow Mapping - OGLdev

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

If we can find a way to use a dedicated shadow map for closer objects and a different shadow map for distant objects then the first shadow map will only need to ... Background Let'stakeacloseuplookoftheshadowfromtutorial47: Asyoucansee,theqaulityoftheshadowisnothigh.It'stooblocky.We'vetouchedonthereasonforthat blockinessattheendoftutorial47andreferredtoitasPerspectiveAliasingwhich meansalargenumberofpixelsinviewspacebeingmappedtothesamepixelintheshadowmap.Thismeans thatallthesepixelswilleitherbeinshadoworinlight,contributingtothesenseofblockiness. Inotherwords,sincetheresolutionoftheshadowmapisnothighenoughitcannotcovertheviewspace adequately.Oneobviouswaytodealwiththisistoincreasetheresolutionoftheshadowmapbut thatwillincreasethememoryfootprintofourappsoitmaynotbethebestcourseofaction. Anotherwaytodealwiththisproblemistonoticethatshadowsclosertothecameraafarmoreimportant intermsofqualitythanshadowofobjectsthatarefaraway.Distantobjectsaresmalleranywayand usuallytheeyefocusesonwhathappenscloseby,leavingtherestasa"background".Ifwecanfindaway touseadedicatedshadowmapforcloserobjectsandadifferentshadowmapfordistantobjectsthenthe firstshadowmapwillonlyneedtocovertheasmallerregion,thusdecreasingtheratiothatwediscussesabove. This,inanutshell,iswhatCascadedShadowMapping(a.k.aCSM)isallabout.Atthetimeofwritingthistutorial CSMisconsideredoneofthebestwaystodealwithPerspectiveAliasing.Let'sseehowwecanimplementit. Fromahighlevelviewwearegoingtosplittheviewfrustumintoseveralcascades(sinceitdoesn'tneed tobejusttwoasinthepreviousexample).Forthepurposeofthistutorialwewillusethreecascades:near,middleand far.Thealgorithmitselfisprettygenericsoyoucanusemorecascadesifyoufeellikeit.Everycascadewill berenderedintoitsownprivateshadowmap.Theshadowalgorithmitselfwillremainthesamebutwhensampling thedepthfromtheshadowmapwewillneedtoselecttheappropriatemapbasedonthedistancefromtheviewer. Let'stakealookatagenericviewfrustum: Asusual,wehaveasmallnearplaneandalargerfarplane.Nowlet'stakealookatthesamefustumfromabove: Thenextstepistosplittherangefromthenearplanetothefarplaneintothreeparts.Wewillcallthisnear,middleandfar. Inaddition,let'saddthelightdirection(thearrowontherighthandside): Sohowarewegoingtorendereachcascadeintoitsownprivateshadowmap?Let'sthinkabouttheshadow phaseintheshadowmappingalgorithm.Wesetupthingstorenderthescenefromthelightpointofview.This meanscreatingaWVPmatrixwiththeworldtransformoftheobject,theviewtransformbasedonthelightand aprojectionmatrix.Sincethistutorialisbasedontutorial47whichdealtwithshadowsofdirectionallights theprojectionmatrixwillbeorthographic.IngeneralCSMsmakemoresenseinoutdoorsceneswherethe mainlightsourceisusuallythesunsousingadirectionallighthereisnatural.Ifyoulookatthe WVPmatrixaboveyouwillnoticethatthefirsttwoparts(worldandview)arethesameforallcascades. Afterall,thepositionoftheobjectintheworldandtheorientationofthecamerabasedonthelightsource arenotrelatedtothesplittingofthefrustumintocascades.Whatmattershereisonlytheprojectionmatrix becauseitdefinestheextentoftheregionwhichwilleventuallyberendered.Andsinceorthographic projectionsaredefinedusingaboxweneedtodefinethreedifferentboxeswhichwillbetranslatedinto threedifferentorthographicprojectionmatrices.Theseprojectionmatriceswillbeusedtocreatethethree WVPmatricestorendereachcascadeintoitsownshadowmap. Themostlogicalthingtodowillbetomaketheseboxesassmallasposibleinordertokeeptheratio ofviewpixelstoshadowmappixelsaslowaspossible.Thismeanscreatingaboundingboxforeachcascade whichisorientedalongthelightdirectionvector.Let'screatesuchaboundingboxforthefirstcascade: Nowlet'screateaboundingboxforthesecondcascade: Andfinallyaboudingboxforthelastcascade: Asyoucansee,thereissomeoverlapoftheboundingboxesduetotheorientationnofthelightwhich meanssomepixelswillberenderedintomorethanoneshadowmap.Thereisnoproblemwiththat aslongasallthepixelsofasinglecascadeareentirelyinsideasingleshadowmap.Theselectionof theshadowmaptouseintheshaderforshadowcalculationswillbebasedonthedistanceofthepixelfrom theactualviewer. Calculationsoftheboundingboxesthatserveasthebasisfortheorthographicprojectioninthe shadowphaseisthemostcomplicatedpartofthealgorithm.Theseboxesmustbedescribedinlightspace becausetheprojectionscomeafterworldandviewtransforms(atwhichpointthelight"originates"from theoriginandpointsalongthepositiveZaxis).Sincetheboxeswillbecalculatedasmin/maxvalues onallthreeaxistheywillbealignedonthelightdirection,whichiswhatweneedforprojection.Tocalculate theboundingboxweneedtoknowhoweachcascadelookslikeinlightspace.Todothatweneedtofollowthese steps: Calculatetheeightcornersofeachcascadeinviewspace.Thisiseasyandrequiressimpletrigonometry: Theaboveimagerepresentsanarbitrarycascade(sinceeachcascadeonitsownisbasicallyafrustumand sharesthesamefield-of-viewanglewiththeothercascades).Notethatwearelookingfromthetop downtotheXZplane.WeneedtocalculateX1and X2: ThisgivesustheXandZcomponentsoftheeightcoordinatesofthecascadeinviewspace.Using similarmathwiththeverticalfield-of-viewanglewecangettheYcomponentandfinalizethecoordinates. Nowweneedtotransformthecascadecoordinatesfromviewspacebacktoworldspace.Let'ssaythatthe viewerisorientedsuchthatinworldspacethefrustumlookslikethat(theredarrowisthelightdirection butignoreitfornow): Inordertotransformfromworldspacetoviewspacewemultiplytheworldpositionvectorby theviewmatrix(whichisbasedonthecameralocationandrotation).Thismeansthatifwealready havethecoordinatesofthecascadeinviewspacewemustmultiplythembytheinverseoftheviewmatrix inordertotransformthemtoworldspace: Withthefrustumcoordinatesinworldspacewecannowtransformthemtolightspaceasanyotherobject. Rememberthatthelightspaceisexactlylikeviewspacebutinsteadofthecameraweusethelightsource. Sincewearedealingwithadirectionallightthathasnooriginwejustneedtorotatetheworldsothat thelightdirectionbecomesalignedwiththepositiveZaxis.Theoriginoflightcansimplybetheorigin ofthelightspacecoordinatesystem(whichmeanswedon'tneedanytranslation).Ifwedothatusingtheprevious diagram(withtheredarrowbeingthelightdirection)thecascadefrustuminlightspaceshouldlooklike: Withthecascadecoordinatesfinallyinlightspacewejustneedtogenerateaboundingboxforit bytakingthemin/maxvaluesoftheX/Y/Zcomponentsoftheeightcoordinates.Thisboundingbox providesthevaluesfortheorthographicprojectionforrenderingthiscascadeintoitsshadowmap. Bygeneratinganorthographicprojectionforeachcascadeseparatelywecannowrendereachcascade intodifferentshadowmap.Duringthelightphasewewillcalculatetheshadowfactorbyselecting ashadowmapbasedonthedistancefromtheviewer. Sourcewalkthru (ogldev_shadow_map_fbo.cpp:104) boolCascadedShadowMapFBO::Init(unsignedintWindowWidth,unsignedintWindowHeight) {   //CreatetheFBO   glGenFramebuffers(1,&m_fbo);   //Createthedepthbuffer   glGenTextures(ARRAY_SIZE_IN_ELEMENTS(m_shadowMap),m_shadowMap);   for(uinti=0;iOnRender();   ShadowMapPass();   RenderPass();   OgldevBackendSwapBuffers(); } ThemainrenderfunctionintheCCMalgorithmisthesameasinthestandardshadowmappingalgorithm-first renderintotheshadowmapsandthenusethemfortheactuallighting. (tutorial49.cpp:211) voidShadowMapPass() {   CalcOrthoProjs();   m_ShadowMapEffect.Enable();   Pipelinep;   //Thecameraissetasthelightsource-doesn'tchangeinthisphase   p.SetCamera(Vector3f(0.0f,0.0f,0.0f),m_dirLight.Direction,Vector3f(0.0f,1.0f,0.0f));   for(uinti=0;iGetPos());   m_csmFBO.BindForReading();   Pipelinep;   p.Orient(m_quad.GetOrientation());   p.SetCamera(Vector3f(0.0f,0.0f,0.0f),m_dirLight.Direction,Vector3f(0.0f,1.0f,0.0f));   for(uinti=0;iGetPos(),m_pGameCamera->GetTarget(),m_pGameCamera->GetUp());   p.SetPerspectiveProj(m_persProjInfo);   m_LightingTech.SetWVP(p.GetWVPTrans());   m_LightingTech.SetWorldMatrix(p.GetWorldTrans());   m_pGroundTex->Bind(COLOR_TEXTURE_UNIT);   m_quad.Render();   for(inti=0;iGetPos(),m_pGameCamera->GetTarget(),m_pGameCamera->GetUp());   Matrix4fCam=p.GetViewTrans();   Matrix4fCamInv=Cam.Inverse();   //Getthelightspacetranform   p.SetCamera(Vector3f(0.0f,0.0f,0.0f),m_dirLight.Direction,Vector3f(0.0f,1.0f,0.0f));   Matrix4fLightM=p.GetViewTrans();   floatar=m_persProjInfo.Height/m_persProjInfo.Width;   floattanHalfHFOV=tanf(ToRadian(m_persProjInfo.FOV/2.0f));   floattanHalfVFOV=tanf(ToRadian((m_persProjInfo.FOV*ar)/2.0f));   for(uinti=0;i



請為這篇文章評分?