View matrix for point light shadows - Graphics - Community

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

This is because I wanted more fine control over the individual textures that a cube map was giving me, I could possibly change it to a cube map ... Downloads Documentation Community Showcase About Viewmatrixforpointlightshadows Graphics Richard_Stern December30,2020,4:07am #1 Hiall. I’vebeenworkingonpointlightshadowsandhavethemalmostworking,somethingjustseemstobeabitoff.I’mnotusingacubemap,insteadI’musinganarrayof6textures.ThisisbecauseIwantedmorefinecontrolovertheindividualtexturesthatacubemapwasgivingme,IcouldpossiblychangeittoacubemapbutIdon’tthinkthat’stheissueI’mhaving. Whenthepointlightisrightoverthescene,everythinglooksgreat,butasImovethelightofftotheright,thingsstartstogowrong: Shadows1435×80492.8KB Therightmostspherelooksgreat,buttheleftonesarejustdark.There’snothingcastingthatshadow. Iwrotesomedebugcodetopaintthepixelsdifferentcolorsbasedonwhichfaceofmyshadowmaparrayisbeingusedandsureenough: debugShadows1435×80453.6KB Thebuggyareaisallinyellowwhichcorrespondstotheleftfaceofmyarray/cube.Thatmakessense,itistotheleftofthelight. Sotheproblemmustbeintherenderingofthatface.Perhapstheviewmatrix? Thisisthecodebeingusedtogeneratetheviewmatrix: switch(eFace) { caseCubeMapFace.PositiveX: returnMatrix.CreateLookAt(v3Pos,v3Pos+Vector3.Right,Vector3.Up); caseCubeMapFace.NegativeX: returnMatrix.CreateLookAt(v3Pos,v3Pos+Vector3.Left,Vector3.Up); caseCubeMapFace.PositiveY: returnMatrix.CreateLookAt(v3Pos,v3Pos+Vector3.Up,Vector3.Backward); caseCubeMapFace.NegativeY: returnMatrix.CreateLookAt(v3Pos,v3Pos+Vector3.Down,Vector3.Forward); caseCubeMapFace.PositiveZ: returnMatrix.CreateLookAt(v3Pos,v3Pos+Vector3.Backward,Vector3.Down); caseCubeMapFace.NegativeZ: returnMatrix.CreateLookAt(v3Pos,v3Pos+Vector3.Forward,Vector3.Up); default: returnMatrix.Identity; } Itriedmessingwiththeupvectorincaseitwasupsidedownorsidewaysbutthatdidn’timprovethings. Itdoesn’tseemliketheproblemcouldbeanyotherpartofthepipelinesinceit’sworkingcorrectlyfortherightsphereandcorrectlyidentifyingwhichfaceoftheshadowmaptouse,butjustincase,here’stherestofthecode: //C#codeusedtodrawtheshadowmap privatevoidDrawOmnidirectionalShadowMap(Lightlight,intnLightIndex) { //Sixfacesofthecubemap for(inti=0;iclosestDirection) { closestDirection=result; faceIndex=face; } } float4lightingPosition=mul(float4(worldPosition,1),_PointLightSpaceMatrix[faceIndex]); float2shadowTexCoord=mad(0.5,lightingPosition.xy/lightingPosition.w,float2(0.5,0.5)); shadowTexCoord.y=1.0f-shadowTexCoord.y; floatourDepth=(lightingPosition.z/lightingPosition.w); shadowContribution=CalcPointShadowsPCF(ourDepth,NdotL,float3(shadowTexCoord,i*CubeSides+faceIndex)); //Dorestoflightingandrendering Anyideawhythatfaceisn’tworking? Richard_Stern December30,2020,4:34am #2 IusedSpriteBatchtorenderouttheleftfaceofthecubeanditlooksfine: ShadowRender603×5246.86KB SoIguesstheproblemisn’ttheviewmatrix.Anyonehaveanyideas? markus December30,2020,10:18am #3 Justawildguess,buttheimagecouldbesampledupsidedown.Yourclearcolorisblack,whichwouldmakeeverythingshadowed.Maybetryclearingtowhite,andseeiftheshadowisgone. Iwouldsuggesttouseacubemapinsteadofthe6separatetextures.Whensamplingfromacubemap,youjustpassinadirection,andthehardwarefiguresoutwhichfacetosamplefrom.Youdon’tneedthisloopoverallfaces. Alsothinkhowtrickythingscangetwhenyouwanttogetfilteringovertextureborders,fromonefacetoanother. 1Like willmotil December30,2020,12:53pm #4 Ican’tdirectlyseeanythingwrongeither. Isecondthecubemappart.YouarealreadyrenderingtherendertargetcubeyoumightaswelljustcastittoatextureCube. textureCubeDestinationMap=renderTargetCube; ifyourgoingtodoitthatwaythoughhereisashaderfunctionthatfiguresoutthefacewithoutalltheloopinganddoting.Itspitsoutthefaceviatheout. Ionlyhavethisbecauseineeditforasphericalmappingconversionfunctioninoneofmyshaders. Thecubessimplifythingsgreatly. float2NormalToUvFace(float3v,outintfaceIndex) { float3vAbs=abs(v); floatma; float2uv; if(vAbs.z>=vAbs.x&&vAbs.z>=vAbs.y) { faceIndex=v.z<0.0?5:4;//FACE_FRONT:FACE_BACK;//zmajoraxis...wedesignatenegativezforward. ma=0.5f/vAbs.z; uv=float2(v.z<0.0f?-v.x:v.x,-v.y); } elseif(vAbs.y>=vAbs.x) { faceIndex=v.y<0.0f?3:2;//FACE_BOTTOM:FACE_TOP;//ymajoraxis. ma=0.5f/vAbs.y; uv=float2(v.x,v.y<0.0?-v.z:v.z); } else { faceIndex=v.x<0.0?1:0;//FACE_LEFT:FACE_RIGHT;//xmajoraxis. ma=0.5f/vAbs.x; uv=float2(v.x<0.0?v.z:-v.z,-v.y); } returnuv*ma+float2(0.5f,0.5f); } Richard_Stern December31,2020,12:17am #5 SotherearetworeasonsI’mnotusingaRenderTargetCubebutmaybepeoplehavesolutionstothese: Ineed8cubes(8pointlights)andthere’snowaytomakeanarrayofrendertargetcubesthatcanbepassedintotheshaderasfarasIcouldtell.Icanmakeanarrayoftexturesthatis8*6(8cubes,6faceseach)sothat’swhyIdiditthisway. TheCalcPointShadowsPCF()functionneedstosample4pointsandaveragethem,itdoesthisbyoffsettingtheUVsbyonepixel.Iwasn’tsurehowtodothiswithaRenderTargetCubesinceitjustsamplesusingadirectionratherthanUVs. markus December31,2020,12:47am #6 Richard_Stern: Ineed8cubes(8pointlights)andthere’snowaytomakeanarrayofrendertargetcubesthatcanbepassedintotheshaderasfarasIcouldtell RenderTargetCubeinheritsfromTexture.Ifanarrayoftexturesworks,shouldn’tthisworktoo? Richard_Stern December31,2020,2:20am #7 RenderTargetCubeinheritsfromTexture.Ifanarrayoftexturesworks,shouldn’tthisworktoo? TheconstructorforRenderTarget2Dhasanoverloadthatacceptsanarraysize,theoneforRenderTargetCubedoesn’tsothereisnowaytodeclareanarrayofcubesthatwillworkintheshader,andyoucan’tuseaconventionalarraybecausethere’snowaytopassthattotheshader. Richard_Stern December31,2020,2:28am #8 Sotexturearrayvscubeaside(Ireallydon’tthinkthat’stheissuehere): Here’sanotherdebugscreenshot,Igotittooutputthecontentsoftheshadowmap,readingfromthecorrectface: ShadowRender21432×80623.9KB Theactualshadowslookcorrect,itstheareaaroundthemthatdoesn’t.Idon’tthinkthathardseamshouldbethereattheedgeofthetexture.Maybethedepthscaleiswrong? Richard_Stern December31,2020,2:47am #9 Okaywait,nevermindallthat.Justrealisedtheshadowmapisn’trightbecausethespheresshouldbedarkerthanthebackground(theyareclosertothelightandcloserisdarker) SoaftersomemoredebuggingIhavenarroweddowntheproblemtobeintherenderingoftheshadowmapbutI’mjustnotsurewhy: IfIsetthelight’spositiontobe9ontheXaxisthenitrendersfine,andasyoucanseeontheshadowmapthespheresaredarkerthanthebackground.(There’sathinseambutthat’sbecauseI’mnotusingacubemap,willworryaboutthatlater) Shadows11437×803127KB ThenifImovethelightto10ontheXaxis,thebackgroundoftheshadowmapgoesblack,whichisobviouslywrong: Shadows21437×803104KB Thenat11ontheXaxis,thebackgroundoftheshadowmapislighteningagainbutit’sstillwrongbecauseitshouldbelighterthanthespheres: Shadows31437×803109KB Sowhatwouldcausethedepthmaptogoblack?HaveIjustwrappedaroundthedepthvaluesorsomething?Howwouldthatevenhappen? Myrenderingshaderisjust: #ifOPENGL #defineSV_POSITIONPOSITION #defineVS_SHADERMODELvs_3_0 #definePS_SHADERMODELps_3_0 #else #defineVS_SHADERMODELvs_5_0 #definePS_SHADERMODELps_5_0 #endif //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- float4x4_World; float4x4_LightViewProjection; //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- structVertexShaderOutput { float4Position:SV_POSITION; floatDepth:TEXCOORD0; }; //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- VertexShaderOutputMainVS(float4Position:POSITION0) { VertexShaderOutputoutput=(VertexShaderOutput)0; float4worldPos=mul(Position,_World); output.Position=mul(worldPos,_LightViewProjection); output.Depth=output.Position.z/output.Position.w; returnoutput; } float4MainPS(VertexShaderOutputinput):COLOR { returnfloat4(input.Depth,0,0,0); } //---------------------------------------------------------------------------------- //Techniqueandpasseswithinthetechnique //---------------------------------------------------------------------------------- techniqueMainEffect { passPass0 { VertexShader=compileVS_SHADERMODELMainVS(); PixelShader=compilePS_SHADERMODELMainPS(); } }; Anyideas? markus December31,2020,3:16am #10 output.Depth=output.Position.z/output.Position.w; Ifyoudothew-divisioninthevertexshader,theautomaticdepth-interpolationbetweentheverticeswillbeoff.Iftheverticesareclosetogether,it’snotnoticeable.Iftheyarefarapart,likeinyourgroundplane,itbecomesaproblem.YoucansolveitbypassingPosition.zwtothepixelshaderanddothedepthcalculationthere. 2Likes Richard_Stern December31,2020,5:09am #11 Thatwasit!Thanks! Workingwith2pointlights: ShadowsWorking1431×801119KB Testwith4colouredlights: ColoredShadows1431×799141KB 4Likes willmotil January5,2021,8:48am #12 Thatisquiteniceineverdidfigureouthowtodopcfifyouwriteupatutorialidreaditforsure. Richard_Stern January6,2021,4:45am #13 IcobbledittogetherfromabunchofthingsIread.I’dsayIunderstanditabout80%whichisnotenoughtoreallywriteaninformedtutorial.Happytosharethecodethough. Thisismyshader,itusesPBRlightingandhasshadowmappingfor1directionallightandupto8pointlights. Mysourcesare: PBRshaderbasedonhttps://learnopengl.com/PBR/Lighting ShadowmapsbasedonShadowmappingonMonogame Afewcaveats:Itisdefinitelynotthemostefficientorwellwrittenshader,myfocuswasjustongettingitworking.Alsoitusesanarrayof6texturestodothepointlightshadowsinsteadofacubemapwhichleadstoseamsalongtheedges. Sowithallthatsaid,here’sthecode //---------------------------------------------------------------------------------- //Standarddefines //---------------------------------------------------------------------------------- #ifOPENGL #defineSV_POSITIONPOSITION #defineVS_SHADERMODELvs_3_0 #definePS_SHADERMODELps_3_0 #else #defineVS_SHADERMODELvs_5_0 #definePS_SHADERMODELps_5_0 #endif //---------------------------------------------------------------------------------- //Properties //---------------------------------------------------------------------------------- float4x4_World; float4x4_View; float4x4_Projection; float3_CameraPos; float4_Color; Texture2D_Albedo; Texture2D_Metalness; Texture2D_Displacement; Texture2D_Normal; Texture2D_Roughness; Texture2D_AO; //Lights staticconstintMaxDirectionalLights=8; staticconstintMaxPointLights=8; staticconstintCubeSides=6; staticconstfloat3FaceDirectons[CubeSides]={ float3(1,0,0), float3(-1,0,0), float3(0,1,0), float3(0,-1,0), float3(0,0,1), float3(0,0,-1), }; float3_AmbientColor; float3_DirectionalLights[MaxDirectionalLights]; float3_DirectionalColors[MaxDirectionalLights]; float_DirectionalIntensity[MaxDirectionalLights]; float3_PointLightPos[MaxPointLights]; float3_PointLightColors[MaxPointLights]; float_PointLightIntensity[MaxPointLights]; float_PointLightRange[MaxPointLights]; //Shadows Texture2D_DirectionalShadowMap; SamplerStateDirectionalShadowMapSampler { Texture=(_DirectionalShadowMap); MinFilter=point; MagFilter=point; MipFilter=point; AddressU=Wrap; AddressV=Wrap; }; Texture2DArray_PointShadowMap; SamplerStatePointShadowMapSampler { Texture=(_PointShadowMap); MinFilter=point; MagFilter=point; MipFilter=point; AddressU=Wrap; AddressV=Wrap; }; float4x4_LightSpaceMatrix; float4x4_PointLightSpaceMatrix[MaxPointLights*CubeSides]; int_ShadowMapSize; float_DepthBias; int_DirectionalShadowIndex; //---------------------------------------------------------------------------------- staticconstfloatPI=3.14159265359; //---------------------------------------------------------------------------------- //Requiredattributesoftheinputvertices //---------------------------------------------------------------------------------- structVertexShaderInput { float3Position:POSITION0; float3Normal:NORMAL; //float3Tangent:TANGENT; //float3Binormal:BINORMAL; float2TextureUV:TEXCOORD0; }; //Semanticsforoutputofvertexshader/inputofpixelshader structVertexShaderOutput { float4Position:SV_POSITION; float2TextureUV:TEXCOORD0; float3Normal:TEXCOORD1; //float3Tangent:TEXCOORD2; //float3Binormal:TEXCOORD3; float3WorldPosition:TEXCOORD2; }; SamplerStateMeshTextureSampler { Filter=Anisotropic; AddressU=Wrap; AddressV=Wrap; }; //---------------------------------------------------------------------------------- //PBRequations //---------------------------------------------------------------------------------- float3fresnelSchlick(floatcosTheta,float3F0) { cosTheta=min(cosTheta,1.0); returnF0+(1.0-F0)*pow(1.0-cosTheta,5.0); } floatDistributionGGX(float3N,float3H,floatroughness) { floata=roughness*roughness; floata2=a*a; floatNdotH=max(dot(N,H),0.0); floatNdotH2=NdotH*NdotH; floatnum=a2; floatdenom=(NdotH2*(a2-1.0)+1.0); denom=PI*denom*denom; returnnum/denom; } floatGeometrySchlickGGX(floatNdotV,floatroughness) { floatr=(roughness+1.0); floatk=(r*r)/8.0; floatnum=NdotV; floatdenom=NdotV*(1.0-k)+k; returnnum/denom; } floatGeometrySmith(float3N,float3V,float3L,floatroughness) { floatNdotV=max(dot(N,V),0.0); floatNdotL=max(dot(N,L),0.0); floatggx2=GeometrySchlickGGX(NdotV,roughness); floatggx1=GeometrySchlickGGX(NdotL,roughness); returnggx1*ggx2; } //Generatingtangentsandbinormalsbasedonhttps://github.com/JoeyDeVries/LearnOpenGL/blob/master/src/6.pbr/1.2.lighting_textured/1.2.pbr.fs float3getNormalFromMap(VertexShaderOutputinput) { float3tangentNormal=_Normal.Sample(MeshTextureSampler,input.TextureUV).rgb; tangentNormal=normalize(tangentNormal*2.0-1.0); float3Q1=ddx(input.WorldPosition); float3Q2=ddy(input.WorldPosition); float2st1=ddx(input.TextureUV); float2st2=ddy(input.TextureUV); float3N=normalize(input.Normal); float3T=-normalize(Q1*st2.y-Q2*st1.y); float3B=normalize(cross(N,T)); //float3N=normalize(input.Normal); //float3T=normalize(input.Tangent); //float3B=normalize(input.Binormal); float3x3TBN=float3x3(T,B,N); returnnormalize(mul(tangentNormal,TBN)); } //---------------------------------------------------------------------------------- //Directionallights:CalculatestheshadowtermusingPCF //---------------------------------------------------------------------------------- floatCalcDirectionalShadowsPCF(floatlight_space_depth,floatndotl,float2shadow_coord) { floatshadow_term=0; floatvariableBias=clamp(0.001*tan(acos(ndotl)),0,_DepthBias); //safetoassumeit'sasquare floatsize=1.0/_ShadowMapSize; floatsamples[4]; samples[0]=(light_space_depth-variableBias<_directionalshadowmap.sample samples shadow_term="(samples[0]+samples[1]+samples[2]+samples[3])/4.0;" returnshadow_term floatcalcpointshadowspcf floatshadow_term="0;" floatvariablebias="clamp(0.001*tan(acos(ndotl)),0,_DepthBias);" floatsize="1.0/_ShadowMapSize;" floatsamples float3calculatepointlights float3v="normalize(_CameraPos-worldPosition);" float3f0="float3(0.04,0.04,0.04);" f0="lerp(F0,albedo,metallic);" float3lo="float3(0.0,0.0,0.0);" for float3l="normalize(_PointLightPos[i]-worldPosition);" float3h="normalize(V+L);" floatdistance="length(_PointLightPos[i]-worldPosition);" floatattenuation="_PointLightRange[i]/(distance*distance);" float3radiance="_PointLightColors[i]*attenuation*_PointLightIntensity[i];" floatndf="DistributionGGX(N,H,roughness);" floatg="GeometrySmith(N,V,L,roughness);" float3f="fresnelSchlick(max(dot(H,V),0.0),F0);" float3ks="F;" float3kd="float3(1.0,1.0,1.0)-kS;" kd float3numerator="NDF*G*F;" floatdenominator="4.0*max(dot(N,V),0.0)*max(dot(N,L),0.0);" float3specular="numerator/max(denominator,0.001);" floatndotl="max(dot(N,L),0.0);" floatshadowcontribution="1.0;" float3directiontofragment="normalize(worldPosition-_PointLightPos[i]);" floatclosestdirection="-1;" intfaceindex="0;" float3forward="FaceDirectons[face];" floatresult="dot(directionToFragment,forward);" if>closestDirection) { closestDirection=result; faceIndex=face; } } intarrayIndex=i*CubeSides+faceIndex; float4lightingPosition=mul(float4(worldPosition,1),_PointLightSpaceMatrix[arrayIndex]); float2shadowTexCoord=mad(0.5,lightingPosition.xy/lightingPosition.w,float2(0.5,0.5)); shadowTexCoord.y=1.0f-shadowTexCoord.y; floatourDepth=(lightingPosition.z/lightingPosition.w); shadowContribution=CalcPointShadowsPCF(ourDepth,NdotL,float3(shadowTexCoord,arrayIndex)); Lo+=(kD*albedo/PI+specular)*radiance*NdotL*shadowContribution; } returnLo; } float3CalculateDirectionalLights(float3worldPosition,float3N,float3albedo,floatmetallic,floatroughness) { float3V=normalize(_CameraPos-worldPosition); //Calculatesurfacereflectionatzeroincidence,defaultto0.04butadjustformetallicsurfaces. float3F0=float3(0.04,0.04,0.04); F0=lerp(F0,albedo,metallic); //Reflectionequation float3Lo=float3(0.0,0.0,0.0); for(inti=0;i



請為這篇文章評分?