@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 3.12 kB
JavaScript
import{math as e}from"../../core/math/math.js";import{Vec3 as s}from"../../core/math/vec3.js";import{Mat4 as a}from"../../core/math/mat4.js";import{BoundingBox as t}from"../../core/shape/bounding-box.js";import{SHADOWUPDATE_NONE as o}from"../constants.js";import{ShadowMap as r}from"./shadow-map.js";import{RenderPassShadowDirectional as n}from"./render-pass-shadow-directional.js";const i=new t,d=new s,c=new a,l=[new s,new s,new s,new s,new s,new s,new s,new s],h={min:0,max:0};function m(e,s,a){l[0].x=l[1].x=l[2].x=l[3].x=s.x,l[1].y=l[3].y=l[7].y=l[5].y=s.y,l[2].z=l[3].z=l[6].z=l[7].z=s.z,l[4].x=l[5].x=l[6].x=l[7].x=a.x,l[0].y=l[2].y=l[4].y=l[6].y=a.y,l[0].z=l[1].z=l[4].z=l[5].z=a.z;let t=9999999999,o=-9999999999;for(let s=0;s<8;++s){e.transformPoint(l[s],l[s]);const a=l[s].z;a<t&&(t=a),a>o&&(o=a)}return h.min=t,h.max=o,h}class w{constructor(e,s){this.renderer=void 0,this.shadowRenderer=void 0,this.device=void 0,this.renderer=e,this.shadowRenderer=s,this.device=e.device}cull(e,s,a,t=null){e.visibleThisFrame=!0,e._shadowMap||(e._shadowMap=r.create(this.device,e));const n=a._nearClip;this.generateSplitDistances(e,n,Math.min(a._farClip,e.shadowDistance));const l=e.shadowUpdateOverrides;for(let r=0;r<e.numCascades&&(null==l?void 0:l[r])!==o;r++){const o=e.getRenderData(a,r),l=o.shadowCamera;l.renderTarget=e._shadowMap.renderTargets[0],o.shadowViewport.copy(e.cascades[r]),o.shadowScissor.copy(e.cascades[r]);const h=l._node,w=e._node;h.setPosition(w.getPosition()),h.setRotation(w.getRotation()),h.rotateLocal(-90,0,0);const p=0===r?n:e._shadowCascadeDistances[r-1],u=e._shadowCascadeDistances[r],f=a.getFrustumCorners(p,u);d.set(0,0,0);const g=a.node.getWorldTransform();for(let e=0;e<8;e++)g.transformPoint(f[e],f[e]),d.add(f[e]);d.mulScalar(1/8);let C=0;for(let e=0;e<8;e++){const s=f[e].sub(d).length();s>C&&(C=s)}const v=h.right,x=h.up,R=h.forward,y=.25*e._shadowResolution/C,_=Math.ceil(d.dot(x)*y)/y,b=Math.ceil(d.dot(v)*y)/y,z=x.mulScalar(_),S=v.mulScalar(b),D=d.dot(R),j=R.mulScalar(D);d.add2(z,S).add(j),h.setPosition(d),h.translateLocal(0,0,1e6),l.nearClip=.01,l.farClip=2e6,l.orthoHeight=C,this.renderer.updateCameraFrustum(l),this.shadowRenderer.cullShadowCasters(s,e,o.visibleCasters,l,t);let M=!0;const P=o.visibleCasters;for(let e=0;e<P.length;e++){const s=P[e];M?(M=!1,i.copy(s.aabb)):i.add(s.aabb)}c.copy(h.getWorldTransform()).invert();const F=m(c,i.getMin(),i.getMax());h.translateLocal(0,0,F.max+.1),l.farClip=F.max-F.min+.2,o.depthRangeCompensation=l.farClip,o.projectionCompensation=C}}generateSplitDistances(s,a,t){s._shadowCascadeDistances.fill(t);for(let o=1;o<s.numCascades;o++){const r=o/s.numCascades,n=a+(t-a)*r,i=a*(t/a)**r,d=e.lerp(n,i,s.cascadeDistribution);s._shadowCascadeDistances[o-1]=d}}getLightRenderPass(e,s){let a=null;if(this.shadowRenderer.needsShadowRendering(e)){const t=e.numShadowFaces,r=e.shadowUpdateOverrides;let i,d=!0;for(let a=0;a<t;a++)(null==r?void 0:r[a])===o&&(d=!1),i=this.shadowRenderer.prepareFace(e,s,a);a=new n(this.device,this.shadowRenderer,e,s,d),this.shadowRenderer.setupRenderPass(a,i,d)}return a}}export{w as ShadowRendererDirectional};