LearnOpenGL - CSM
文章推薦指數: 80 %
Cascaded shadow mapping is a direct answer to the third point, however while implementing it we will solve the first two points, too.
Ifyou'rerunningAdBlock,pleaseconsiderwhitelistingthissiteifyou'dliketosupportLearnOpenGL;andnoworries,Iwon'tbemadifyoudon't:)
IntroductionGettingstartedOpenGLCreatingawindowHelloWindowHelloTriangleShadersTexturesTransformationsCoordinateSystemsCameraReviewLightingColorsBasicLightingMaterialsLightingmapsLightcastersMultiplelightsReviewModelLoadingAssimpMeshModelAdvancedOpenGLDepthtestingStenciltestingBlendingFacecullingFramebuffersCubemapsAdvancedDataAdvancedGLSLGeometryShaderInstancingAntiAliasingAdvancedLightingAdvancedLightingGammaCorrectionShadowsShadowMappingPointShadowsNormalMappingParallaxMappingHDRBloomDeferredShadingSSAOPBRTheoryLightingIBLDiffuseirradianceSpecularIBLInPracticeDebuggingTextRendering2DGameBreakoutSettingupRenderingSpritesLevelsCollisionsBallCollisiondetectionCollisionresolutionParticlesPostprocessingPowerupsAudioRendertextFinalthoughtsGuestArticlesHowtopublish2020OITIntroductionWeightedBlendedSkeletalAnimation2021CSMSceneSceneGraphFrustumCullingTessellationHeightmapTessellationDSACoderepositoryTranslationsAbout
BTC
1CLGKgmBSuYJ1nnvDGAepVTKNNDpUjfpRa
ETH/ERC20
0x1de59bd9e52521a46309474f8372531533bd7c43
CSM
Guest-Articles/2021/CSM
CascadedShadowMapping
ShadowmappingasdescribedonLearnOpenGLisapowerful,andrelativelysimpletechnique.However,ifimplementedas-isfromtheabovereferredtutorial,theavidOpenGLstudentwillnoticeafewshortcomings.
Theshadowmapisalwayscreatedaroundtheorigin,andnotontheareathecameraisactuallylookingat.Itwouldbebestofcourseifwecouldshadowmapthewholescene,withsufficientresolution,butoncurrenthardwarethisisnotfeasible.Inrealitywewanttheshadowmapstobecreatedonobjectsthatareinview,savingourpreciousGPUmemoryforthingsthatmatter.
Theshadowmaporthographicprojectionmatrixisnotproperlyfittedontotheviewfrustum.Toachievethebestpossibleresolutionforourshadowmaps,theorthomatrixneedstobeastightlyfittothecamerafrustumaspossible,becauseagain:ifit’slargerthatmeansthatlessdetailisspentontheobjectsthatareactuallyvisible.
Theshadowmaps(evenwithadvancedPCFfunctions)areblurryifwewanttheshadowrenderingdistancetobelarge,aswewouldinagamewithafirst-personcamera.Wecanincreasetheresolutionoftheshadowmapstomitigatethis,butGPUmemoryisaresourceweshouldbeconservativeof.
Cascadedshadowmappingisadirectanswertothethirdpoint,howeverwhileimplementingitwewillsolvethefirsttwopoints,too.Thecoreinsightincascadedshadowmappingis,thatwedon’tneedthesameamountofshadowdetailforthingsthatarefarfromus.Wewantcrispshadowsforstuffthat’sneartothenearplane,andweareabsolutelyfinewithblurrinessforobjectsthatarehundredsofunitsaway:it’snotgoingtobenoticeableatall.Howcanweachievethis?Theanswerisbeautifulinitssimplicity:justrenderdifferentshadowmapsforthingsthatarecloseandforthosethatarefaraway,andsamplefromthemaccordingtothedepthofthefragmentinthefragmentshader.Thehigh-levelalgorithmisasfollows:
Divideourordinaryviewfrustumintonsubfrusta,wherethefarplaneofthei-thfrustumisthenearplaneofthe(i+1)-thfrustum
Computethetightlyfittingorthomatrixforeachfrustum
Foreachfrustumrenderashadowmapasifseenfromourdirectionallight
Sendallshadowmapstoourfragmentshader
Renderthescene,andaccordingtothefragment’sdepthvaluesamplefromthecorrectshadowmap
Soundssimpleright?Well,itis,butasitofteniswhenitcomestoourfriendOpenGL:thedevilisinthedetails.
IntheaboveimagewecanseetheedgesofshadowcascadesinCounter-Strike:GlobalOffensive.Theimagewascapturedonlowgraphicssettings.
Worldcoordinatesoftheviewfrustum
Beforegettingourhandsdirtywithshadows,weneedtotackleamoreabstractproblem:makingourprojectionmatrixfitnicelyontoagenericfrustum.Tobeabletodothis,weneedtoknowtheworldspacecoordinatesofthefrustuminquestion.Whilethismightsounddauntingatfirst,wealreadyhaveallthetoolsnecessaryinourrepertoire.Ifwethinkbackontheexcellentcoordinatesystemstutorial,thebeheadedpyramidofthefrustumonlylooksthatwayinworldcoordinates,andourviewandprojectionmatricesdothejoboftransformingthisunusualshapeintotheNDCcube.AndweknowthecoordinatesofthecornersoftheNDCcube:thecoordinatesareintherange[-1,1]onthethreeaxes.Becausematrixmultiplicationisareversibleprocess,wecanapplytheinverseoftheviewandprojectionmatricesonthecornerpointsoftheNDCcubetogetthefrustumcornersinworldspace.
$$v_{NDC}=M_{proj}M_{view}v_{world}$$
$$v_{world}=(M_{proj}M_{view})^{-1}v_{NDC}$$
std::vector<:vec4>getFrustumCornersWorldSpace(constglm::mat4&proj,constglm::mat4&view)
{
constautoinv=glm::inverse(proj*view);
std::vector<:vec4>frustumCorners;
for(unsignedintx=0;x<2;++x)
{
for(unsignedinty=0;y<2;++y)
{
for(unsignedintz=0;z<2;++z)
{
constglm::vec4pt=
inv*glm::vec4(
2.0f*x-1.0f,
2.0f*y-1.0f,
2.0f*z-1.0f,
1.0f);
frustumCorners.push_back(pt/pt.w);
}
}
}
returnfrustumCorners;
}
Theprojectionmatrixdescribedhereisaperspectivematrix,usingthecamera’saspectratioandfov,andusingthenearandfarplaneofthecurrentfrustumbeinganalyzed.Theviewmatrixistheviewmatrixofourcamera.
constautoproj=glm::perspective(
glm::radians(camera.Zoom),
(float)SCR_WIDTH/(float)SCR_HEIGHT,
nearPlane,
farPlane
);
TheaboveimageisthecourtesyofOGLDev
Thelightview-projectionmatrix
Thismatrix-asinordinaryshadowmapping–istheproductoftheviewandprojectionmatrixthattransformsthesceneasifitwereseenbythelight.Calculatingtheviewmatrixissimple,weknowthedirectionourlightiscomingfrom,andweknowapointinworldspacethatitdefinitelyislookingat:thecenterofthefrustum.Thepositionofthefrustumcentercanbeobtainedbyaveragingthecoordinatesofthefrustumcorners.(Thisissobecauseaveragingthecoordinatesofthenearandfarplanegivesusthecenterofthoserectangles,andtakingthemidpointofthesetwopointsgivesusthecenterofthefrustum.)
glm::vec3center=glm::vec3(0,0,0);
for(constauto&v:corners)
{
center+=glm::vec3(v);
}
center/=corners.size();
constautolightView=glm::lookAt(
center+lightDir,
center,
glm::vec3(0.0f,1.0f,0.0f)
);
Theprojectionmatrixisbitmorecomplex.Becausethelightinquestionisadirectionallight,thematrixneedstobeanorthographicprojectionmatrix,thismuchisclear.Tounderstandhowwedeterminetheleft,right,topetc.parametersofthematriximaginethesceneyouaredrawingfromtheperspectiveofthelight.Fromthisviewpointtheshadowmapwearetryingtorenderisgoingtobeanaxisalignedrectangle,andthisrectangle–asweestablishedbefore–needstofitonthefrustumtightly.Soweneedtoobtainthecoordinatesofthefrustuminthisspace,andtakethemaximumandminimumofthecoordinatesalongthecoordinateaxes.Whilethismightsounddauntingatfirst,thisperspectiveisexactlywhatourlightviewmatrixtransformationgivesus.Weneedtotransformthefrustumcornerpointsinthelightviewspace,andfindthemaximumandminimumcoordinates.
floatminX=std::numeric_limits
延伸文章資訊
- 1Cascaded Shadow Maps(CSM)實時陰影的原理與實現 - GetIt01
本文翻譯自:https://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded...
- 2OpenGL Cascaded Shadow Maps - Make Games, Not War
To begin with, cascaded Shadow Mapping is a technique which uses several shadow maps to further i...
- 3重疊的陰影圖- Win32 apps
shadow map coverage ... cascade overlap increases as light direction becomes parallel ... Interva...
- 4Cascaded Shadow maps not quite right - Stack Overflow
I've mostly implemented cascading shadow maps (CSM), ... And samples the shadow map array with th...
- 5LearnOpenGL - CSM
Cascaded shadow mapping is a direct answer to the third point, however while implementing it we w...