Learn OpenGL. Lesson 5.5 - Normal Mapping

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

It is interesting to note the blue tint of this normal map (almost all normal maps have a similar shade). This happens because all the normals are oriented ... LearnOpenGL.Lesson5.5-NormalMappingOriginalauthor:JoeydeVriesTransferTutorialNormalmapping Allthescenesweuseconsistofpolygons,inturn,consistingofhundreds,thousandsofabsolutelyflattriangles.Wehavealreadymanagedtoslightlyenhancetherealismofthescenesduetoadditionaldetails,whichareprovidedbyapplyingtwo-dimensionaltexturestotheseflattriangles.Texturinghelpstohidethefactthatallobjectsinthescenearejustacollectionofmanysmalltriangles.Greattechnique,butitspossibilitiesarenotunlimited:whenapproachinganysurface,allonebecomesclearthatitconsistsofflatsurfaces.Mostoftherealobjectsarenotcompletelyflatandshowalotofembosseddetails.ContentPart1.StartOpenglCreatingawindowHellowindowHellotriangleShadersTexturesTransformationsCoordinatesystemsCamera Part2.BasiclightingColorsLightingBasicsMaterialsTextureCardsSourcesoflightMultiplelightsources Part3.Loading3DModelsAssimplibraryMeshmeshclass3Dmodelclass Part4.OpenGLadvancedfeaturesDepthtestStenciltestMixingcolorsFaceclippingFramebufferCubiccardsAdvanceddatahandlingAdvancedGLSLGeometricshaderInstancingСглаживание Часть5.ПродвинутоеосвещениеПродвинутоеосвещение.МодельБлинна-Фонга.Гамма-коррекцияКартытенейВсенаправленныекартытенейNormalMapping Forexample,takeabrickwork.Itssurfaceisveryroughand,obviously,isrepresentedfarfromplane:ithascavitieswithcementandmanysmalldetailslikeholesandcracks.Ifthescenewithimitationofbrickworkisanalyzedinthepresenceoflight,thentheillusionofthereliefofthesurfaceisveryeasilydestroyed.Belowisanexampleofsuchascene,containingaplanewithappliedbrickworktextureandonepointlightsource: Ascanbeseen,thelightingdoesnotatalltakeintoaccountthedetailsofthereliefintendedforthissurface:allsmallcracksareabsent,andthehollowswithcementareindistinguishablefromtherestofthesurface.Itwouldbepossibletouseaspecularglossmapinordertolimittheilluminationofcertainpartsthatarelocatedinthesurfacerecesses.Butthisismorelikeadirtyhackthanaworkingsolution.Whatweneedisawaytoprovidetheequationsofilluminationwithsurfacemicroreliefdata. Inthecontextofthelightingequationsknowntous,considerthisquestion:underwhatconditionswillthesurfacebelitasideallyflat?Theanswerisrelatedtothesurfacenormal.Fromthepointofviewofthelightingalgorithm,informationontheshapeofthesurfaceistransmittedonlythroughthenormalvector.Sincethenormalvectorisconstanteverywhereontheabovesurface,theilluminationisuniform,correspondingtotheplane.Andwhatifthelightalgorithmisnottransmittedtoasinglenormal,constantforallfragmentsbelongingtoanobject,butauniquenormalforeachfragment?Thus,thenormalvectorwillvaryslightlybasedonthesurfacetopography,whichwillcreateamoreconvincingillusionofsurfacecomplexity: Duetotheuseoffragmentsofdifferentnormals,theilluminationalgorithmwillconsiderthesurfaceasconsistingofasetofmicroscopicplanesperpendiculartoitsnormalvector.Intheend,thiswillsignificantlyaddtheobjectoftexture.Thetechniqueofapplyingnormalsuniquetoafragment,andnottheentiresurface-thisisNormalMappingorBumpMapping.Appliedtoanalreadyfamiliarscene: Animpressiveincreaseinvisualcomplexityisseenduetotheverymodestcostofproductivity.Sinceweareallchangesinthelightingmodelareonlyinthepresentationofauniquenormalineachfragment,thennoformulasforthecalculationsdonotchange.Onlytheinputinsteadoftheinterpolatedsurfacenormalentersthenormalforthecurrentfragment.Allthesamelightingequationsdotherestoftheworktocreateanillusionofrelief.Normalmapping So,itturnsout,weneedtoprovidetheilluminationalgorithmwithnormals,uniqueforeachfragment.Weusethemethodalreadyfamiliarfromthetexturesofdiffuseandspecularreflectionandusetheusual2Dtexturetostoredataaboutthenormalateachpointofthesurface.Don'tbesurprised,texturesaregreatforstoringnormalvectors.Next,wewillonlyhavetosamplethetexture,restorethenormalvectorandcalculatetheillumination. Atfirstglance,itmaynotbeveryclearhowtostorevectordatainaregulartexture,whichistypicallyusedtostorecolorinformation.Butthinkforasecond:theRGBcolortriadisessentiallyathree-dimensionalvector.Similarly,youcansavethecomponentsoftheXYZnormalvectorinthecorrespondingcolorcomponents.Themagnitudesofthecomponentsofthenormalvectorlieintheinterval[-1,1]andthereforerequireadditionalconversiontotheinterval[0,1]:vec3rgb_normal=normal*0.5+0.5;//переходот[-1,1]к[0,1] SuchareductionofthenormalvectortothespaceoftheRGBcolorcomponentswillallowustopreservethetextureofthenormalvectorobtainedonthebasisoftherealreliefofthemodeledobjectanduniqueforeachfragment.Anexampleofsuchatexture-normalmaps-forthesamebrickwork: Itisinterestingtonotethebluetintofthisnormalmap(almostallnormalmapshaveasimilarshade).ThishappensbecauseallthenormalsareorientedapproximatelyalongtheoZaxis,whichisrepresentedbythecoordinatetriple(0,0,1),i.e.intheformofacolortriad-pureblue.SmallchangesinshadeareduetothedeviationofthenormalsfromthepositiveoZsemi-axisinsomeareas,whichcorrespondstotheuneventerrain.So,youcanseethatontheupperedgesofeachbrick,thetextureacquiresagreentint.Andthisislogical:ontheupperedgesofthebrick,thenormalsshouldbeorientedmoretowardstheoYaxis(0,1,0),whichcorrespondstothegreencolor. Forthetestscene,wetakeaplaneorientedtowardsthepositivesemi-axisoZandusethefollowingforit.diffusemapandnormalmap.Pleasenotethatthenormalmaponthelinkandinthepictureabovearedifferent.Inthearticle,theauthorrathercasuallymentionedthereasonsforthedifferences,limitinghimselfwiththeadvicetotransformnormalmapstosuchaformthatthegreencomponentpoints“down”ratherthan“up”inthesystemlocaltothetextureplane. Ifyoulookinmoredetail,thentwofactorsinteract:ThedifferenceinhowtexelsareaddressedinclientmemoryandinOpenGLtexturememoryThepresenceoftwonotationsfornormalmaps.Conventionally,twocamps:DirectX-styleandOpenGL-style Asforthenormalmapnotation,thetwocampsthatarehistoricallyfamiliarare:DirectXandOpenGL. Asyoucansee,theyarenotcompatible.AndhavingalittlethoughtonecanunderstandthatDirectXconsidersthetangentspacetobeleft-handedandOpenGLtoright-handed.Havingslippedthex-cardofnormalstoourapplicationwithoutchanges,wegetincorrectillumination,anditisnotalwaysimmediatelyobviousthatitisincorrect.ThemostnoticeableisthatthebumpsintheOpenGLformatbecomerecessesforDirectXandviceversa. Asforaddressing:loadingdatafromatexturefileintomemory,weassumethatthefirsttexelistheleftuppertexeloftheimage.Forthepresentationofthetexturedataintheapplication'smemory,thisisgenerallythecase.ButOpenGLusesadifferenttexturecoordinatesystem:forit,thefirsttexelisthebottomleft.Forcorrecttexturing,imagesareusuallyturnedoveralongtheYaxiseveninthecodeofoneoranotherimagefileloader.FortheStb_imageusedinthelessonsyouneedtoaddacheckboxstbi_set_flip_vertically_on_load(1); Whatisthemostfunny,twooptionsaredisplayedcorrectlyintermsoflighting:thenormalmapinOpenGLnotationwithYreflectionturnedonorthenormalmapinDirectXnotationwithYreflectionturnedoff.Thelightinginbothcasesworkscorrectly,thedifferencewillremainonlyinthetextureinversionY.Noteper. So,let'sloadbothtextures,attachthemtotextureunitsandrenderthepreparedplane,takingintoaccountthefollowingmodificationsofthefragmentshadercode:uniformsampler2DnormalMap; voidmain(){ //выборкавектораизкартынормалейсобластьюзначений[0,1] normal=texture(normalMap,fs_in.TexCoords).rgb; //переводвекторанормаливинтервал[-1,1] normal=normalize(normal*2.0-1.0); [...] //вычислениеосвещения... } HereweapplytheinversetransformfromtheRGBvaluespacetothefullnormalvectorandthensimplyuseitinthefamiliarBlinna-Phonglightingmodel. Now,ifyouslowlychangethepositionofthelightsourceinthescene,youcanfeeltheillusionofthesurfacereliefprovidedbythenormalmap: Butthereremainsoneproblemthatradicallynarrowstherangeofpossibleuseofnormalmaps.Asalreadynoted,thebluetintofthenormalmaphintedthatallthevectorsinthetextureareorientedonaveragealongthepositiveoZaxis.Inourscene,thisdidnotcreateproblems,becausethenormaltothesurfaceoftheplanewasalsoalignedwithoZ.However,whathappensifwechangethepositionoftheplaneinthescenesothatthenormaltoitwillbealignedwiththepositivesemi-axisoY? Thelightingturnedouttobecompletelywrong!Andthereasonissimple:thenormalsamplesfromthemapallalsoreturnvectorsorientedalongthepositivesemi-axisoZ,althoughinthiscasetheyshouldbeorientedinthedirectionofthepositivesemi-axisoYofthesurfacenormal.Atthesametime,thecalculationofilluminationproceedsasifthesurfacenormalsarelocatedasiftheplaneisstillorientedtowardsthepositiveoZsemi-axis,whichgivesanincorrectresult.Thefigurebelowmoreclearlyshowstheorientationofthesurfacenormalsreadfromthenormalmap: ItcanbeseenthatthenormalsaregenerallyalignedalongtheoZpositivesemiaxis,althoughtheyshouldbealignedalongthenormaltothesurface,whichisdirectedalongtheoYpositivesemiaxis. Apossiblesolutionwouldbetospecifyaseparatenormalmapforeachorientationofthesurfaceunderconsideration.Foracube,itwouldtakesixnormalmaps,andformorecomplexmodelsthenumberofpossibleorientationsmaybetoohighandnotsuitableforimplementation. Thereisanother,mathematicallymorecomplexapproach,whichproposestocarryoutcalculationsofilluminationinanothercoordinatesystem:suchthatthenormalvectorsinitalwaysapproximatelycoincidewiththepositivesemi-axisoZ.Othervectorsrequiredforlightingcalculationsarethenconvertedtothiscoordinatesystem.Thismethodmakesitpossibletouseonenormalmapforanyorientationoftheobject.Andthisspecificcoordinatesystemiscalledtangentspaceortangentspace.Tangentspace Itshouldbenotedthatthenormalvectorinthenormalmapisexpresseddirectlyinthetangentspace,i.e.insuchacoordinatesystemthatthenormalisalwaysdirectedapproximatelyinthedirectionofthepositivesemi-axisoZ.Thetangentspaceisdefinedasacoordinatesystemlocaltotheplaneofthetriangleandeachnormalvectorisdefinedwithinthiscoordinatesystem.Itispossibletoimaginethissystemasalocalcoordinatesystemforthenormalmap:allvectorsinitaresetdirectedtowardsthepositivesemi-axisoZ,regardlessofthefinalorientationofthesurface.Usingspeciallypreparedtransformationmatrices,onecantransformthenormalvectorsfromthislocaltangentcoordinatesystemintoworldorspeciescoordinates,orientingtheminaccordancewiththefinalpositionofthesurfacessubjectedtotexturing. Considerthepreviousexamplewiththeincorrectapplicationofnormalmapping,wheretheplanewasorientedalongthepositivesemi-axisoY.Sincethenormalmapisgiveninthetangentspace,oneofthecorrectionoptionsisthecalculationofthematrixofthetransitionofthenormalsfromthetangentspacetosuchthattheywouldbecomeorientedalongthenormaltothesurface.ThiswouldcausethenormalstobecomealignedalongthepositivesemiaxisoY.Aremarkablepropertyofthetangentspaceisthefactthatbycalculatingsuchamatrixwecanreorientthenormalstoanysurfaceanditsorientation. Suchamatrixis​​abbreviatedasTBN,whichisanabbreviationforthenameofthetripletvectorsTangent,Bitangent,andNormal.Weneedtofindthesethreevectorsinordertoformthisbasischangematrix.Suchamatrixmakesthetransitionofthevectorfromthetangentspacetosomeotherone,andforitsformation,threemutuallyperpendicularvectorsareneeded,theorientationofwhichcorrespondstotheorientationoftheplaneofthenormalmap.Thisisadirectionvectorup,rightandforward,asetfamiliartousfromthelessonaboutthevirtualcamera. Withthetopallclearatonce-thisisournormalvector.Thevectortotherightandforwardarecalledtangent(tangent)andbitwise(bitangent),respectively.Thefollowingfiguregivesanideaof​​theirrelativepositionontheplane: Thecalculationofthetangentandthebitmapisnotasobviousasthecalculationofthenormalvector.Inthefigure,youcanseethatthedirectionofthetangentandbi-tangentnormalmapisalignedwiththeaxesdefiningthesurfacetexturecoordinates.Thisfactisthebasisforthecalculationofthesetwovectorswhichwillrequiresomeskillwithmathematics.Lookatthepicture: ChangestotexturecoordinatesalongatrianglefaceE2designatedasΔU2andΔV2expressedinthesamedirectionsasthetangentvectorsTandbikasatelnoyBedand.Basedonthisfact,onecanexpressthefacesofatriangleE1andE2intheformofalinearcombinationoftangentandbi-tangentvectors:E1=ΔU1T+ΔV1BE2=ΔU2T+ΔV2B Convertingintoelement-wiserecordingweget:(E1x,E1y,E1z)=ΔU1(Tx,Ty,Tz)+ΔV1(Bx,By,Bz)(E2x,E2y,E2z)=ΔU2(Tx,Ty,Tz)+ΔV2(Bx,By,Bz)Eiscalculatedasthevectorofthedifferenceoftwovectors,andΔUandΔVasthedifferenceoftexturecoordinates.Itremainstofindtwounknownsintwoequations:thetangentTandbicantBedand.Ifyoustillrememberthelessonsofalgebra,thenyouknowthatsuchconditionsmakeitpossibletosolvethesystemforTandforBedand. Thelatterformofequationsallowsustorewriteitintheformofmatrixmultiplication:[E1xE1yE1zE2xE2yE2z]=[ΔU1ΔV1ΔU2ΔV2][TxTyTzBxByBz] Trytomentallyperformamatrixmultiplicationtomakesuretherecordiscorrect.WritingthesysteminmatrixformmakesitmucheasiertounderstandtheapproachtofindingTand.Multiplybothsidesoftheequationbytheinverse: Wegetadecisionregardingandwhich,however,requiresthecalculationoftheinversematrixofchangesintexturecoordinates.Wewillnotgointothedetailsofcalculatinginversematrices-theexpressionfortheinversematrixlooksliketheproductofthenumberinversetothedeterminantoftheoriginalmatrix,andtheadjointmatrix: Thisexpressionistheformulaforcalculatingthetangentvectorandbikasatelnoybasedonthecoordinatesofthefacesofthetriangleandthecorrespondingtexturecoordinates. Donotworryiftheessenceoftheabovemathematicalcalculationseludesyou.Ifyouunderstandthatwegetthetangentandthebinaryonthebasisofthecoordinatesofthetriangle'sverticesandtheirtexturecoordinates(sincethetexturecoordinatesalsobelongtothetangentspace)-thisishalfthebattle.Calculationoftangentsandbitangts Intheexampleofthislesson,wetookasimpleplane,lookinginthedirectionofthepositivesemi-axisoZ.Nowwewilltrytoimplementnormalmappingusingtangentspaceinordertobeabletoorienttheplaneintheexampleaswelike,withoutdestroyingtheeffectofnormalmapping.Usingtheabovecalculation,wewillmanuallyfindthetangentandbicassivetothesurfaceunderconsideration. Letusassumethattheplaneiscomposedofthefollowingverticeswithtexturecoordinates(twotrianglesaregivenbyvectors1,2,3and1,3,4)://координатывершин glm::vec3pos1(-1.0,1.0,0.0); glm::vec3pos2(-1.0,-1.0,0.0); glm::vec3pos3(1.0,-1.0,0.0); glm::vec3pos4(1.0,1.0,0.0); //текстурныекоординаты glm::vec2uv1(0.0,1.0); glm::vec2uv2(0.0,0.0); glm::vec2uv3(1.0,0.0); glm::vec2uv4(1.0,1.0); //векторнормали glm::vec3nm(0.0,0.0,1.0); First,wecalculatethevectorsdescribingthefacesofthetriangle,aswellasthedeltasofthetexturecoordinates:glm::vec3edge1=pos2-pos1; glm::vec3edge2=pos3-pos1; glm::vec2deltaUV1=uv2-uv1; glm::vec2deltaUV2=uv3-uv1; Havingonhandthenecessaryinitialdatawecanproceedtothecalculationofthetangentandthebicantdirectlybytheformulasfromtheprevioussection:floatf=1.0f/(deltaUV1.x*deltaUV2.y-deltaUV2.x*deltaUV1.y); tangent1.x=f*(deltaUV2.y*edge1.x-deltaUV1.y*edge2.x); tangent1.y=f*(deltaUV2.y*edge1.y-deltaUV1.y*edge2.y); tangent1.z=f*(deltaUV2.y*edge1.z-deltaUV1.y*edge2.z); tangent1=glm::normalize(tangent1); bitangent1.x=f*(-deltaUV2.x*edge1.x+deltaUV1.x*edge2.x); bitangent1.y=f*(-deltaUV2.x*edge1.y+deltaUV1.x*edge2.y); bitangent1.z=f*(-deltaUV2.x*edge1.z+deltaUV1.x*edge2.z); bitangent1=glm::normalize(bitangent1); [...]//аналогичныйкоддлярасчетакасательныхвтороготреугольникаплоскости Firstweputthefractionalcomponentofthefinalexpressionintoaseparatevariablef.Thenforeachcomponentofthevectorsweperformthecorrespondingpartofthematrixmultiplicationandmultiplybyf.Bycomparingthiscodewiththefinalcalculationformula,youcanseethatthisisliterallyitsarrangement.Donotforgettocarryoutnormalizationattheendsothatthevectorsfoundaresingle. Sincethetriangleisaflatfigure,itisenoughtocalculatethetangentandthecutoutoncepertriangle-theywillbethesameforallvertices.Itshouldbenotedthatmostoftheimplementationsofworkingwithmodels(suchasloadersorlandscapegenerators)usesuchanorganizationoftriangles,wheretheyshareverticeswithothertriangles.Insuchcases,developersusuallyresorttoaveragingtheparametersincommonvertices,suchasthenormalvector,tangentandbiting,togetasmootherresult.Thetrianglesthatmakeupourplanealsoshareseveralvertices,butsincebothofthemlieinthesameplane,averagingisnotrequired.Yetitisusefultorememberthatsuchanapproachisavailableinreal-worldapplicationsandtasks. Theresultingtangentandbi-vectorvectorsshouldhavethevalues​​(1,0,0)and(0,1,0),respectively.That,togetherwiththenormalvector(0,0,1)formtheorthogonalmatrixTBN.Ifyouvisualizetheresultingbasisalongwiththeplane,yougetthefollowingimage: Now,havingthecalculatedvectors,youcanstartthefullimplementationofnormalmapping.Normalmappingintangentspace FirstyouneedtocreateamatrixTBNinshaders.Forthispurpose,wewilltransferthepreviouslypreparedtangentandbitwisevectorstothevertexshaderthroughthevertexattributes:#version330core layout(location=0)invec3aPos; layout(location=1)invec3aNormal; layout(location=2)invec2aTexCoords; layout(location=3)invec3aTangent; layout(location=4)invec3aBitangent; Inthecodeofthevertexshaderitself,wewillformthematrixdirectly:voidmain(){ [...] vec3T=normalize(vec3(model*vec4(aTangent,0.0))); vec3B=normalize(vec3(model*vec4(aBitangent,0.0))); vec3N=normalize(vec3(model*vec4(aNormal,0.0))); mat3TBN=mat3(T,B,N) } Inthefirstcodetransformallvectorbasisofthetangentspacecoordinatesysteminwhichitisconvenienttowork-inthiscase,theworldcoordinatesystem,andwemultiplyavectorbyamatrixmodelmodel.Next,wecreatetheTBNmatrixitselfbysimplypassingallthreerelevantvectorstothemat3constructor.Payattentionthatforthecompletecorrectnessoftheorderofcalculations,itisnecessarytomultiplythevectorsnotbythemodelmatrix,butbythenormalmatrix,sinceweareonlyinterestedintheorientationofthevectors,butnotintheirdisplacementorscalingStrictlyspeaking,itisnotatallnecessarytotransmitavectortoashader. SincethetripletofTBNvectorsaremutuallyperpendicular,thequicantcanbetriviallyfoundintheshaderthroughvectormultiplication:vec3B=cross(N,T) SotheTBNmatrixis​​obtained,howdoweuseit?Infact,therearetwoapproachestoitsuseinnormalmapping:UsetheTBNmatrixtotransformallthenecessaryvectorsfromthetangentspacetotheworldone.Transfertheresultstothefragmentshader,where,alsousingthematrix,convertthevectorfromthenormalmaptotheworldspace.Asaresult,thenormalvectorwillbeinthespacewhereallthelightingiscalculated.TakethematrixinversetoTBNandtransformallthenecessaryvectorsfromworldspacetotangent.Those.usethismatrixtoconvertvectorsinvolvedinlightingcalculationsintotangentspace.Thenormalvectorinthiscasealsoremainsinthesamespaceastheotherparticipantsinthecalculationoftheillumination. Let'sconsiderthefirstoption.Thenormalvectorfromthecorrespondingtextureisgiveninthetangentspace,whiletheothervectorsusedinthecalculationoftheilluminationaregiveninworldspace.BytransferringtheTBNmatrixtothefragmentshader,wecouldconvertthenormalvectorobtainedbysamplingfromthetexturefromthetangentspacetotheworldspace,ensuringtheunityofthecoordinatesystemsforallelementsoftheilluminationcalculation.Inthiscase,allcalculations(especiallyscalarmultiplicationsofvectors)willbecorrect. TransferringtheTBNmatrixis​​doneinthesimplestway:outVS_OUT{ vec3FragPos; vec2TexCoords; mat3TBN; }vs_out; voidmain(){ [...] vs_out.TBN=mat3(T,B,N); } Inthecodeofthefragmentshader,respectively,wesettheinputvariableofthemat3type:inVS_OUT{ vec3FragPos; vec2TexCoords; mat3TBN; }fs_in; Withthematrixinhand,youcanspecifythecodeforobtainingthenormalbyexpressingthetranslationfromthetangentintotheworldspace:normal=texture(normalMap,fs_in.TexCoords).rgb; normal=normalize(normal*2.0-1.0); normal=normalize(fs_in.TBN*normal); Sincetheresultingnormalisnowsetinworldspace,thereisnoneedtochangeanythingelseintheshadercode.Theilluminationcalculationsassumethenormalvectorgiveninworldcoordinates. Let'salsolookatthesecondapproach.ItwillrequireobtainingtheinverseTBNmatrix,aswellastransferringallthevectorsinvolvedintheilluminationcalculationfromtheworldcoordinatesystemtotheonethatcorrespondstothenormalvectorsobtainedfromthetexture-thetangent.Inthiscase,theformationoftheTBNmatrixremainsunchanged,butbeforetransferringtothefragmentshader,weneedtogetaninversematrix:vs_out.TBN=transpose(mat3(T,B,N)); Noticethatthetranspose()functionisusedinsteadofinverse().Suchasubstitutionisvalid,sincefororthogonalmatrices(whereallaxesarerepresentedbyunitmutuallyperpendicularvectors),obtainingtheinversematrixgivestheresultidenticaltothetransposition.Andthisisveryopportunely,since,inthegeneralcase,thecalculationoftheinversematrixis​​muchmorecomputationallyexpensiveincomparisonwithtransposition. Inthecodeofthefragmentshader,wewillnotconvertthenormalvector,butinsteadconvertfromtheworldcoordinatesystemtothetangentotherimportantvectors,namely,lightDirandviewDir.Thissolutionalsobringsalltheelementsofthecalculationsintoasinglecoordinatesystem,thistimethetangent.voidmain(){ vec3normal=texture(normalMap,fs_in.TexCoords).rgb; normal=normalize(normal*2.0-1.0); vec3lightDir=fs_in.TBN*normalize(lightPos-fs_in.FragPos); vec3viewDir=fs_in.TBN*normalize(viewPos-fs_in.FragPos); [...] } Thesecondapproachseemstobemorelaboriousandrequiresmorematrixmultiplicationsinthefragmentshader(whichgreatlyaffectsperformance).Whydidweeventakeitapart? Thefactisthattransferringvectorsfromworldcoordinatestotangentsprovidesanadditionaladvantage:infact,wecantakeoutallthetransformationcodefromthefragmenttothevertexshader!ThisapproachisworkingbecauselightPosandviewPosdonotchangefromfragmenttofragment,andthevalueoffs_in.FragPoswecanalsoconverttothetangentspaceinthevertexshader,theinterpolatedvalueattheinputtothefragmentshaderwillbequitecorrect.Thus,forthesecondapproachthereisnoneedtotranslateallthesevectorsintothetangentspaceinthecodeofthefragmentshader,whilethefirstrequiresit-thenormalisuniqueforeachfragment. Asaresult,wemoveawayfromthetransferoftheinversematrixtotheTBNtothefragmentshaderandinsteadgiveitthepositionvectorofthevertex,thelightsourceandtheobserverinthetangentspace.Sowewillgetridofcostlymatrixmultiplicationsinthefragmentshader,whichwillbeasignificantoptimization,becausethevertexshaderisexecutedmuchlessfrequently.Itisthisadvantagethatmakesthesecondapproachoneofthepreferredinmostcasesofuse.outVS_OUT{ vec3FragPos; vec2TexCoords; vec3TangentLightPos; vec3TangentViewPos; vec3TangentFragPos; }vs_out; uniformvec3lightPos; uniformvec3viewPos; [...] voidmain(){ [...] mat3TBN=transpose(mat3(T,B,N)); vs_out.TangentLightPos=TBN*lightPos; vs_out.TangentViewPos=TBN*viewPos; vs_out.TangentFragPos=TBN*vec3(model*vec4(aPos,0.0)); Inthefragmentshader,weturntotheuseofnewinputvariablesinthecalculationsoflightingintangentspace.Sincethenormalsareconditionallygiveninthisspace,allcalculationsremaincorrect. Nowthatallnormalmappingcalculationsareperformedinatangentspace,wecanchangetheorientationofthetestsurfaceintheapplicationaswewantandthelightingwillremaincorrect:glm::mat4model(1.0f); model=glm::rotate(model,(float)glfwGetTime()*-10.0f,glm::normalize(glm::vec3(1.0,0.0,1.0))); shader.setMat4("model",model); RenderQuad(); Indeed,outwardly,everythinglooksasitshould: Thesourcesarehere.Complexobjects So,wefiguredouthowtoperformanormalmappinginatangentspaceandhowtoindependentlycalculatethetangentandbi-tangentvectorsforthis.Fortunately,suchamanualcalculationisnotsomethingthatoftenarises:forthemostpart,thiscodeisimplementedbydeveloperssomewhereinthedepthsofthemodelloader.Inourcase,thisistruefortheusedAssimploader. Assimpprovidesaveryusefuloptionsflagwhenloadingmodels:aiProcess_CalcTangentSpace.WhenitistransferredtotheReadFile()function,thelibraryitselfwillbeengagedincalculatingthesmoothedtangentsandbitmapsforeachoftheloadedvertices-aprocesssimilartotheoneconsideredhere.constaiScene*scene=importer.ReadFile( path,aiProcess_Triangulate|aiProcess_FlipUVs|aiProcess_CalcTangentSpace ); Afterthat,youcandirectlyaccessthecalculatedtangents:vector.x=mesh->mTangents[i].x; vector.y=mesh->mTangents[i].y; vector.z=mesh->mTangents[i].z; vertex.Tangent=vector; Youwillalsoneedtoupdatethebootcodesothatittakesintoaccountthereceiptofnormalmapsfortexturedmodels.WavefrontObjectformat(.obj)exportsnormalmapsinsuchawaythattheAssimpaiTextureType_NORMALflagdoesnotensurecorrectloadingofthesemaps,whilewiththeaiTextureType_HEIGHTflageverythingworkscorrectly.Sopersonally,Iusuallyloadnormalmapsinthefollowingway:vectornormalMaps=loadMaterialTextures(material,aiTextureType_HEIGHT,"texture_normal"); Ofcourse,forothermodeldescriptionformatsandfiletypes,thisapproachmaynotbeappropriate.AlsonotethatsettingtheaiProcess_CalcTangentSpaceflagdoesnotalwayswork.Weknowthatthecalculationoftangentsisbasedontexturecoordinates,however,oftentheauthorsofthemodelsapplyvarioustrickstothetexturecoordinates,whichbreaksthecalculationoftangents.Thus,mirrorimageoftexturecoordinatesisoftenusedforsymmetricallytexturedmodels.Ifyoudonottakeintoaccountthefactofspecularity,thenthecalculationofthetangentswillbeincorrect.Assimpdoesnotdothisaccounting.Thenanosuitmodelwearefamiliarwithisnotsuitableforthedemonstration,sinceitalsousesmirroring. Butwithacorrectlytexturedmodelusingnormalandspecularmaps,thetestapplicationgivesaverygoodresult: Asyoucansee,theuseofnormalmappinggivesatangibleincreaseindetailandischeapintermsofcostperformance. Donotforgetthattheuseofnormalmappingcanimprovetheperformanceforaparticularscene.Withoutitsuse,theachievementofmodeldetailispossibleonlythroughanincreaseinthedensityofthepolygonalmesh,mesh.Butthistechniqueallowstoachievevisuallythesamelevelofdetailforlowpolymeshes.Belowyoucanseeacomparisonofthesetwoapproaches: Thelevelofdetailonthehigh-polymodelandonthelow-polyusingnormalmappingisalmostindistinguishable.Sothistechniqueisanexcellentmethodtoreplacehigh-polymodelsinascenewithsimplifiedoneswithalmostnolossinvisualquality.Lastnote Thereisonemoretechnicaldetailregardingnormalmapping,whichslightlyimprovesthequalityatalmostnoadditionalcost. Whentangentsarecalculatedforlargeandcomplexmeshesthathaveasignificantnumberofverticesbelongingtoseveraltriangles,thetangentvectorsareusuallyaveragedtogetasmoothandvisuallypleasingnormalmappingresult.However,thiscreatesaproblem:afteraveraging,atripletofTBNvectorscanlosemutualperpendicularity,whichalsomeansalossoforthogonalityfortheTBNmatrix.Inthegeneralcase,thenormalmappingresult,obtainedonthebasisofanon-orthogonalmatrix,isonlyslightlyincorrect,butwecanstillimproveit. Forthis,itisenoughtoapplyasimplemathematicalmethod:theGram-Schmidtprocessorre-orthogonalizationofourtriplevectorsTBN.Inthevertexshadercode:vec3T=normalize(vec3(model*vec4(aTangent,0.0))); vec3N=normalize(vec3(model*vec4(aNormal,0.0))); //ре-ортогонализацияTотносительноN T=normalize(T-dot(T,N)*N); //получаемперпендикулярныйвекторBчерезвекторноеумножениеTиN vec3B=cross(N,T); mat3TBN=mat3(T,B,N) This,albeitsmall,amendmentimprovesthequalityofanormalmappinginexchangeforameageroverhead.Ifyouareinterestedinthedetailsofthisprocedure,youcanseethelastpartofthevideoNormalMappingMathematics,thelinktowhichisgivenbelow.AdditionalresourcesTutorial26:NormalMapping:TheogldevNormalMappinglesson.HowNormalMappingWorks:AvideotutorialexplainingthebasicsoftheNormalMappingfromTheBennyBox.NormalMappingMathematics:amovierelatedtothepreviousone,explainingthemathusedintheNormalMappingmethod,alsofromTheBennyBox.Tutorial13:NormalMapping:anotherlessonfromopengl-tutorial.org.PS:Wehaveatelegram-konftocoordinatetransfers.Ifthereisaseriousdesiretohelpwiththetranslation,thenyouarewelcome!Tags:openglopengl3normalmappingtangentspacetangentbitangentbumpmapping Alsopopularnow: VideoreviewoftheAsusU38DTlaptop/NOTICBlog Roskomnadzormovedtoanewlevelofinsanity SeriouschangesinFacebookAPIarecoming-February,March,April2013 PCREinJavaScriptunderNode SAPApplicationInfrastructure/FujitsuBlog EffectivevideomonitoringofuseractionswithNetWrixUserActivityVideoReporter1.0/NetwrixBlog Howtomakeproductionefficient Thechoiceofafreelancer,oronthehypothesisofanoldprofessoronthetopicofsearch Getvideosfromvk.comusingPHP EarlyEngagementIssues/SmartProgressBlog



請為這篇文章評分?