How to use shadow method in wpt

Best JavaScript code snippet using wpt

ShadowMap.js

Source:ShadowMap.js Github

copy

Full Screen

1define([2 '../Core/BoundingRectangle',3 '../Core/BoundingSphere',4 '../Core/BoxOutlineGeometry',5 '../Core/Cartesian2',6 '../Core/Cartesian3',7 '../Core/Cartesian4',8 '../Core/Cartographic',9 '../Core/clone',10 '../Core/Color',11 '../Core/ColorGeometryInstanceAttribute',12 '../Core/combine',13 '../Core/CullingVolume',14 '../Core/defaultValue',15 '../Core/defined',16 '../Core/defineProperties',17 '../Core/destroyObject',18 '../Core/DeveloperError',19 '../Core/FeatureDetection',20 '../Core/GeometryInstance',21 '../Core/Intersect',22 '../Core/Math',23 '../Core/Matrix4',24 '../Core/OrthographicOffCenterFrustum',25 '../Core/PerspectiveFrustum',26 '../Core/PixelFormat',27 '../Core/Quaternion',28 '../Core/SphereOutlineGeometry',29 '../Core/WebGLConstants',30 '../Renderer/ClearCommand',31 '../Renderer/ContextLimits',32 '../Renderer/CubeMap',33 '../Renderer/DrawCommand',34 '../Renderer/Framebuffer',35 '../Renderer/Pass',36 '../Renderer/PassState',37 '../Renderer/PixelDatatype',38 '../Renderer/Renderbuffer',39 '../Renderer/RenderbufferFormat',40 '../Renderer/RenderState',41 '../Renderer/Sampler',42 '../Renderer/Texture',43 '../Renderer/TextureMagnificationFilter',44 '../Renderer/TextureMinificationFilter',45 '../Renderer/TextureWrap',46 './Camera',47 './CullFace',48 './DebugCameraPrimitive',49 './PerInstanceColorAppearance',50 './Primitive',51 './ShadowMapShader'52 ], function(53 BoundingRectangle,54 BoundingSphere,55 BoxOutlineGeometry,56 Cartesian2,57 Cartesian3,58 Cartesian4,59 Cartographic,60 clone,61 Color,62 ColorGeometryInstanceAttribute,63 combine,64 CullingVolume,65 defaultValue,66 defined,67 defineProperties,68 destroyObject,69 DeveloperError,70 FeatureDetection,71 GeometryInstance,72 Intersect,73 CesiumMath,74 Matrix4,75 OrthographicOffCenterFrustum,76 PerspectiveFrustum,77 PixelFormat,78 Quaternion,79 SphereOutlineGeometry,80 WebGLConstants,81 ClearCommand,82 ContextLimits,83 CubeMap,84 DrawCommand,85 Framebuffer,86 Pass,87 PassState,88 PixelDatatype,89 Renderbuffer,90 RenderbufferFormat,91 RenderState,92 Sampler,93 Texture,94 TextureMagnificationFilter,95 TextureMinificationFilter,96 TextureWrap,97 Camera,98 CullFace,99 DebugCameraPrimitive,100 PerInstanceColorAppearance,101 Primitive,102 ShadowMapShader) {103 'use strict';104 /**105 * Use {@link Viewer#shadowMap} to get the scene's shadow map originating from the sun. Do not construct this directly.106 *107 * <p>108 * The normalOffset bias pushes the shadows forward slightly, and may be disabled109 * for applications that require ultra precise shadows.110 * </p>111 *112 * @alias ShadowMap113 * @internalConstructor114 * @class115 *116 * @param {Object} options An object containing the following properties:117 * @param {Camera} options.lightCamera A camera representing the light source.118 * @param {Boolean} [options.enabled=true] Whether the shadow map is enabled.119 * @param {Boolean} [options.isPointLight=false] Whether the light source is a point light. Point light shadows do not use cascades.120 * @param {Boolean} [options.pointLightRadius=100.0] Radius of the point light.121 * @param {Boolean} [options.cascadesEnabled=true] Use multiple shadow maps to cover different partitions of the view frustum.122 * @param {Number} [options.numberOfCascades=4] The number of cascades to use for the shadow map. Supported values are one and four.123 * @param {Number} [options.maximumDistance=5000.0] The maximum distance used for generating cascaded shadows. Lower values improve shadow quality.124 * @param {Number} [options.size=2048] The width and height, in pixels, of each shadow map.125 * @param {Boolean} [options.softShadows=false] Whether percentage-closer-filtering is enabled for producing softer shadows.126 * @param {Number} [options.darkness=0.3] The shadow darkness.127 * @param {Boolean} [options.normalOffset=true] Whether a normal bias is applied to shadows.128 *129 * @exception {DeveloperError} Only one or four cascades are supported.130 *131 * @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Shadows.html|Cesium Sandcastle Shadows Demo}132 */133 function ShadowMap(options) {134 options = defaultValue(options, defaultValue.EMPTY_OBJECT);135 // options.context is an undocumented option136 var context = options.context;137 //>>includeStart('debug', pragmas.debug);138 if (!defined(context)) {139 throw new DeveloperError('context is required.');140 }141 if (!defined(options.lightCamera)) {142 throw new DeveloperError('lightCamera is required.');143 }144 if (defined(options.numberOfCascades) && ((options.numberOfCascades !== 1) && (options.numberOfCascades !== 4))) {145 throw new DeveloperError('Only one or four cascades are supported.');146 }147 //>>includeEnd('debug');148 this._enabled = defaultValue(options.enabled, true);149 this._softShadows = defaultValue(options.softShadows, false);150 this._normalOffset = defaultValue(options.normalOffset, true);151 this.dirty = true;152 /**153 * Specifies whether the shadow map originates from a light source. Shadow maps that are used for analytical154 * purposes should set this to false so as not to affect scene rendering.155 *156 * @private157 */158 this.fromLightSource = defaultValue(options.fromLightSource, true);159 /**160 * Determines the darkness of the shadows.161 *162 * @type {Number}163 * @default 0.3164 */165 this.darkness = defaultValue(options.darkness, 0.3);166 this._darkness = this.darkness;167 /**168 * Determines the maximum distance of the shadow map. Only applicable for cascaded shadows. Larger distances may result in lower quality shadows.169 *170 * @type {Number}171 * @default 5000.0172 */173 this.maximumDistance = defaultValue(options.maximumDistance, 5000.0);174 this._outOfView = false;175 this._outOfViewPrevious = false;176 this._needsUpdate = true;177 // In IE11 and Edge polygon offset is not functional.178 // TODO : Also disabled for instances of Firefox and Chrome running ANGLE that do not support depth textures.179 // Re-enable once https://github.com/AnalyticalGraphicsInc/cesium/issues/4560 is resolved.180 var polygonOffsetSupported = true;181 if (FeatureDetection.isInternetExplorer() || FeatureDetection.isEdge() || ((FeatureDetection.isChrome() || FeatureDetection.isFirefox()) && FeatureDetection.isWindows() && !context.depthTexture)) {182 polygonOffsetSupported = false;183 }184 this._polygonOffsetSupported = polygonOffsetSupported;185 this._terrainBias = {186 polygonOffset : polygonOffsetSupported,187 polygonOffsetFactor : 1.1,188 polygonOffsetUnits : 4.0,189 normalOffset : this._normalOffset,190 normalOffsetScale : 0.5,191 normalShading : true,192 normalShadingSmooth : 0.3,193 depthBias : 0.0001194 };195 this._primitiveBias = {196 polygonOffset : polygonOffsetSupported,197 polygonOffsetFactor : 1.1,198 polygonOffsetUnits : 4.0,199 normalOffset : this._normalOffset,200 normalOffsetScale : 0.1,201 normalShading : true,202 normalShadingSmooth : 0.05,203 depthBias : 0.00002204 };205 this._pointBias = {206 polygonOffset : false,207 polygonOffsetFactor : 1.1,208 polygonOffsetUnits : 4.0,209 normalOffset : this._normalOffset,210 normalOffsetScale : 0.0,211 normalShading : true,212 normalShadingSmooth : 0.1,213 depthBias : 0.0005214 };215 // Framebuffer resources216 this._depthAttachment = undefined;217 this._colorAttachment = undefined;218 // Uniforms219 this._shadowMapMatrix = new Matrix4();220 this._shadowMapTexture = undefined;221 this._lightDirectionEC = new Cartesian3();222 this._lightPositionEC = new Cartesian4();223 this._distance = 0.0;224 this._lightCamera = options.lightCamera;225 this._shadowMapCamera = new ShadowMapCamera();226 this._shadowMapCullingVolume = undefined;227 this._sceneCamera = undefined;228 this._boundingSphere = new BoundingSphere();229 this._isPointLight = defaultValue(options.isPointLight, false);230 this._pointLightRadius = defaultValue(options.pointLightRadius, 100.0);231 this._cascadesEnabled = this._isPointLight ? false : defaultValue(options.cascadesEnabled, true);232 this._numberOfCascades = !this._cascadesEnabled ? 0 : defaultValue(options.numberOfCascades, 4);233 this._fitNearFar = true;234 this._maximumCascadeDistances = [25.0, 150.0, 700.0, Number.MAX_VALUE];235 this._textureSize = new Cartesian2();236 this._isSpotLight = false;237 if (this._cascadesEnabled) {238 // Cascaded shadows are always orthographic. The frustum dimensions are calculated on the fly.239 this._shadowMapCamera.frustum = new OrthographicOffCenterFrustum();240 } else if (defined(this._lightCamera.frustum.fov)) {241 // If the light camera uses a perspective frustum, then the light source is a spot light242 this._isSpotLight = true;243 }244 // Uniforms245 this._cascadeSplits = [new Cartesian4(), new Cartesian4()];246 this._cascadeMatrices = [new Matrix4(), new Matrix4(), new Matrix4(), new Matrix4()];247 this._cascadeDistances = new Cartesian4();248 var numberOfPasses;249 if (this._isPointLight) {250 numberOfPasses = 6; // One shadow map for each direction251 } else if (!this._cascadesEnabled) {252 numberOfPasses = 1;253 } else {254 numberOfPasses = this._numberOfCascades;255 }256 this._passes = new Array(numberOfPasses);257 for (var i = 0; i < numberOfPasses; ++i) {258 this._passes[i] = new ShadowPass(context);259 }260 this.debugShow = false;261 this.debugFreezeFrame = false;262 this._debugFreezeFrame = false;263 this._debugCascadeColors = false;264 this._debugLightFrustum = undefined;265 this._debugCameraFrustum = undefined;266 this._debugCascadeFrustums = new Array(this._numberOfCascades);267 this._debugShadowViewCommand = undefined;268 this._usesDepthTexture = context.depthTexture;269 if (this._isPointLight) {270 this._usesDepthTexture = false;271 }272 // Create render states for shadow casters273 this._primitiveRenderState = undefined;274 this._terrainRenderState = undefined;275 this._pointRenderState = undefined;276 createRenderStates(this);277 // For clearing the shadow map texture every frame278 this._clearCommand = new ClearCommand({279 depth : 1.0,280 color : new Color()281 });282 this._clearPassState = new PassState(context);283 this._size = defaultValue(options.size, 2048);284 this.size = this._size;285 }286 /**287 * Global maximum shadow distance used to prevent far off receivers from extending288 * the shadow far plane. This helps set a tighter near/far when viewing objects from space.289 *290 * @private291 */292 ShadowMap.MAXIMUM_DISTANCE = 20000.0;293 function ShadowPass(context) {294 this.camera = new ShadowMapCamera();295 this.passState = new PassState(context);296 this.framebuffer = undefined;297 this.textureOffsets = undefined;298 this.commandList = [];299 this.cullingVolume = undefined;300 }301 function createRenderState(colorMask, bias) {302 return RenderState.fromCache({303 cull : {304 enabled : true,305 face : CullFace.BACK306 },307 depthTest : {308 enabled : true309 },310 colorMask : {311 red : colorMask,312 green : colorMask,313 blue : colorMask,314 alpha : colorMask315 },316 depthMask : true,317 polygonOffset : {318 enabled : bias.polygonOffset,319 factor : bias.polygonOffsetFactor,320 units : bias.polygonOffsetUnits321 }322 });323 }324 function createRenderStates(shadowMap) {325 // Enable the color mask if the shadow map is backed by a color texture, e.g. when depth textures aren't supported326 var colorMask = !shadowMap._usesDepthTexture;327 shadowMap._primitiveRenderState = createRenderState(colorMask, shadowMap._primitiveBias);328 shadowMap._terrainRenderState = createRenderState(colorMask, shadowMap._terrainBias);329 shadowMap._pointRenderState = createRenderState(colorMask, shadowMap._pointBias);330 }331 /**332 * @private333 */334 ShadowMap.prototype.debugCreateRenderStates = function() {335 createRenderStates(this);336 };337 defineProperties(ShadowMap.prototype, {338 /**339 * Determines if the shadow map will be shown.340 *341 * @memberof ShadowMap.prototype342 * @type {Boolean}343 * @default true344 */345 enabled : {346 get : function() {347 return this._enabled;348 },349 set : function(value) {350 this.dirty = this._enabled !== value;351 this._enabled = value;352 }353 },354 /**355 * Determines if a normal bias will be applied to shadows.356 *357 * @memberof ShadowMap.prototype358 * @type {Boolean}359 * @default true360 */361 normalOffset : {362 get : function() {363 return this._normalOffset;364 },365 set : function(value) {366 this.dirty = this._normalOffset !== value;367 this._normalOffset = value;368 this._terrainBias.normalOffset = value;369 this._primitiveBias.normalOffset = value;370 this._pointBias.normalOffset = value;371 }372 },373 /**374 * Determines if soft shadows are enabled. Uses pcf filtering which requires more texture reads and may hurt performance.375 *376 * @memberof ShadowMap.prototype377 * @type {Boolean}378 * @default false379 */380 softShadows : {381 get : function() {382 return this._softShadows;383 },384 set : function(value) {385 this.dirty = this._softShadows !== value;386 this._softShadows = value;387 }388 },389 /**390 * The width and height, in pixels, of each shadow map.391 *392 * @memberof ShadowMap.prototype393 * @type {Number}394 * @default 2048395 */396 size : {397 get : function() {398 return this._size;399 },400 set : function(value) {401 resize(this, value);402 }403 },404 /**405 * Whether the shadow map is out of view of the scene camera.406 *407 * @memberof ShadowMap.prototype408 * @type {Boolean}409 * @readonly410 * @private411 */412 outOfView : {413 get : function() {414 return this._outOfView;415 }416 },417 /**418 * The culling volume of the shadow frustum.419 *420 * @memberof ShadowMap.prototype421 * @type {CullingVolume}422 * @readonly423 * @private424 */425 shadowMapCullingVolume : {426 get : function() {427 return this._shadowMapCullingVolume;428 }429 },430 /**431 * The passes used for rendering shadows. Each face of a point light or each cascade for a cascaded shadow map is a separate pass.432 *433 * @memberof ShadowMap.prototype434 * @type {ShadowPass[]}435 * @readonly436 * @private437 */438 passes : {439 get : function() {440 return this._passes;441 }442 },443 /**444 * Whether the light source is a point light.445 *446 * @memberof ShadowMap.prototype447 * @type {Boolean}448 * @readonly449 * @private450 */451 isPointLight : {452 get : function() {453 return this._isPointLight;454 }455 },456 /**457 * Debug option for visualizing the cascades by color.458 *459 * @memberof ShadowMap.prototype460 * @type {Boolean}461 * @default false462 * @private463 */464 debugCascadeColors : {465 get : function() {466 return this._debugCascadeColors;467 },468 set : function(value) {469 this.dirty = this._debugCascadeColors !== value;470 this._debugCascadeColors = value;471 }472 }473 });474 function destroyFramebuffer(shadowMap) {475 var length = shadowMap._passes.length;476 for (var i = 0; i < length; ++i) {477 var pass = shadowMap._passes[i];478 var framebuffer = pass.framebuffer;479 if (defined(framebuffer) && !framebuffer.isDestroyed()) {480 framebuffer.destroy();481 }482 pass.framebuffer = undefined;483 }484 // Destroy the framebuffer attachments485 shadowMap._depthAttachment = shadowMap._depthAttachment && shadowMap._depthAttachment.destroy();486 shadowMap._colorAttachment = shadowMap._colorAttachment && shadowMap._colorAttachment.destroy();487 }488 function createSampler() {489 return new Sampler({490 wrapS : TextureWrap.CLAMP_TO_EDGE,491 wrapT : TextureWrap.CLAMP_TO_EDGE,492 minificationFilter : TextureMinificationFilter.NEAREST,493 magnificationFilter : TextureMagnificationFilter.NEAREST494 });495 }496 function createFramebufferColor(shadowMap, context) {497 var depthRenderbuffer = new Renderbuffer({498 context : context,499 width : shadowMap._textureSize.x,500 height : shadowMap._textureSize.y,501 format : RenderbufferFormat.DEPTH_COMPONENT16502 });503 var colorTexture = new Texture({504 context : context,505 width : shadowMap._textureSize.x,506 height : shadowMap._textureSize.y,507 pixelFormat : PixelFormat.RGBA,508 pixelDatatype : PixelDatatype.UNSIGNED_BYTE,509 sampler : createSampler()510 });511 var framebuffer = new Framebuffer({512 context : context,513 depthRenderbuffer : depthRenderbuffer,514 colorTextures : [colorTexture],515 destroyAttachments : false516 });517 var length = shadowMap._passes.length;518 for (var i = 0; i < length; ++i) {519 var pass = shadowMap._passes[i];520 pass.framebuffer = framebuffer;521 pass.passState.framebuffer = framebuffer;522 }523 shadowMap._shadowMapTexture = colorTexture;524 shadowMap._depthAttachment = depthRenderbuffer;525 shadowMap._colorAttachment = colorTexture;526 }527 function createFramebufferDepth(shadowMap, context) {528 var depthStencilTexture = new Texture({529 context : context,530 width : shadowMap._textureSize.x,531 height : shadowMap._textureSize.y,532 pixelFormat : PixelFormat.DEPTH_STENCIL,533 pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8,534 sampler : createSampler()535 });536 var framebuffer = new Framebuffer({537 context : context,538 depthStencilTexture : depthStencilTexture,539 destroyAttachments : false540 });541 var length = shadowMap._passes.length;542 for (var i = 0; i < length; ++i) {543 var pass = shadowMap._passes[i];544 pass.framebuffer = framebuffer;545 pass.passState.framebuffer = framebuffer;546 }547 shadowMap._shadowMapTexture = depthStencilTexture;548 shadowMap._depthAttachment = depthStencilTexture;549 }550 function createFramebufferCube(shadowMap, context) {551 var depthRenderbuffer = new Renderbuffer({552 context : context,553 width : shadowMap._textureSize.x,554 height : shadowMap._textureSize.y,555 format : RenderbufferFormat.DEPTH_COMPONENT16556 });557 var cubeMap = new CubeMap({558 context : context,559 width : shadowMap._textureSize.x,560 height : shadowMap._textureSize.y,561 pixelFormat : PixelFormat.RGBA,562 pixelDatatype : PixelDatatype.UNSIGNED_BYTE,563 sampler : createSampler()564 });565 var faces = [cubeMap.negativeX, cubeMap.negativeY, cubeMap.negativeZ, cubeMap.positiveX, cubeMap.positiveY, cubeMap.positiveZ];566 for (var i = 0; i < 6; ++i) {567 var framebuffer = new Framebuffer({568 context : context,569 depthRenderbuffer : depthRenderbuffer,570 colorTextures : [faces[i]],571 destroyAttachments : false572 });573 var pass = shadowMap._passes[i];574 pass.framebuffer = framebuffer;575 pass.passState.framebuffer = framebuffer;576 }577 shadowMap._shadowMapTexture = cubeMap;578 shadowMap._depthAttachment = depthRenderbuffer;579 shadowMap._colorAttachment = cubeMap;580 }581 function createFramebuffer(shadowMap, context) {582 if (shadowMap._isPointLight) {583 createFramebufferCube(shadowMap, context);584 } else if (shadowMap._usesDepthTexture) {585 createFramebufferDepth(shadowMap, context);586 } else {587 createFramebufferColor(shadowMap, context);588 }589 }590 function checkFramebuffer(shadowMap, context) {591 // Attempt to make an FBO with only a depth texture. If it fails, fallback to a color texture.592 if (shadowMap._usesDepthTexture && (shadowMap._passes[0].framebuffer.status !== WebGLConstants.FRAMEBUFFER_COMPLETE)) {593 shadowMap._usesDepthTexture = false;594 createRenderStates(shadowMap);595 destroyFramebuffer(shadowMap);596 createFramebuffer(shadowMap, context);597 }598 }599 function updateFramebuffer(shadowMap, context) {600 if (!defined(shadowMap._passes[0].framebuffer) || (shadowMap._shadowMapTexture.width !== shadowMap._textureSize.x)) {601 destroyFramebuffer(shadowMap);602 createFramebuffer(shadowMap, context);603 checkFramebuffer(shadowMap, context);604 clearFramebuffer(shadowMap, context);605 }606 }607 function clearFramebuffer(shadowMap, context, shadowPass) {608 shadowPass = defaultValue(shadowPass, 0);609 if (shadowMap._isPointLight || (shadowPass === 0)) {610 shadowMap._clearCommand.framebuffer = shadowMap._passes[shadowPass].framebuffer;611 shadowMap._clearCommand.execute(context, shadowMap._clearPassState);612 }613 }614 function resize(shadowMap, size) {615 shadowMap._size = size;616 var passes = shadowMap._passes;617 var numberOfPasses = passes.length;618 var textureSize = shadowMap._textureSize;619 if (shadowMap._isPointLight) {620 size = (ContextLimits.maximumCubeMapSize >= size) ? size : ContextLimits.maximumCubeMapSize;621 textureSize.x = size;622 textureSize.y = size;623 var faceViewport = new BoundingRectangle(0, 0, size, size);624 passes[0].passState.viewport = faceViewport;625 passes[1].passState.viewport = faceViewport;626 passes[2].passState.viewport = faceViewport;627 passes[3].passState.viewport = faceViewport;628 passes[4].passState.viewport = faceViewport;629 passes[5].passState.viewport = faceViewport;630 } else if (numberOfPasses === 1) {631 // +----+632 // | 1 |633 // +----+634 size = (ContextLimits.maximumTextureSize >= size) ? size : ContextLimits.maximumTextureSize;635 textureSize.x = size;636 textureSize.y = size;637 passes[0].passState.viewport = new BoundingRectangle(0, 0, size, size);638 } else if (numberOfPasses === 4) {639 // +----+----+640 // | 3 | 4 |641 // +----+----+642 // | 1 | 2 |643 // +----+----+644 size = (ContextLimits.maximumTextureSize >= size * 2) ? size : ContextLimits.maximumTextureSize / 2;645 textureSize.x = size * 2;646 textureSize.y = size * 2;647 passes[0].passState.viewport = new BoundingRectangle(0, 0, size, size);648 passes[1].passState.viewport = new BoundingRectangle(size, 0, size, size);649 passes[2].passState.viewport = new BoundingRectangle(0, size, size, size);650 passes[3].passState.viewport = new BoundingRectangle(size, size, size, size);651 }652 // Update clear pass state653 shadowMap._clearPassState.viewport = new BoundingRectangle(0, 0, textureSize.x, textureSize.y);654 // Transforms shadow coordinates [0, 1] into the pass's region of the texture655 for (var i = 0; i < numberOfPasses; ++i) {656 var pass = passes[i];657 var viewport = pass.passState.viewport;658 var biasX = viewport.x / textureSize.x;659 var biasY = viewport.y / textureSize.y;660 var scaleX = viewport.width / textureSize.x;661 var scaleY = viewport.height / textureSize.y;662 pass.textureOffsets = new Matrix4(scaleX, 0.0, 0.0, biasX, 0.0, scaleY, 0.0, biasY, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);663 }664 }665 var scratchViewport = new BoundingRectangle();666 function createDebugShadowViewCommand(shadowMap, context) {667 var fs;668 if (shadowMap._isPointLight) {669 fs = 'uniform samplerCube shadowMap_textureCube; \n' +670 'varying vec2 v_textureCoordinates; \n' +671 'void main() \n' +672 '{ \n' +673 ' vec2 uv = v_textureCoordinates; \n' +674 ' vec3 dir; \n' +675 ' \n' +676 ' if (uv.y < 0.5) \n' +677 ' { \n' +678 ' if (uv.x < 0.333) \n' +679 ' { \n' +680 ' dir.x = -1.0; \n' +681 ' dir.y = uv.x * 6.0 - 1.0; \n' +682 ' dir.z = uv.y * 4.0 - 1.0; \n' +683 ' } \n' +684 ' else if (uv.x < 0.666) \n' +685 ' { \n' +686 ' dir.y = -1.0; \n' +687 ' dir.x = uv.x * 6.0 - 3.0; \n' +688 ' dir.z = uv.y * 4.0 - 1.0; \n' +689 ' } \n' +690 ' else \n' +691 ' { \n' +692 ' dir.z = -1.0; \n' +693 ' dir.x = uv.x * 6.0 - 5.0; \n' +694 ' dir.y = uv.y * 4.0 - 1.0; \n' +695 ' } \n' +696 ' } \n' +697 ' else \n' +698 ' { \n' +699 ' if (uv.x < 0.333) \n' +700 ' { \n' +701 ' dir.x = 1.0; \n' +702 ' dir.y = uv.x * 6.0 - 1.0; \n' +703 ' dir.z = uv.y * 4.0 - 3.0; \n' +704 ' } \n' +705 ' else if (uv.x < 0.666) \n' +706 ' { \n' +707 ' dir.y = 1.0; \n' +708 ' dir.x = uv.x * 6.0 - 3.0; \n' +709 ' dir.z = uv.y * 4.0 - 3.0; \n' +710 ' } \n' +711 ' else \n' +712 ' { \n' +713 ' dir.z = 1.0; \n' +714 ' dir.x = uv.x * 6.0 - 5.0; \n' +715 ' dir.y = uv.y * 4.0 - 3.0; \n' +716 ' } \n' +717 ' } \n' +718 ' \n' +719 ' float shadow = czm_unpackDepth(textureCube(shadowMap_textureCube, dir)); \n' +720 ' gl_FragColor = vec4(vec3(shadow), 1.0); \n' +721 '} \n';722 } else {723 fs = 'uniform sampler2D shadowMap_texture; \n' +724 'varying vec2 v_textureCoordinates; \n' +725 'void main() \n' +726 '{ \n' +727 (shadowMap._usesDepthTexture ?728 ' float shadow = texture2D(shadowMap_texture, v_textureCoordinates).r; \n' :729 ' float shadow = czm_unpackDepth(texture2D(shadowMap_texture, v_textureCoordinates)); \n') +730 ' gl_FragColor = vec4(vec3(shadow), 1.0); \n' +731 '} \n';732 }733 var drawCommand = context.createViewportQuadCommand(fs, {734 uniformMap : {735 shadowMap_texture : function() {736 return shadowMap._shadowMapTexture;737 },738 shadowMap_textureCube : function() {739 return shadowMap._shadowMapTexture;740 }741 }742 });743 drawCommand.pass = Pass.OVERLAY;744 return drawCommand;745 }746 function updateDebugShadowViewCommand(shadowMap, frameState) {747 // Draws the shadow map on the bottom-right corner of the screen748 var context = frameState.context;749 var screenWidth = frameState.context.drawingBufferWidth;750 var screenHeight = frameState.context.drawingBufferHeight;751 var size = Math.min(screenWidth, screenHeight) * 0.3;752 var viewport = scratchViewport;753 viewport.x = screenWidth - size;754 viewport.y = 0;755 viewport.width = size;756 viewport.height = size;757 var debugCommand = shadowMap._debugShadowViewCommand;758 if (!defined(debugCommand)) {759 debugCommand = createDebugShadowViewCommand(shadowMap, context);760 shadowMap._debugShadowViewCommand = debugCommand;761 }762 // Get a new RenderState for the updated viewport size763 if (!defined(debugCommand.renderState) || !BoundingRectangle.equals(debugCommand.renderState.viewport, viewport)) {764 debugCommand.renderState = RenderState.fromCache({765 viewport : BoundingRectangle.clone(viewport)766 });767 }768 frameState.commandList.push(shadowMap._debugShadowViewCommand);769 }770 var frustumCornersNDC = new Array(8);771 frustumCornersNDC[0] = new Cartesian4(-1.0, -1.0, -1.0, 1.0);772 frustumCornersNDC[1] = new Cartesian4(1.0, -1.0, -1.0, 1.0);773 frustumCornersNDC[2] = new Cartesian4(1.0, 1.0, -1.0, 1.0);774 frustumCornersNDC[3] = new Cartesian4(-1.0, 1.0, -1.0, 1.0);775 frustumCornersNDC[4] = new Cartesian4(-1.0, -1.0, 1.0, 1.0);776 frustumCornersNDC[5] = new Cartesian4(1.0, -1.0, 1.0, 1.0);777 frustumCornersNDC[6] = new Cartesian4(1.0, 1.0, 1.0, 1.0);778 frustumCornersNDC[7] = new Cartesian4(-1.0, 1.0, 1.0, 1.0);779 var scratchMatrix = new Matrix4();780 var scratchFrustumCorners = new Array(8);781 for (var i = 0; i < 8; ++i) {782 scratchFrustumCorners[i] = new Cartesian4();783 }784 function createDebugPointLight(modelMatrix, color) {785 var box = new GeometryInstance({786 geometry : new BoxOutlineGeometry({787 minimum : new Cartesian3(-0.5, -0.5, -0.5),788 maximum : new Cartesian3(0.5, 0.5, 0.5)789 }),790 attributes : {791 color : ColorGeometryInstanceAttribute.fromColor(color)792 }793 });794 var sphere = new GeometryInstance({795 geometry : new SphereOutlineGeometry({796 radius : 0.5797 }),798 attributes : {799 color : ColorGeometryInstanceAttribute.fromColor(color)800 }801 });802 return new Primitive({803 geometryInstances : [box, sphere],804 appearance : new PerInstanceColorAppearance({805 translucent : false,806 flat : true807 }),808 asynchronous : false,809 modelMatrix : modelMatrix810 });811 }812 var debugOutlineColors = [Color.RED, Color.GREEN, Color.BLUE, Color.MAGENTA];813 var scratchScale = new Cartesian3();814 function applyDebugSettings(shadowMap, frameState) {815 updateDebugShadowViewCommand(shadowMap, frameState);816 var enterFreezeFrame = shadowMap.debugFreezeFrame && !shadowMap._debugFreezeFrame;817 shadowMap._debugFreezeFrame = shadowMap.debugFreezeFrame;818 // Draw scene camera in freeze frame mode819 if (shadowMap.debugFreezeFrame) {820 if (enterFreezeFrame) {821 // Recreate debug camera when entering freeze frame mode822 shadowMap._debugCameraFrustum = shadowMap._debugCameraFrustum && shadowMap._debugCameraFrustum.destroy();823 shadowMap._debugCameraFrustum = new DebugCameraPrimitive({824 camera : shadowMap._sceneCamera,825 color : Color.CYAN,826 updateOnChange : false827 });828 }829 shadowMap._debugCameraFrustum.update(frameState);830 }831 if (shadowMap._cascadesEnabled) {832 // Draw cascades only in freeze frame mode833 if (shadowMap.debugFreezeFrame) {834 if (enterFreezeFrame) {835 // Recreate debug frustum when entering freeze frame mode836 shadowMap._debugLightFrustum = shadowMap._debugLightFrustum && shadowMap._debugLightFrustum.destroy();837 shadowMap._debugLightFrustum = new DebugCameraPrimitive({838 camera : shadowMap._shadowMapCamera,839 color : Color.YELLOW,840 updateOnChange : false841 });842 }843 shadowMap._debugLightFrustum.update(frameState);844 for (var i = 0; i < shadowMap._numberOfCascades; ++i) {845 if (enterFreezeFrame) {846 // Recreate debug frustum when entering freeze frame mode847 shadowMap._debugCascadeFrustums[i] = shadowMap._debugCascadeFrustums[i] && shadowMap._debugCascadeFrustums[i].destroy();848 shadowMap._debugCascadeFrustums[i] = new DebugCameraPrimitive({849 camera : shadowMap._passes[i].camera,850 color : debugOutlineColors[i],851 updateOnChange : false852 });853 }854 shadowMap._debugCascadeFrustums[i].update(frameState);855 }856 }857 } else if (shadowMap._isPointLight) {858 if (!defined(shadowMap._debugLightFrustum) || shadowMap._needsUpdate) {859 var translation = shadowMap._shadowMapCamera.positionWC;860 var rotation = Quaternion.IDENTITY;861 var uniformScale = shadowMap._pointLightRadius * 2.0;862 var scale = Cartesian3.fromElements(uniformScale, uniformScale, uniformScale, scratchScale);863 var modelMatrix = Matrix4.fromTranslationQuaternionRotationScale(translation, rotation, scale, scratchMatrix);864 shadowMap._debugLightFrustum = shadowMap._debugLightFrustum && shadowMap._debugLightFrustum.destroy();865 shadowMap._debugLightFrustum = createDebugPointLight(modelMatrix, Color.YELLOW);866 }867 shadowMap._debugLightFrustum.update(frameState);868 } else {869 if (!defined(shadowMap._debugLightFrustum) || shadowMap._needsUpdate) {870 shadowMap._debugLightFrustum = new DebugCameraPrimitive({871 camera : shadowMap._shadowMapCamera,872 color : Color.YELLOW,873 updateOnChange : false874 });875 }876 shadowMap._debugLightFrustum.update(frameState);877 }878 }879 function ShadowMapCamera() {880 this.viewMatrix = new Matrix4();881 this.inverseViewMatrix = new Matrix4();882 this.frustum = undefined;883 this.positionCartographic = new Cartographic();884 this.positionWC = new Cartesian3();885 this.directionWC = Cartesian3.clone(Cartesian3.UNIT_Z);886 this.upWC = Cartesian3.clone(Cartesian3.UNIT_Y);887 this.rightWC = Cartesian3.clone(Cartesian3.UNIT_X);888 this.viewProjectionMatrix = new Matrix4();889 }890 ShadowMapCamera.prototype.clone = function(camera) {891 Matrix4.clone(camera.viewMatrix, this.viewMatrix);892 Matrix4.clone(camera.inverseViewMatrix, this.inverseViewMatrix);893 this.frustum = camera.frustum.clone(this.frustum);894 Cartographic.clone(camera.positionCartographic, this.positionCartographic);895 Cartesian3.clone(camera.positionWC, this.positionWC);896 Cartesian3.clone(camera.directionWC, this.directionWC);897 Cartesian3.clone(camera.upWC, this.upWC);898 Cartesian3.clone(camera.rightWC, this.rightWC);899 };900 // Converts from NDC space to texture space901 var scaleBiasMatrix = new Matrix4(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);902 ShadowMapCamera.prototype.getViewProjection = function() {903 var view = this.viewMatrix;904 var projection = this.frustum.projectionMatrix;905 Matrix4.multiply(projection, view, this.viewProjectionMatrix);906 Matrix4.multiply(scaleBiasMatrix, this.viewProjectionMatrix, this.viewProjectionMatrix);907 return this.viewProjectionMatrix;908 };909 var scratchSplits = new Array(5);910 var scratchFrustum = new PerspectiveFrustum();911 var scratchCascadeDistances = new Array(4);912 var scratchMin = new Cartesian3();913 var scratchMax = new Cartesian3();914 function computeCascades(shadowMap, frameState) {915 var shadowMapCamera = shadowMap._shadowMapCamera;916 var sceneCamera = shadowMap._sceneCamera;917 var cameraNear = sceneCamera.frustum.near;918 var cameraFar = sceneCamera.frustum.far;919 var numberOfCascades = shadowMap._numberOfCascades;920 // Split cascades. Use a mix of linear and log splits.921 var i;922 var range = cameraFar - cameraNear;923 var ratio = cameraFar / cameraNear;924 var lambda = 0.9;925 var clampCascadeDistances = false;926 // When the camera is close to a relatively small model, provide more detail in the closer cascades.927 // If the camera is near or inside a large model, such as the root tile of a city, then use the default values.928 // To get the most accurate cascade splits we would need to find the min and max values from the depth texture.929 if (frameState.shadowHints.closestObjectSize < 200.0) {930 clampCascadeDistances = true;931 lambda = 0.9;932 }933 var cascadeDistances = scratchCascadeDistances;934 var splits = scratchSplits;935 splits[0] = cameraNear;936 splits[numberOfCascades] = cameraFar;937 // Find initial splits938 for (i = 0; i < numberOfCascades; ++i) {939 var p = (i + 1) / numberOfCascades;940 var logScale = cameraNear * Math.pow(ratio, p);941 var uniformScale = cameraNear + range * p;942 var split = CesiumMath.lerp(uniformScale, logScale, lambda);943 splits[i + 1] = split;944 cascadeDistances[i] = split - splits[i];945 }946 if (clampCascadeDistances) {947 // Clamp each cascade to its maximum distance948 for (i = 0; i < numberOfCascades; ++i) {949 cascadeDistances[i] = Math.min(cascadeDistances[i], shadowMap._maximumCascadeDistances[i]);950 }951 // Recompute splits952 var distance = splits[0];953 for (i = 0; i < numberOfCascades - 1; ++i) {954 distance += cascadeDistances[i];955 splits[i + 1] = distance;956 }957 }958 Cartesian4.unpack(splits, 0, shadowMap._cascadeSplits[0]);959 Cartesian4.unpack(splits, 1, shadowMap._cascadeSplits[1]);960 Cartesian4.unpack(cascadeDistances, 0, shadowMap._cascadeDistances);961 var shadowFrustum = shadowMapCamera.frustum;962 var left = shadowFrustum.left;963 var right = shadowFrustum.right;964 var bottom = shadowFrustum.bottom;965 var top = shadowFrustum.top;966 var near = shadowFrustum.near;967 var far = shadowFrustum.far;968 var position = shadowMapCamera.positionWC;969 var direction = shadowMapCamera.directionWC;970 var up = shadowMapCamera.upWC;971 var cascadeSubFrustum = sceneCamera.frustum.clone(scratchFrustum);972 var shadowViewProjection = shadowMapCamera.getViewProjection();973 for (i = 0; i < numberOfCascades; ++i) {974 // Find the bounding box of the camera sub-frustum in shadow map texture space975 cascadeSubFrustum.near = splits[i];976 cascadeSubFrustum.far = splits[i + 1];977 var viewProjection = Matrix4.multiply(cascadeSubFrustum.projectionMatrix, sceneCamera.viewMatrix, scratchMatrix);978 var inverseViewProjection = Matrix4.inverse(viewProjection, scratchMatrix);979 var shadowMapMatrix = Matrix4.multiply(shadowViewProjection, inverseViewProjection, scratchMatrix);980 // Project each corner from camera NDC space to shadow map texture space. Min and max will be from 0 to 1.981 var min = Cartesian3.fromElements(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, scratchMin);982 var max = Cartesian3.fromElements(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, scratchMax);983 for (var k = 0; k < 8; ++k) {984 var corner = Cartesian4.clone(frustumCornersNDC[k], scratchFrustumCorners[k]);985 Matrix4.multiplyByVector(shadowMapMatrix, corner, corner);986 Cartesian3.divideByScalar(corner, corner.w, corner); // Handle the perspective divide987 Cartesian3.minimumByComponent(corner, min, min);988 Cartesian3.maximumByComponent(corner, max, max);989 }990 // Limit light-space coordinates to the [0, 1] range991 min.x = Math.max(min.x, 0.0);992 min.y = Math.max(min.y, 0.0);993 min.z = 0.0; // Always start cascade frustum at the top of the light frustum to capture objects in the light's path994 max.x = Math.min(max.x, 1.0);995 max.y = Math.min(max.y, 1.0);996 max.z = Math.min(max.z, 1.0);997 var pass = shadowMap._passes[i];998 var cascadeCamera = pass.camera;999 cascadeCamera.clone(shadowMapCamera); // PERFORMANCE_IDEA : could do a shallow clone for all properties except the frustum1000 var frustum = cascadeCamera.frustum;1001 frustum.left = left + min.x * (right - left);1002 frustum.right = left + max.x * (right - left);1003 frustum.bottom = bottom + min.y * (top - bottom);1004 frustum.top = bottom + max.y * (top - bottom);1005 frustum.near = near + min.z * (far - near);1006 frustum.far = near + max.z * (far - near);1007 pass.cullingVolume = cascadeCamera.frustum.computeCullingVolume(position, direction, up);1008 // Transforms from eye space to the cascade's texture space1009 var cascadeMatrix = shadowMap._cascadeMatrices[i];1010 Matrix4.multiply(cascadeCamera.getViewProjection(), sceneCamera.inverseViewMatrix, cascadeMatrix);1011 Matrix4.multiply(pass.textureOffsets, cascadeMatrix, cascadeMatrix);1012 }1013 }1014 var scratchLightView = new Matrix4();1015 var scratchRight = new Cartesian3();1016 var scratchUp = new Cartesian3();1017 var scratchTranslation = new Cartesian3();1018 function fitShadowMapToScene(shadowMap, frameState) {1019 var shadowMapCamera = shadowMap._shadowMapCamera;1020 var sceneCamera = shadowMap._sceneCamera;1021 // 1. First find a tight bounding box in light space that contains the entire camera frustum.1022 var viewProjection = Matrix4.multiply(sceneCamera.frustum.projectionMatrix, sceneCamera.viewMatrix, scratchMatrix);1023 var inverseViewProjection = Matrix4.inverse(viewProjection, scratchMatrix);1024 // Start to construct the light view matrix. Set translation later once the bounding box is found.1025 var lightDir = shadowMapCamera.directionWC;1026 var lightUp = sceneCamera.directionWC; // Align shadows to the camera view.1027 var lightRight = Cartesian3.cross(lightDir, lightUp, scratchRight);1028 lightUp = Cartesian3.cross(lightRight, lightDir, scratchUp); // Recalculate up now that right is derived1029 Cartesian3.normalize(lightUp, lightUp);1030 Cartesian3.normalize(lightRight, lightRight);1031 var lightPosition = Cartesian3.fromElements(0.0, 0.0, 0.0, scratchTranslation);1032 var lightView = Matrix4.computeView(lightPosition, lightDir, lightUp, lightRight, scratchLightView);1033 var cameraToLight = Matrix4.multiply(lightView, inverseViewProjection, scratchMatrix);1034 // Project each corner from NDC space to light view space, and calculate a min and max in light view space1035 var min = Cartesian3.fromElements(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, scratchMin);1036 var max = Cartesian3.fromElements(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, scratchMax);1037 for (var i = 0; i < 8; ++i) {1038 var corner = Cartesian4.clone(frustumCornersNDC[i], scratchFrustumCorners[i]);1039 Matrix4.multiplyByVector(cameraToLight, corner, corner);1040 Cartesian3.divideByScalar(corner, corner.w, corner); // Handle the perspective divide1041 Cartesian3.minimumByComponent(corner, min, min);1042 Cartesian3.maximumByComponent(corner, max, max);1043 }1044 // 2. Set bounding box back to include objects in the light's view1045 max.z += 1000.0; // Note: in light space, a positive number is behind the camera1046 min.z -= 10.0; // Extend the shadow volume forward slightly to avoid problems right at the edge1047 // 3. Adjust light view matrix so that it is centered on the bounding volume1048 var translation = scratchTranslation;1049 translation.x = -(0.5 * (min.x + max.x));1050 translation.y = -(0.5 * (min.y + max.y));1051 translation.z = -max.z;1052 var translationMatrix = Matrix4.fromTranslation(translation, scratchMatrix);1053 lightView = Matrix4.multiply(translationMatrix, lightView, lightView);1054 // 4. Create an orthographic frustum that covers the bounding box extents1055 var halfWidth = 0.5 * (max.x - min.x);1056 var halfHeight = 0.5 * (max.y - min.y);1057 var depth = max.z - min.z;1058 var frustum = shadowMapCamera.frustum;1059 frustum.left = -halfWidth;1060 frustum.right = halfWidth;1061 frustum.bottom = -halfHeight;1062 frustum.top = halfHeight;1063 frustum.near = 0.01;1064 frustum.far = depth;1065 // 5. Update the shadow map camera1066 Matrix4.clone(lightView, shadowMapCamera.viewMatrix);1067 Matrix4.inverse(lightView, shadowMapCamera.inverseViewMatrix);1068 Matrix4.getTranslation(shadowMapCamera.inverseViewMatrix, shadowMapCamera.positionWC);1069 frameState.mapProjection.ellipsoid.cartesianToCartographic(shadowMapCamera.positionWC, shadowMapCamera.positionCartographic);1070 Cartesian3.clone(lightDir, shadowMapCamera.directionWC);1071 Cartesian3.clone(lightUp, shadowMapCamera.upWC);1072 Cartesian3.clone(lightRight, shadowMapCamera.rightWC);1073 }1074 var directions = [1075 new Cartesian3(-1.0, 0.0, 0.0),1076 new Cartesian3(0.0, -1.0, 0.0),1077 new Cartesian3(0.0, 0.0, -1.0),1078 new Cartesian3(1.0, 0.0, 0.0),1079 new Cartesian3(0.0, 1.0, 0.0),1080 new Cartesian3(0.0, 0.0, 1.0)1081 ];1082 var ups = [1083 new Cartesian3(0.0, -1.0, 0.0),1084 new Cartesian3(0.0, 0.0, -1.0),1085 new Cartesian3(0.0, -1.0, 0.0),1086 new Cartesian3(0.0, -1.0, 0.0),1087 new Cartesian3(0.0, 0.0, 1.0),1088 new Cartesian3(0.0, -1.0, 0.0)1089 ];1090 var rights = [1091 new Cartesian3(0.0, 0.0, 1.0),1092 new Cartesian3(1.0, 0.0, 0.0),1093 new Cartesian3(-1.0, 0.0, 0.0),1094 new Cartesian3(0.0, 0.0, -1.0),1095 new Cartesian3(1.0, 0.0, 0.0),1096 new Cartesian3(1.0, 0.0, 0.0)1097 ];1098 function computeOmnidirectional(shadowMap, frameState) {1099 // All sides share the same frustum1100 var frustum = new PerspectiveFrustum();1101 frustum.fov = CesiumMath.PI_OVER_TWO;1102 frustum.near = 1.0;1103 frustum.far = shadowMap._pointLightRadius;1104 frustum.aspectRatio = 1.0;1105 for (var i = 0; i < 6; ++i) {1106 var camera = shadowMap._passes[i].camera;1107 camera.positionWC = shadowMap._shadowMapCamera.positionWC;1108 camera.positionCartographic = frameState.mapProjection.ellipsoid.cartesianToCartographic(camera.positionWC, camera.positionCartographic);1109 camera.directionWC = directions[i];1110 camera.upWC = ups[i];1111 camera.rightWC = rights[i];1112 Matrix4.computeView(camera.positionWC, camera.directionWC, camera.upWC, camera.rightWC, camera.viewMatrix);1113 Matrix4.inverse(camera.viewMatrix, camera.inverseViewMatrix);1114 camera.frustum = frustum;1115 }1116 }1117 var scratchCartesian1 = new Cartesian3();1118 var scratchCartesian2 = new Cartesian3();1119 var scratchBoundingSphere = new BoundingSphere();1120 var scratchCenter = scratchBoundingSphere.center;1121 function checkVisibility(shadowMap, frameState) {1122 var sceneCamera = shadowMap._sceneCamera;1123 var shadowMapCamera = shadowMap._shadowMapCamera;1124 var boundingSphere = scratchBoundingSphere;1125 // Check whether the shadow map is in view and needs to be updated1126 if (shadowMap._cascadesEnabled) {1127 // If the nearest shadow receiver is further than the shadow map's maximum distance then the shadow map is out of view.1128 if (sceneCamera.frustum.near >= shadowMap.maximumDistance) {1129 shadowMap._outOfView = true;1130 shadowMap._needsUpdate = false;1131 return;1132 }1133 // If the light source is below the horizon then the shadow map is out of view1134 var surfaceNormal = frameState.mapProjection.ellipsoid.geodeticSurfaceNormal(sceneCamera.positionWC, scratchCartesian1);1135 var lightDirection = Cartesian3.negate(shadowMapCamera.directionWC, scratchCartesian2);1136 var dot = Cartesian3.dot(surfaceNormal, lightDirection);1137 // Shadows start to fade out once the light gets closer to the horizon.1138 // At this point the globe uses vertex lighting alone to darken the surface.1139 var darknessAmount = CesiumMath.clamp(dot / 0.1, 0.0, 1.0);1140 shadowMap._darkness = CesiumMath.lerp(1.0, shadowMap.darkness, darknessAmount);1141 if (dot < 0.0) {1142 shadowMap._outOfView = true;1143 shadowMap._needsUpdate = false;1144 return;1145 }1146 // By default cascaded shadows need to update and are always in view1147 shadowMap._needsUpdate = true;1148 shadowMap._outOfView = false;1149 } else if (shadowMap._isPointLight) {1150 // Sphere-frustum intersection test1151 boundingSphere.center = shadowMapCamera.positionWC;1152 boundingSphere.radius = shadowMap._pointLightRadius;1153 shadowMap._outOfView = frameState.cullingVolume.computeVisibility(boundingSphere) === Intersect.OUTSIDE;1154 shadowMap._needsUpdate = !shadowMap._outOfView && !shadowMap._boundingSphere.equals(boundingSphere);1155 BoundingSphere.clone(boundingSphere, shadowMap._boundingSphere);1156 } else {1157 // Simplify frustum-frustum intersection test as a sphere-frustum test1158 var frustumRadius = shadowMapCamera.frustum.far / 2.0;1159 var frustumCenter = Cartesian3.add(shadowMapCamera.positionWC, Cartesian3.multiplyByScalar(shadowMapCamera.directionWC, frustumRadius, scratchCenter), scratchCenter);1160 boundingSphere.center = frustumCenter;1161 boundingSphere.radius = frustumRadius;1162 shadowMap._outOfView = frameState.cullingVolume.computeVisibility(boundingSphere) === Intersect.OUTSIDE;1163 shadowMap._needsUpdate = !shadowMap._outOfView && !shadowMap._boundingSphere.equals(boundingSphere);1164 BoundingSphere.clone(boundingSphere, shadowMap._boundingSphere);1165 }1166 }1167 function updateCameras(shadowMap, frameState) {1168 var camera = frameState.camera; // The actual camera in the scene1169 var lightCamera = shadowMap._lightCamera; // The external camera representing the light source1170 var sceneCamera = shadowMap._sceneCamera; // Clone of camera, with clamped near and far planes1171 var shadowMapCamera = shadowMap._shadowMapCamera; // Camera representing the shadow volume, initially cloned from lightCamera1172 // Clone light camera into the shadow map camera1173 if (shadowMap._cascadesEnabled) {1174 Cartesian3.clone(lightCamera.directionWC, shadowMapCamera.directionWC);1175 } else if (shadowMap._isPointLight) {1176 Cartesian3.clone(lightCamera.positionWC, shadowMapCamera.positionWC);1177 } else {1178 shadowMapCamera.clone(lightCamera);1179 }1180 // Get the light direction in eye coordinates1181 var lightDirection = shadowMap._lightDirectionEC;1182 Matrix4.multiplyByPointAsVector(camera.viewMatrix, shadowMapCamera.directionWC, lightDirection);1183 Cartesian3.normalize(lightDirection, lightDirection);1184 Cartesian3.negate(lightDirection, lightDirection);1185 // Get the light position in eye coordinates1186 Matrix4.multiplyByPoint(camera.viewMatrix, shadowMapCamera.positionWC, shadowMap._lightPositionEC);1187 shadowMap._lightPositionEC.w = shadowMap._pointLightRadius;1188 // Get the near and far of the scene camera1189 var near;1190 var far;1191 if (shadowMap._fitNearFar) {1192 // shadowFar can be very large, so limit to shadowMap.maximumDistance1193 // Push the far plane slightly further than the near plane to avoid degenerate frustum1194 near = Math.min(frameState.shadowHints.nearPlane, shadowMap.maximumDistance);1195 far = Math.min(frameState.shadowHints.farPlane, shadowMap.maximumDistance + 1.0);1196 } else {1197 near = camera.frustum.near;1198 far = shadowMap.maximumDistance;1199 }1200 shadowMap._sceneCamera = Camera.clone(camera, sceneCamera);1201 camera.frustum.clone(shadowMap._sceneCamera.frustum);1202 shadowMap._sceneCamera.frustum.near = near;1203 shadowMap._sceneCamera.frustum.far = far;1204 shadowMap._distance = far - near;1205 checkVisibility(shadowMap, frameState);1206 if (!shadowMap._outOfViewPrevious && shadowMap._outOfView) {1207 shadowMap._needsUpdate = true;1208 }1209 shadowMap._outOfViewPrevious = shadowMap._outOfView;1210 }1211 /**1212 * @private1213 */1214 ShadowMap.prototype.update = function(frameState) {1215 updateCameras(this, frameState);1216 if (this._needsUpdate) {1217 updateFramebuffer(this, frameState.context);1218 if (this._isPointLight) {1219 computeOmnidirectional(this, frameState);1220 }1221 if (this._cascadesEnabled) {1222 fitShadowMapToScene(this, frameState);1223 if (this._numberOfCascades > 1) {1224 computeCascades(this, frameState);1225 }1226 }1227 if (!this._isPointLight) {1228 // Compute the culling volume1229 var shadowMapCamera = this._shadowMapCamera;1230 var position = shadowMapCamera.positionWC;1231 var direction = shadowMapCamera.directionWC;1232 var up = shadowMapCamera.upWC;1233 this._shadowMapCullingVolume = shadowMapCamera.frustum.computeCullingVolume(position, direction, up);1234 if (this._passes.length === 1) {1235 // Since there is only one pass, use the shadow map camera as the pass camera.1236 this._passes[0].camera.clone(shadowMapCamera);1237 }1238 } else {1239 this._shadowMapCullingVolume = CullingVolume.fromBoundingSphere(this._boundingSphere);1240 }1241 }1242 if (this._passes.length === 1) {1243 // Transforms from eye space to shadow texture space.1244 // Always requires an update since the scene camera constantly changes.1245 var inverseView = this._sceneCamera.inverseViewMatrix;1246 Matrix4.multiply(this._shadowMapCamera.getViewProjection(), inverseView, this._shadowMapMatrix);1247 }1248 if (this.debugShow) {1249 applyDebugSettings(this, frameState);1250 }1251 };1252 /**1253 * @private1254 */1255 ShadowMap.prototype.updatePass = function(context, shadowPass) {1256 clearFramebuffer(this, context, shadowPass);1257 };1258 var scratchTexelStepSize = new Cartesian2();1259 function combineUniforms(shadowMap, uniforms, isTerrain) {1260 var bias = shadowMap._isPointLight ? shadowMap._pointBias : (isTerrain ? shadowMap._terrainBias : shadowMap._primitiveBias);1261 var mapUniforms = {1262 shadowMap_texture :function() {1263 return shadowMap._shadowMapTexture;1264 },1265 shadowMap_textureCube : function() {1266 return shadowMap._shadowMapTexture;1267 },1268 shadowMap_matrix : function() {1269 return shadowMap._shadowMapMatrix;1270 },1271 shadowMap_cascadeSplits : function() {1272 return shadowMap._cascadeSplits;1273 },1274 shadowMap_cascadeMatrices : function() {1275 return shadowMap._cascadeMatrices;1276 },1277 shadowMap_lightDirectionEC : function() {1278 return shadowMap._lightDirectionEC;1279 },1280 shadowMap_lightPositionEC : function() {1281 return shadowMap._lightPositionEC;1282 },1283 shadowMap_cascadeDistances : function() {1284 return shadowMap._cascadeDistances;1285 },1286 shadowMap_texelSizeDepthBiasAndNormalShadingSmooth : function() {1287 var texelStepSize = scratchTexelStepSize;1288 texelStepSize.x = 1.0 / shadowMap._textureSize.x;1289 texelStepSize.y = 1.0 / shadowMap._textureSize.y;1290 return Cartesian4.fromElements(texelStepSize.x, texelStepSize.y, bias.depthBias, bias.normalShadingSmooth, this.combinedUniforms1);1291 },1292 shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness : function() {1293 return Cartesian4.fromElements(bias.normalOffsetScale, shadowMap._distance, shadowMap.maximumDistance, shadowMap._darkness, this.combinedUniforms2);1294 },1295 combinedUniforms1 : new Cartesian4(),1296 combinedUniforms2 : new Cartesian4()1297 };1298 return combine(uniforms, mapUniforms, false);1299 }1300 function createCastDerivedCommand(shadowMap, shadowsDirty, command, context, oldShaderId, result) {1301 var castShader;1302 var castRenderState;1303 var castUniformMap;1304 if (defined(result)) {1305 castShader = result.shaderProgram;1306 castRenderState = result.renderState;1307 castUniformMap = result.uniformMap;1308 }1309 result = DrawCommand.shallowClone(command, result);1310 result.castShadows = true;1311 result.receiveShadows = false;1312 if (!defined(castShader) || oldShaderId !== command.shaderProgram.id || shadowsDirty) {1313 var shaderProgram = command.shaderProgram;1314 var isTerrain = command.pass === Pass.GLOBE;1315 var isOpaque = command.pass !== Pass.TRANSLUCENT;1316 var isPointLight = shadowMap._isPointLight;1317 var usesDepthTexture= shadowMap._usesDepthTexture;1318 var keyword = ShadowMapShader.getShadowCastShaderKeyword(isPointLight, isTerrain, usesDepthTexture, isOpaque);1319 castShader = context.shaderCache.getDerivedShaderProgram(shaderProgram, keyword);1320 if (!defined(castShader)) {1321 var vertexShaderSource = shaderProgram.vertexShaderSource;1322 var fragmentShaderSource = shaderProgram.fragmentShaderSource;1323 var castVS = ShadowMapShader.createShadowCastVertexShader(vertexShaderSource, isPointLight, isTerrain);1324 var castFS = ShadowMapShader.createShadowCastFragmentShader(fragmentShaderSource, isPointLight, usesDepthTexture, isOpaque);1325 castShader = context.shaderCache.createDerivedShaderProgram(shaderProgram, keyword, {1326 vertexShaderSource : castVS,1327 fragmentShaderSource : castFS,1328 attributeLocations : shaderProgram._attributeLocations1329 });1330 }1331 castRenderState = shadowMap._primitiveRenderState;1332 if (isPointLight) {1333 castRenderState = shadowMap._pointRenderState;1334 } else if (isTerrain) {1335 castRenderState = shadowMap._terrainRenderState;1336 }1337 // Modify the render state for commands that do not use back-face culling, e.g. flat textured walls1338 var cullEnabled = command.renderState.cull.enabled;1339 if (!cullEnabled) {1340 castRenderState = clone(castRenderState, false);1341 castRenderState.cull = clone(castRenderState.cull, false);1342 castRenderState.cull.enabled = false;1343 castRenderState = RenderState.fromCache(castRenderState);1344 }1345 castUniformMap = combineUniforms(shadowMap, command.uniformMap, isTerrain);1346 }1347 result.shaderProgram = castShader;1348 result.renderState = castRenderState;1349 result.uniformMap = castUniformMap;1350 return result;1351 }1352 ShadowMap.createDerivedCommands = function(shadowMaps, lightShadowMaps, command, shadowsDirty, context, result) {1353 if (!defined(result)) {1354 result = {};1355 }1356 var lightShadowMapsEnabled = (lightShadowMaps.length > 0);1357 var shaderProgram = command.shaderProgram;1358 var vertexShaderSource = shaderProgram.vertexShaderSource;1359 var fragmentShaderSource = shaderProgram.fragmentShaderSource;1360 var isTerrain = command.pass === Pass.GLOBE;1361 var hasTerrainNormal = false;1362 if (isTerrain) {1363 hasTerrainNormal = command.owner.data.pickTerrain.mesh.encoding.hasVertexNormals;1364 }1365 if (command.castShadows) {1366 var castCommands = result.castCommands;1367 if (!defined(castCommands)) {1368 castCommands = result.castCommands = [];1369 }1370 var oldShaderId = result.castShaderProgramId;1371 var shadowMapLength = shadowMaps.length;1372 castCommands.length = shadowMapLength;1373 for (var i = 0; i < shadowMapLength; ++i) {1374 castCommands[i] = createCastDerivedCommand(shadowMaps[i], shadowsDirty, command, context, oldShaderId, castCommands[i]);1375 }1376 result.castShaderProgramId = command.shaderProgram.id;1377 }1378 if (command.receiveShadows && lightShadowMapsEnabled) {1379 // Only generate a receiveCommand if there is a shadow map originating from a light source.1380 var receiveShader;1381 var receiveUniformMap;1382 if (defined(result.receiveCommand)) {1383 receiveShader = result.receiveCommand.shaderProgram;1384 receiveUniformMap = result.receiveCommand.uniformMap;1385 }1386 result.receiveCommand = DrawCommand.shallowClone(command, result.receiveCommand);1387 result.castShadows = false;1388 result.receiveShadows = true;1389 // If castShadows changed, recompile the receive shadows shader. The normal shading technique simulates1390 // self-shadowing so it should be turned off if castShadows is false.1391 var castShadowsDirty = result.receiveShaderCastShadows !== command.castShadows;1392 var shaderDirty = result.receiveShaderProgramId !== command.shaderProgram.id;1393 if (!defined(receiveShader) || shaderDirty || shadowsDirty || castShadowsDirty) {1394 var keyword = ShadowMapShader.getShadowReceiveShaderKeyword(lightShadowMaps[0], command.castShadows, isTerrain, hasTerrainNormal);1395 receiveShader = context.shaderCache.getDerivedShaderProgram(shaderProgram, keyword);1396 if (!defined(receiveShader)) {1397 var receiveVS = ShadowMapShader.createShadowReceiveVertexShader(vertexShaderSource, isTerrain, hasTerrainNormal);1398 var receiveFS = ShadowMapShader.createShadowReceiveFragmentShader(fragmentShaderSource, lightShadowMaps[0], command.castShadows, isTerrain, hasTerrainNormal);1399 receiveShader = context.shaderCache.createDerivedShaderProgram(shaderProgram, keyword, {1400 vertexShaderSource : receiveVS,1401 fragmentShaderSource : receiveFS,1402 attributeLocations : shaderProgram._attributeLocations1403 });1404 }1405 receiveUniformMap = combineUniforms(lightShadowMaps[0], command.uniformMap, isTerrain);1406 }1407 result.receiveCommand.shaderProgram = receiveShader;1408 result.receiveCommand.uniformMap = receiveUniformMap;1409 result.receiveShaderProgramId = command.shaderProgram.id;1410 result.receiveShaderCastShadows = command.castShadows;1411 }1412 return result;1413 };1414 /**1415 * @private1416 */1417 ShadowMap.prototype.isDestroyed = function() {1418 return false;1419 };1420 /**1421 * @private1422 */1423 ShadowMap.prototype.destroy = function() {1424 destroyFramebuffer(this);1425 this._debugLightFrustum = this._debugLightFrustum && this._debugLightFrustum.destroy();1426 this._debugCameraFrustum = this._debugCameraFrustum && this._debugCameraFrustum.destroy();1427 this._debugShadowViewCommand = this._debugShadowViewCommand && this._debugShadowViewCommand.shaderProgram && this._debugShadowViewCommand.shaderProgram.destroy();1428 for (var i = 0; i < this._numberOfCascades; ++i) {1429 this._debugCascadeFrustums[i] = this._debugCascadeFrustums[i] && this._debugCascadeFrustums[i].destroy();1430 }1431 return destroyObject(this);1432 };1433 return ShadowMap;...

Full Screen

Full Screen

test-shadow-embed.js

Source:test-shadow-embed.js Github

copy

Full Screen

1/**2 * Copyright 2016 The AMP HTML Authors. All Rights Reserved.3 *4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 *8 * http://www.apache.org/licenses/LICENSE-2.09 *10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS-IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */16import {AmpDocShadow} from '../../src/service/ampdoc-impl';17import {18 ShadowDomVersion,19 setShadowCssSupportedForTesting,20 setShadowDomSupportedVersionForTesting,21} from '../../src/web-components';22import {23 ShadowDomWriterBulk,24 ShadowDomWriterStreamer,25 createShadowDomWriter,26 createShadowRoot,27 getShadowRootNode,28 importShadowBody,29 isShadowRoot,30 scopeShadowCss,31 setShadowDomStreamingSupportedForTesting,32} from '../../src/shadow-embed';33import {installStylesForDoc} from '../../src/style-installer';34import {toArray} from '../../src/types';35describes.sandboxed('shadow-embed', {}, () => {36 afterEach(() => {37 setShadowDomSupportedVersionForTesting(undefined);38 });39 [ShadowDomVersion.NONE, ShadowDomVersion.V0, ShadowDomVersion.V1]40 .forEach(scenario => {41 describe('shadow APIs', () => {42 let hostElement;43 beforeEach(function() {44 hostElement = document.createElement('div');45 setShadowDomSupportedVersionForTesting(scenario);46 setShadowCssSupportedForTesting(undefined);47 });48 describe(scenario, function() {49 before(function() {50 if (scenario == ShadowDomVersion.V0 &&51 !Element.prototype.createShadowRoot) {52 this.skipTest();53 }54 if (scenario == ShadowDomVersion.V1 &&55 !Element.prototype.attachShadow) {56 this.skipTest();57 }58 });59 it('should transform CSS installStylesForDoc ' +60 'for shadow root', () => {61 const shadowRoot = createShadowRoot(hostElement);62 const ampdoc = new AmpDocShadow(63 window, 'https://a.org/', shadowRoot);64 const style = installStylesForDoc(ampdoc, 'body {}', null, true);65 expect(shadowRoot.contains(style)).to.be.true;66 const css = style.textContent.replace(/\s/g, '');67 if (scenario == ShadowDomVersion.NONE) {68 expect(css).to.match(/amp-body/);69 } else {70 expect(css).to.equal('body{}');71 }72 });73 describe('createShadowRoot', () => {74 it('should clear duplicate root', () => {75 const shadowRoot1 = createShadowRoot(hostElement);76 const span = document.createElement('span');77 shadowRoot1.appendChild(span);78 expect(shadowRoot1.contains(span)).to.be.true;79 const shadowRoot2 = createShadowRoot(hostElement);80 expect(shadowRoot2).to.equal(shadowRoot1);81 expect(shadowRoot2.contains(span)).to.be.false;82 });83 it('should have host', () => {84 const shadowRoot = createShadowRoot(hostElement);85 expect(shadowRoot.host).to.equal(hostElement);86 });87 it('should have getElementById', () => {88 const shadowRoot = createShadowRoot(hostElement);89 expect(shadowRoot.getElementById).to.be.ok;90 const spanId = 'test' + Math.floor(Math.random() * 10000);91 const span = document.createElement('span');92 span.id = spanId;93 shadowRoot.appendChild(span);94 expect(shadowRoot.getElementById(spanId)).to.equal(span);95 });96 if (scenario == ShadowDomVersion.NONE) {97 it('should add id for polyfill', () => {98 const shadowRoot = createShadowRoot(hostElement);99 expect(shadowRoot.tagName).to.equal('I-AMPHTML-SHADOW-ROOT');100 expect(shadowRoot.id).to.match(/i-amphtml-sd-\d+/);101 });102 it('should add host style for polyfill', () => {103 const doc = hostElement.ownerDocument;104 doc.body.appendChild(hostElement);105 const slot = doc.createElement('div');106 hostElement.appendChild(slot);107 expect(slot).to.have.display('block');108 const shadowRoot = createShadowRoot(hostElement);109 expect(hostElement).to.have.class(110 'i-amphtml-shadow-host-polyfill');111 expect(slot).to.have.display('none');112 expect(shadowRoot).to.not.have.display('none');113 doc.body.removeChild(hostElement);114 });115 }116 // Test scenarios where Shadow Css is not supported117 it('Should add an id and class for CSS \118 encapsulation to the shadow root', () => {119 setShadowCssSupportedForTesting(false);120 const shadowRoot = createShadowRoot(hostElement);121 expect(shadowRoot.id).to.match(/i-amphtml-sd-\d+/);122 // Browserify does not support arrow functions with params.123 // Using Old School for124 const shadowRootClassListArray =125 toArray(shadowRoot.host.classList);126 let foundShadowCssClass = false;127 for (let i = 0; i < shadowRootClassListArray.length; i++) {128 if (shadowRootClassListArray[i].match(/i-amphtml-sd-\d+/)) {129 foundShadowCssClass = true;130 break;131 }132 }133 expect(foundShadowCssClass).to.be.ok;134 });135 it('Should transform CSS for the shadow root', () => {136 setShadowCssSupportedForTesting(false);137 const shadowRoot = createShadowRoot(hostElement);138 const ampdoc = new AmpDocShadow(139 window, 'https://a.org/', shadowRoot);140 const style =141 installStylesForDoc(ampdoc, 'body {}', null, true);142 expect(shadowRoot.contains(style)).to.be.true;143 const css = style.textContent.replace(/\s/g, '');144 expect(css).to.match(/amp-body/);145 });146 });147 describe('stylesheets', () => {148 let parentStylesheet;149 beforeEach(() => {150 parentStylesheet = document.createElement('style');151 parentStylesheet.textContent = '.x {background: red}';152 document.body.appendChild(parentStylesheet);153 document.body.appendChild(hostElement);154 });155 afterEach(() => {156 document.body.removeChild(parentStylesheet);157 document.body.removeChild(hostElement);158 });159 it('should have shadow stylesheets and not global', () => {160 const shadowRoot = createShadowRoot(hostElement);161 const shadowStyle = document.createElement('style');162 shadowStyle.textContent = '.x {background: green}';163 shadowRoot.appendChild(shadowStyle);164 const {styleSheets} = shadowRoot;165 expect(styleSheets).to.exist;166 expect(styleSheets).to.have.length(1);167 expect(styleSheets[0].ownerNode).to.equal(shadowStyle);168 });169 });170 // TODO(aghassemi, #12499): Make this work with latest mocha / karma171 describe.skip('importShadowBody', () => {172 let shadowRoot, source, child1, child2;173 beforeEach(() => {174 shadowRoot = createShadowRoot(hostElement);175 source = document.createElement('body');176 child1 = document.createElement('div');177 child1.id = 'child1';178 child2 = document.createElement('div');179 child2.id = 'child2';180 source.appendChild(child1);181 source.appendChild(child2);182 });183 it('should import body with all children', () => {184 expect(shadowRoot.body).to.be.undefined;185 const body = importShadowBody(shadowRoot, source, true);186 expect(shadowRoot.body).to.equal(body);187 expect(body.tagName).to.equal(188 scenario == ShadowDomVersion.NONE ? 'AMP-BODY' : 'BODY');189 expect(body.style.position).to.equal('relative');190 if (scenario == ShadowDomVersion.NONE) {191 expect(body.style.display).to.equal('block');192 }193 expect(shadowRoot.contains(body)).to.be.true;194 expect(body.children).to.have.length(2);195 expect(body.children[0].id).to.equal('child1');196 expect(body.children[1].id).to.equal('child2');197 });198 it('should import shallow body', () => {199 expect(shadowRoot.body).to.be.undefined;200 const body = importShadowBody(shadowRoot, source, false);201 expect(shadowRoot.body).to.equal(body);202 expect(body.tagName).to.equal(203 scenario == ShadowDomVersion.NONE ? 'AMP-BODY' : 'BODY');204 expect(body.style.position).to.equal('relative');205 if (scenario == ShadowDomVersion.NONE) {206 expect(body.style.display).to.equal('block');207 }208 expect(shadowRoot.contains(body)).to.be.true;209 expect(body.children).to.have.length(0);210 });211 });212 });213 });214 });215 describe('isShadowRoot', () => {216 it('should yield false for non-nodes', () => {217 expect(isShadowRoot(null)).to.be.false;218 expect(isShadowRoot(undefined)).to.be.false;219 expect(isShadowRoot('')).to.be.false;220 expect(isShadowRoot(11)).to.be.false;221 });222 it('should yield false for other types of nodes', () => {223 expect(isShadowRoot(document.createElement('div'))).to.be.false;224 expect(isShadowRoot(document.createTextNode('abc'))).to.be.false;225 });226 it('should yield true for natively-supported createShadowRoot API', () => {227 const element = document.createElement('div');228 if (element.createShadowRoot) {229 const shadowRoot = element.createShadowRoot();230 expect(isShadowRoot(shadowRoot)).to.be.true;231 }232 });233 it('should yield true for natively-supported attachShadow API', () => {234 const element = document.createElement('div');235 if (element.attachShadow) {236 const shadowRoot = element.attachShadow({mode: 'open'});237 expect(isShadowRoot(shadowRoot)).to.be.true;238 }239 });240 it('should yield false for document-fragment non-shadow-root node', () => {241 const fragment = document.createDocumentFragment();242 expect(isShadowRoot(fragment)).to.be.false;243 });244 it('should yield true for polyfill', () => {245 expect(isShadowRoot(document.createElement(246 'i-amphtml-shadow-root'))).to.be.true;247 });248 });249 describe('getShadowRootNode', () => {250 let content, host, shadowRoot;251 beforeEach(() => {252 host = document.createElement('div');253 shadowRoot = createShadowRoot(host);254 content = document.createElement('span');255 shadowRoot.appendChild(content);256 });257 it('should find itself as the root node', () => {258 expect(getShadowRootNode(shadowRoot)).to.equal(shadowRoot);259 });260 it('should find the root node from ancestors', () => {261 expect(getShadowRootNode(content)).to.equal(shadowRoot);262 });263 it('should find the root node via polyfill', () => {264 setShadowDomSupportedVersionForTesting(ShadowDomVersion.NONE);265 expect(getShadowRootNode(content)).to.equal(shadowRoot);266 });267 });268 describe('scopeShadowCss', () => {269 let shadowRoot;270 beforeEach(() => {271 shadowRoot = document.createElement('div');272 shadowRoot.id = 'h';273 });274 function scope(css) {275 return scopeShadowCss(shadowRoot, css).replace(/[\n\t\n]/g, '');276 }277 it('should replace root selectors', () => {278 expect(scope('html {}')).to.equal('.h amp-html {}');279 expect(scope('body {}')).to.equal('.h amp-body {}');280 expect(scope('html {} body {}')).to.equal(281 '.h amp-html {}.h amp-body {}');282 expect(scope('html, body {}')).to.equal('.h amp-html, .h amp-body {}');283 expect(scope('body.x {}')).to.equal('.h amp-body.x {}');284 expect(scope('body::after {}')).to.equal('.h amp-body::after {}');285 expect(scope('body[x] {}')).to.equal('.h amp-body[x] {}');286 });287 it('should avoid false positives for root selectors', () => {288 expect(scope('.body {}')).to.equal('.h .body {}');289 expect(scope('x-body {}')).to.equal('.h x-body {}');290 expect(scope('body-x {}')).to.equal('.h body-x {}');291 expect(scope('body_x {}')).to.equal('.h body_x {}');292 expect(scope('body1 {}')).to.equal('.h body1 {}');293 });294 });295 describe('createShadowDomWriter', () => {296 let createHTMLDocumentSpy;297 let win;298 let isFirefox;299 beforeEach(() => {300 setShadowDomStreamingSupportedForTesting(undefined);301 createHTMLDocumentSpy = sandbox.spy();302 isFirefox = false;303 const platform = {304 isFirefox: () => isFirefox,305 };306 win = {307 navigator: {308 userAgent: '',309 },310 document: {311 implementation: {312 createHTMLDocument: type => {313 createHTMLDocumentSpy(type);314 return {315 open: () => {},316 };317 },318 },319 },320 services: {321 'platform': {obj: platform},322 'vsync': {obj: {}},323 },324 };325 });326 it('should resolve to streamer', () => {327 expect(createShadowDomWriter(win))328 .to.be.instanceOf(ShadowDomWriterStreamer);329 expect(createHTMLDocumentSpy).to.be.calledOnce;330 expect(createHTMLDocumentSpy).to.be.calledWith('');331 });332 it('should resolve to bulk without API', () => {333 delete win.document.implementation.createHTMLDocument;334 expect(createShadowDomWriter(win))335 .to.be.instanceOf(ShadowDomWriterBulk);336 delete win.document.implementation;337 expect(createShadowDomWriter(win))338 .to.be.instanceOf(ShadowDomWriterBulk);339 expect(createHTMLDocumentSpy).to.not.be.called;340 });341 it('should resolve to bulk on firefox', () => {342 isFirefox = true;343 expect(createShadowDomWriter(win))344 .to.be.instanceOf(ShadowDomWriterBulk);345 expect(createHTMLDocumentSpy).to.not.be.called;346 });347 });348 describes.fakeWin('ShadowDomWriterStreamer', {amp: true}, env => {349 let win;350 let writer;351 let onBodySpy, onBodyChunkSpy;352 let onBodyPromise, onBodyChunkPromiseResolver, onEndPromise;353 beforeEach(() => {354 win = env.win;355 writer = new ShadowDomWriterStreamer(win);356 onBodySpy = sandbox.spy();357 onBodyChunkSpy = sandbox.spy();358 onBodyPromise = new Promise(resolve => {359 writer.onBody(parsedDoc => {360 resolve(parsedDoc.body);361 onBodySpy();362 return win.document.body;363 });364 });365 writer.onBodyChunk(() => {366 if (onBodyChunkPromiseResolver) {367 onBodyChunkPromiseResolver();368 onBodyChunkPromiseResolver = null;369 }370 onBodyChunkSpy();371 });372 onEndPromise = new Promise(resolve => {373 writer.onEnd(resolve);374 });375 });376 function waitForNextBodyChunk() {377 return new Promise(resolve => {378 onBodyChunkPromiseResolver = resolve;379 });380 }381 it('should complete when writer has been closed', () => {382 writer.close();383 return onEndPromise.then(() => {384 expect(onBodySpy).to.be.calledOnce;385 env.flushVsync();386 expect(onBodyChunkSpy).to.not.be.called;387 });388 });389 it('should resolve body as soon as available', () => {390 writer.write('<body class="b">');391 expect(onBodySpy).to.not.be.called;392 return onBodyPromise.then(body => {393 expect(body.getAttribute('class')).to.equal('b');394 expect(onBodySpy).to.be.calledOnce;395 });396 });397 it('should schedule body chunk', () => {398 writer.write('<body>');399 return onBodyPromise.then(() => {400 expect(onBodySpy).to.be.calledOnce;401 writer.write('<child>');402 expect(onBodyChunkSpy).to.not.be.called;403 return waitForNextBodyChunk().then(() => {404 env.flushVsync();405 expect(onBodySpy).to.be.calledOnce;406 expect(onBodyChunkSpy).to.be.calledOnce;407 expect(win.document.body.querySelector('child')).to.exist;408 writer.write('</child><child2>');409 return waitForNextBodyChunk().then(() => {410 env.flushVsync();411 expect(win.document.body.querySelector('child2')).to.exist;412 });413 });414 });415 });416 it('should schedule several body chunks together', () => {417 writer.write('<body>');418 return onBodyPromise.then(() => {419 expect(onBodySpy).to.be.calledOnce;420 writer.write('<child></child>');421 expect(onBodyChunkSpy).to.not.be.called;422 const promise = waitForNextBodyChunk();423 writer.write('<child2></child2>');424 return promise.then(() => {425 expect(onBodyChunkSpy).to.be.calledOnce;426 expect(win.document.body.querySelector('child')).to.exist;427 expect(win.document.body.querySelector('child2')).to.exist;428 });429 });430 });431 it('should not parse noscript as markup', () => {432 writer.write('<body><child1></child1><noscript><child2></child2>' +433 '</noscript>');434 return waitForNextBodyChunk().then(() => {435 expect(win.document.body.querySelector('child1')).to.exist;436 expect(win.document.body.querySelector('child2')).not.to.exist;437 writer.write('<noscript><child3></child3></noscript>');438 writer.write('<child4></child4>');439 writer.close();440 env.flushVsync();441 return onEndPromise.then(() => {442 expect(win.document.body.querySelector('child3')).not.to.exist;443 expect(win.document.body.querySelector('child4')).to.exist;444 });445 });446 });447 it('should not parse noscript as markup across writes', () => {448 writer.write('<body><child1></child1><noscript><child2>');449 return waitForNextBodyChunk().then(() => {450 expect(win.document.body.querySelector('child1')).to.exist;451 writer.write('</child2></noscript>');452 writer.write('<child3></child3>');453 writer.close();454 env.flushVsync();455 return onEndPromise.then(() => {456 expect(win.document.body.querySelector('child1')).to.exist;457 expect(win.document.body.querySelector('child2')).not.to.exist;458 expect(win.document.body.querySelector('child3')).to.exist;459 });460 });461 });462 });463 describes.fakeWin('ShadowDomWriterBulk', {amp: true}, env => {464 let win;465 let writer;466 let onBodySpy, onBodyChunkSpy;467 let onBodyPromise, onBodyChunkPromiseResolver, onEndPromise;468 beforeEach(() => {469 win = env.win;470 writer = new ShadowDomWriterBulk(win);471 onBodySpy = sandbox.spy();472 onBodyChunkSpy = sandbox.spy();473 onBodyPromise = new Promise(resolve => {474 writer.onBody(parsedDoc => {475 resolve(parsedDoc.body);476 onBodySpy(parsedDoc);477 return win.document.body;478 });479 });480 writer.onBodyChunk(() => {481 if (onBodyChunkPromiseResolver) {482 onBodyChunkPromiseResolver();483 onBodyChunkPromiseResolver = null;484 }485 onBodyChunkSpy();486 });487 onEndPromise = new Promise(resolve => {488 writer.onEnd(resolve);489 });490 });491 it('should complete when writer has been closed', () => {492 writer.close();493 return onEndPromise.then(() => {494 expect(onBodySpy).to.be.calledOnce;495 env.flushVsync();496 expect(onBodyChunkSpy).to.not.be.called;497 });498 });499 it('should wait for body until stream is closed', () => {500 writer.write('<body class="b">');501 env.flushVsync();502 expect(onBodySpy).to.not.be.called;503 expect(writer.eof_).to.be.false;504 writer.write('abc');505 env.flushVsync();506 expect(onBodySpy).to.not.be.called;507 expect(writer.eof_).to.be.false;508 writer.close();509 env.flushVsync();510 expect(onBodySpy).to.be.calledOnce;511 expect(win.document.body.textContent).to.equal('abc');512 expect(writer.eof_).to.be.true;513 return Promise.all([onBodyPromise, onEndPromise]);514 });515 it('should process for body chunks together', () => {516 writer.write('<body class="b">');517 env.flushVsync();518 expect(onBodySpy).to.not.be.called;519 writer.write('<child></child>');520 env.flushVsync();521 expect(onBodySpy).to.not.be.called;522 writer.write('<child2></child2>');523 env.flushVsync();524 expect(onBodySpy).to.not.be.called;525 writer.close();526 env.flushVsync();527 expect(onBodySpy).to.be.calledOnce;528 expect(win.document.body.querySelector('child')).to.exist;529 expect(win.document.body.querySelector('child2')).to.exist;530 expect(writer.eof_).to.be.true;531 return Promise.all([onBodyPromise, onEndPromise]);532 });533 it('should not parse noscript as markup', () => {534 writer.write('<body>');535 writer.write('<child1></child1><noscript><child2></child2></noscript>');536 writer.write('<child3></child3>');537 writer.close();538 env.flushVsync();539 expect(win.document.body.querySelector('child1')).to.exist;540 expect(win.document.body.querySelector('child2')).not.to.exist;541 expect(win.document.body.querySelector('child3')).to.exist;542 return Promise.all([onBodyPromise, onEndPromise]);543 });544 });...

Full Screen

Full Screen

ShadowMapShader.js

Source:ShadowMapShader.js Github

copy

Full Screen

1define([2 '../Core/defined',3 '../Renderer/ShaderSource'4 ], function(5 defined,6 ShaderSource) {7 'use strict';8 /**9 * @private10 */11 function ShadowMapShader() {12 }13 ShadowMapShader.getShadowCastShaderKeyword = function(isPointLight, isTerrain, usesDepthTexture, isOpaque) {14 return 'castShadow ' + isPointLight + ' ' + isTerrain + ' ' + usesDepthTexture + ' ' + isOpaque;15 };16 ShadowMapShader.createShadowCastVertexShader = function(vs, isPointLight, isTerrain) {17 var defines = vs.defines.slice(0);18 var sources = vs.sources.slice(0);19 vs.defines.push('SHADOW_MAP');20 if (isTerrain) {21 defines.push('GENERATE_POSITION');22 }23 var positionVaryingName = ShaderSource.findPositionVarying(vs);24 var hasPositionVarying = defined(positionVaryingName);25 if (isPointLight && !hasPositionVarying) {26 var length = sources.length;27 for (var j = 0; j < length; ++j) {28 sources[j] = ShaderSource.replaceMain(sources[j], 'czm_shadow_cast_main');29 }30 var shadowVS =31 'varying vec3 v_positionEC; \n' +32 'void main() \n' +33 '{ \n' +34 ' czm_shadow_cast_main(); \n' +35 ' v_positionEC = (czm_inverseProjection * gl_Position).xyz; \n' +36 '}';37 sources.push(shadowVS);38 }39 return new ShaderSource({40 defines : defines,41 sources : sources42 });43 };44 ShadowMapShader.createShadowCastFragmentShader = function(fs, isPointLight, usesDepthTexture, opaque) {45 var defines = fs.defines.slice(0);46 var sources = fs.sources.slice(0);47 var positionVaryingName = ShaderSource.findPositionVarying(fs);48 var hasPositionVarying = defined(positionVaryingName);49 if (!hasPositionVarying) {50 positionVaryingName = 'v_positionEC';51 }52 var length = sources.length;53 for (var i = 0; i < length; ++i) {54 sources[i] = ShaderSource.replaceMain(sources[i], 'czm_shadow_cast_main');55 }56 var fsSource = '';57 if (isPointLight) {58 if (!hasPositionVarying) {59 fsSource += 'varying vec3 v_positionEC; \n';60 }61 fsSource += 'uniform vec4 shadowMap_lightPositionEC; \n';62 }63 if (opaque) {64 fsSource +=65 'void main() \n' +66 '{ \n';67 } else {68 fsSource +=69 'void main() \n' +70 '{ \n' +71 ' czm_shadow_cast_main(); \n' +72 ' if (gl_FragColor.a == 0.0) \n' +73 ' { \n' +74 ' discard; \n' +75 ' } \n';76 }77 if (isPointLight) {78 fsSource +=79 ' float distance = length(' + positionVaryingName + '); \n' +80 ' if (distance >= shadowMap_lightPositionEC.w) \n' +81 ' { \n' +82 ' discard; \n' +83 ' } \n' +84 ' distance /= shadowMap_lightPositionEC.w; // radius \n' +85 ' gl_FragColor = czm_packDepth(distance); \n';86 } else if (usesDepthTexture) {87 fsSource += ' gl_FragColor = vec4(1.0); \n';88 } else {89 fsSource += ' gl_FragColor = czm_packDepth(gl_FragCoord.z); \n';90 }91 fsSource += '} \n';92 sources.push(fsSource);93 return new ShaderSource({94 defines : defines,95 sources : sources96 });97 };98 ShadowMapShader.getShadowReceiveShaderKeyword = function(shadowMap, castShadows, isTerrain, hasTerrainNormal) {99 var usesDepthTexture = shadowMap._usesDepthTexture;100 var polygonOffsetSupported = shadowMap._polygonOffsetSupported;101 var isPointLight = shadowMap._isPointLight;102 var isSpotLight = shadowMap._isSpotLight;103 var hasCascades = shadowMap._numberOfCascades > 1;104 var debugCascadeColors = shadowMap.debugCascadeColors;105 var softShadows = shadowMap.softShadows;106 return 'receiveShadow ' + usesDepthTexture + polygonOffsetSupported + isPointLight + isSpotLight +107 hasCascades + debugCascadeColors + softShadows + castShadows + isTerrain + hasTerrainNormal;108 };109 ShadowMapShader.createShadowReceiveVertexShader = function(vs, isTerrain, hasTerrainNormal) {110 var defines = vs.defines.slice(0);111 var sources = vs.sources.slice(0);112 vs.defines.push('SHADOW_MAP');113 if (isTerrain) {114 if (hasTerrainNormal) {115 defines.push('GENERATE_POSITION_AND_NORMAL');116 } else {117 defines.push('GENERATE_POSITION');118 }119 }120 return new ShaderSource({121 defines : defines,122 sources : sources123 });124 };125 ShadowMapShader.createShadowReceiveFragmentShader = function(fs, shadowMap, castShadows, isTerrain, hasTerrainNormal) {126 var normalVaryingName = ShaderSource.findNormalVarying(fs);127 var hasNormalVarying = (!isTerrain && defined(normalVaryingName)) || (isTerrain && hasTerrainNormal);128 var positionVaryingName = ShaderSource.findPositionVarying(fs);129 var hasPositionVarying = defined(positionVaryingName);130 var usesDepthTexture = shadowMap._usesDepthTexture;131 var polygonOffsetSupported = shadowMap._polygonOffsetSupported;132 var isPointLight = shadowMap._isPointLight;133 var isSpotLight = shadowMap._isSpotLight;134 var hasCascades = shadowMap._numberOfCascades > 1;135 var debugCascadeColors = shadowMap.debugCascadeColors;136 var softShadows = shadowMap.softShadows;137 var bias = isPointLight ? shadowMap._pointBias : (isTerrain ? shadowMap._terrainBias : shadowMap._primitiveBias);138 var defines = fs.defines.slice(0);139 var sources = fs.sources.slice(0);140 var length = sources.length;141 for (var i = 0; i < length; ++i) {142 sources[i] = ShaderSource.replaceMain(sources[i], 'czm_shadow_receive_main');143 }144 if (isPointLight) {145 defines.push('USE_CUBE_MAP_SHADOW');146 } else if (usesDepthTexture) {147 defines.push('USE_SHADOW_DEPTH_TEXTURE');148 }149 if (softShadows && !isPointLight) {150 defines.push('USE_SOFT_SHADOWS');151 }152 // Enable day-night shading so that the globe is dark when the light is below the horizon153 if (hasCascades && castShadows && isTerrain) {154 if (hasNormalVarying) {155 defines.push('ENABLE_VERTEX_LIGHTING');156 } else {157 defines.push('ENABLE_DAYNIGHT_SHADING');158 }159 }160 if (castShadows && bias.normalShading && hasNormalVarying) {161 defines.push('USE_NORMAL_SHADING');162 if (bias.normalShadingSmooth > 0.0) {163 defines.push('USE_NORMAL_SHADING_SMOOTH');164 }165 }166 var fsSource = '';167 if (isPointLight) {168 fsSource += 'uniform samplerCube shadowMap_textureCube; \n';169 } else {170 fsSource += 'uniform sampler2D shadowMap_texture; \n';171 }172 var returnPositionEC;173 if (hasPositionVarying) {174 returnPositionEC = ' return vec4(' + positionVaryingName + ', 1.0); \n';175 } else {176 returnPositionEC =177 '#ifndef LOG_DEPTH \n' +178 ' return czm_windowToEyeCoordinates(gl_FragCoord); \n' +179 '#else \n' +180 ' return vec4(v_logPositionEC, 1.0); \n' +181 '#endif \n';182 }183 fsSource +=184 'uniform mat4 shadowMap_matrix; \n' +185 'uniform vec3 shadowMap_lightDirectionEC; \n' +186 'uniform vec4 shadowMap_lightPositionEC; \n' +187 'uniform vec4 shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness; \n' +188 'uniform vec4 shadowMap_texelSizeDepthBiasAndNormalShadingSmooth; \n' +189 '#ifdef LOG_DEPTH \n' +190 'varying vec3 v_logPositionEC; \n' +191 '#endif \n' +192 'vec4 getPositionEC() \n' +193 '{ \n' +194 returnPositionEC +195 '} \n' +196 'vec3 getNormalEC() \n' +197 '{ \n' +198 (hasNormalVarying ?199 ' return normalize(' + normalVaryingName + '); \n' :200 ' return vec3(1.0); \n') +201 '} \n' +202 // Offset the shadow position in the direction of the normal for perpendicular and back faces203 'void applyNormalOffset(inout vec4 positionEC, vec3 normalEC, float nDotL) \n' +204 '{ \n' +205 (bias.normalOffset && hasNormalVarying ?206 ' float normalOffset = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.x; \n' +207 ' float normalOffsetScale = 1.0 - nDotL; \n' +208 ' vec3 offset = normalOffset * normalOffsetScale * normalEC; \n' +209 ' positionEC.xyz += offset; \n' : '') +210 '} \n';211 fsSource +=212 'void main() \n' +213 '{ \n' +214 ' czm_shadow_receive_main(); \n' +215 ' vec4 positionEC = getPositionEC(); \n' +216 ' vec3 normalEC = getNormalEC(); \n' +217 ' float depth = -positionEC.z; \n';218 fsSource +=219 ' czm_shadowParameters shadowParameters; \n' +220 ' shadowParameters.texelStepSize = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.xy; \n' +221 ' shadowParameters.depthBias = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.z; \n' +222 ' shadowParameters.normalShadingSmooth = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.w; \n' +223 ' shadowParameters.darkness = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.w; \n';224 if (isTerrain) {225 // Scale depth bias based on view distance to reduce z-fighting in distant terrain226 fsSource += ' shadowParameters.depthBias *= max(depth * 0.01, 1.0); \n';227 } else if (!polygonOffsetSupported) {228 // If polygon offset isn't supported push the depth back based on view, however this229 // causes light leaking at further away views230 fsSource += ' shadowParameters.depthBias *= mix(1.0, 100.0, depth * 0.0015); \n';231 }232 if (isPointLight) {233 fsSource +=234 ' vec3 directionEC = positionEC.xyz - shadowMap_lightPositionEC.xyz; \n' +235 ' float distance = length(directionEC); \n' +236 ' directionEC = normalize(directionEC); \n' +237 ' float radius = shadowMap_lightPositionEC.w; \n' +238 ' // Stop early if the fragment is beyond the point light radius \n' +239 ' if (distance > radius) \n' +240 ' { \n' +241 ' return; \n' +242 ' } \n' +243 ' vec3 directionWC = czm_inverseViewRotation * directionEC; \n' +244 ' shadowParameters.depth = distance / radius; \n' +245 ' shadowParameters.nDotL = clamp(dot(normalEC, -directionEC), 0.0, 1.0); \n' +246 ' shadowParameters.texCoords = directionWC; \n' +247 ' float visibility = czm_shadowVisibility(shadowMap_textureCube, shadowParameters); \n';248 } else if (isSpotLight) {249 fsSource +=250 ' vec3 directionEC = normalize(positionEC.xyz - shadowMap_lightPositionEC.xyz); \n' +251 ' float nDotL = clamp(dot(normalEC, -directionEC), 0.0, 1.0); \n' +252 ' applyNormalOffset(positionEC, normalEC, nDotL); \n' +253 ' vec4 shadowPosition = shadowMap_matrix * positionEC; \n' +254 ' // Spot light uses a perspective projection, so perform the perspective divide \n' +255 ' shadowPosition /= shadowPosition.w; \n' +256 ' // Stop early if the fragment is not in the shadow bounds \n' +257 ' if (any(lessThan(shadowPosition.xyz, vec3(0.0))) || any(greaterThan(shadowPosition.xyz, vec3(1.0)))) \n' +258 ' { \n' +259 ' return; \n' +260 ' } \n' +261 ' shadowParameters.texCoords = shadowPosition.xy; \n' +262 ' shadowParameters.depth = shadowPosition.z; \n' +263 ' shadowParameters.nDotL = nDotL; \n' +264 ' float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n';265 } else if (hasCascades) {266 fsSource +=267 ' float maxDepth = shadowMap_cascadeSplits[1].w; \n' +268 ' // Stop early if the eye depth exceeds the last cascade \n' +269 ' if (depth > maxDepth) \n' +270 ' { \n' +271 ' return; \n' +272 ' } \n' +273 ' // Get the cascade based on the eye-space depth \n' +274 ' vec4 weights = czm_cascadeWeights(depth); \n' +275 ' // Apply normal offset \n' +276 ' float nDotL = clamp(dot(normalEC, shadowMap_lightDirectionEC), 0.0, 1.0); \n' +277 ' applyNormalOffset(positionEC, normalEC, nDotL); \n' +278 ' // Transform position into the cascade \n' +279 ' vec4 shadowPosition = czm_cascadeMatrix(weights) * positionEC; \n' +280 ' // Get visibility \n' +281 ' shadowParameters.texCoords = shadowPosition.xy; \n' +282 ' shadowParameters.depth = shadowPosition.z; \n' +283 ' shadowParameters.nDotL = nDotL; \n' +284 ' float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n' +285 ' // Fade out shadows that are far away \n' +286 ' float shadowMapMaximumDistance = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.z; \n' +287 ' float fade = max((depth - shadowMapMaximumDistance * 0.8) / (shadowMapMaximumDistance * 0.2), 0.0); \n' +288 ' visibility = mix(visibility, 1.0, fade); \n' +289 (debugCascadeColors ?290 ' // Draw cascade colors for debugging \n' +291 ' gl_FragColor *= czm_cascadeColor(weights); \n' : '');292 } else {293 fsSource +=294 ' float nDotL = clamp(dot(normalEC, shadowMap_lightDirectionEC), 0.0, 1.0); \n' +295 ' applyNormalOffset(positionEC, normalEC, nDotL); \n' +296 ' vec4 shadowPosition = shadowMap_matrix * positionEC; \n' +297 ' // Stop early if the fragment is not in the shadow bounds \n' +298 ' if (any(lessThan(shadowPosition.xyz, vec3(0.0))) || any(greaterThan(shadowPosition.xyz, vec3(1.0)))) \n' +299 ' { \n' +300 ' return; \n' +301 ' } \n' +302 ' shadowParameters.texCoords = shadowPosition.xy; \n' +303 ' shadowParameters.depth = shadowPosition.z; \n' +304 ' shadowParameters.nDotL = nDotL; \n' +305 ' float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n';306 }307 fsSource +=308 ' gl_FragColor.rgb *= visibility; \n' +309 '} \n';310 sources.push(fsSource);311 return new ShaderSource({312 defines : defines,313 sources : sources314 });315 };316 return ShadowMapShader;...

Full Screen

Full Screen

shadowClone.js

Source:shadowClone.js Github

copy

Full Screen

1var CenteringTextElement = require("./util/CenteringTextElement");2var elementTools = require("./util/elementTools")();3var math = require("./util/math")();4module.exports = function (graph) {5 /** variable defs **/6 var ShadowClone = {};7 ShadowClone.nodeId = 10003;8 ShadowClone.parent = undefined;9 ShadowClone.s_x = 0;10 ShadowClone.s_y = 0;11 ShadowClone.e_x = 0;12 ShadowClone.e_y = 0;13 ShadowClone.rootElement = undefined;14 ShadowClone.rootNodeLayer = undefined;15 ShadowClone.pathLayer = undefined;16 ShadowClone.nodeElement = undefined;17 ShadowClone.pathElement = undefined;18 ShadowClone.typus = "shadowClone";19 ShadowClone.type = function () {20 return ShadowClone.typus;21 };22 // TODO: We need the endPoint of the Link here!23 ShadowClone.parentNode = function () {24 return ShadowClone.parent;25 };26 ShadowClone.setParentProperty = function (parentProperty, inverted) {27 ShadowClone.invertedProperty = inverted;28 ShadowClone.parent = parentProperty;29 var renElment;30 if (inverted === true) {31 renElment = parentProperty.inverse().labelObject();32 if (renElment !== undefined) {33 if (renElment.linkRangeIntersection && renElment.linkDomainIntersection) {34 var iiP_range = renElment.linkDomainIntersection;35 var iiP_domain = renElment.linkRangeIntersection;36 ShadowClone.s_x = iiP_domain.x;37 ShadowClone.s_y = iiP_domain.y;38 ShadowClone.e_x = iiP_range.x;39 ShadowClone.e_y = iiP_range.y;40 }41 }42 } else {43 renElment = parentProperty.labelObject();44 if (renElment.linkRangeIntersection && renElment.linkDomainIntersection) {45 var iP_range = renElment.linkRangeIntersection;46 var iP_domain = renElment.linkDomainIntersection;47 ShadowClone.s_x = iP_domain.x;48 ShadowClone.s_y = iP_domain.y;49 ShadowClone.e_x = iP_range.x;50 ShadowClone.e_y = iP_range.y;51 }52 }53 ShadowClone.rootNodeLayer.remove();54 ShadowClone.rootNodeLayer = ShadowClone.rootElement.append('g');55 ShadowClone.rootNodeLayer.datum(parentProperty);56 // ShadowClone.pathElement.remove();57 // ShadowClone.pathElement = ShadowClone.pathLayer.append('line');58 //59 // ShadowClone.pathElement.attr("x1", ShadowClone.s_x)60 // .attr("y1", ShadowClone.s_y)61 // .attr("x2", ShadowClone.e_x)62 // .attr("y2", ShadowClone.e_y);63 ShadowClone.pathElement.remove();64 ShadowClone.pathElement = ShadowClone.pathLayer.append('line');65 ShadowClone.markerElement = ShadowClone.pathLayer.append("marker");66 ShadowClone.markerElement.attr("id", "shadowCloneMarker");67 ShadowClone.pathElement.attr("x1", ShadowClone.e_x)68 .attr("y1", ShadowClone.e_y)69 .attr("x2", ShadowClone.s_x)70 .attr("y2", ShadowClone.s_y);71 ShadowClone.pathElement.classed(parentProperty.linkType(), true);72 if (parentProperty.markerElement()) {73 ShadowClone.markerElement.attr("viewBox", parentProperty.markerElement().attr("viewBox"))74 .attr("markerWidth", parentProperty.markerElement().attr("markerWidth"))75 .attr("markerHeight", parentProperty.markerElement().attr("markerHeight"))76 .attr("orient", parentProperty.markerElement().attr("orient"));77 var markerPath = parentProperty.markerElement().select("path");78 if (!markerPath[0].includes(null)) {79 ShadowClone.markerElement.append("path")80 .attr("d", markerPath.attr("d"))81 .classed(parentProperty.markerType(), true);82 }83 ShadowClone.pathElement.attr("marker-end", "url(#" + "shadowCloneMarker" + ")");84 ShadowClone.markerElement.classed("hidden", !elementTools.isDatatypeProperty(parentProperty));85 }86 var rect = ShadowClone.rootNodeLayer.append("rect")87 .classed(parentProperty.styleClass(), true)88 .classed("property", true)89 .attr("x", -parentProperty.width() / 2)90 .attr("y", -parentProperty.height() / 2)91 .attr("width", parentProperty.width())92 .attr("height", parentProperty.height());93 if (parentProperty.visualAttributes()) {94 rect.classed(parentProperty.visualAttributes(), true);95 }96 rect.classed("datatype", false);97 var bgColor = parentProperty.backgroundColor();98 if (parentProperty.attributes().indexOf("deprecated") > -1) {99 bgColor = undefined;100 rect.classed("deprecatedproperty", true);101 } else {102 rect.classed("deprecatedproperty", false);103 }104 rect.style("fill", bgColor);105 // add Text;106 var equivalentsString = parentProperty.equivalentsString();107 var suffixForFollowingEquivalents = equivalentsString ? "," : "";108 var textElement = new CenteringTextElement(ShadowClone.rootNodeLayer, bgColor);109 textElement.addText(parentProperty.labelForCurrentLanguage(), "", suffixForFollowingEquivalents);110 textElement.addEquivalents(equivalentsString);111 textElement.addSubText(parentProperty.indicationString());112 var cx = 0.5 * (ShadowClone.s_x + ShadowClone.e_x);113 var cy = 0.5 * (ShadowClone.s_y + ShadowClone.e_y);114 ShadowClone.rootNodeLayer.attr("transform", "translate(" + cx + "," + cy + ")");115 ShadowClone.rootNodeLayer.classed("hidden", true);116 ShadowClone.pathElement.classed("hidden", true);117 };118 ShadowClone.hideClone = function (val) {119 if (ShadowClone.rootNodeLayer) ShadowClone.rootNodeLayer.classed("hidden", val);120 if (ShadowClone.pathElement) ShadowClone.pathElement.classed("hidden", val);121 };122 ShadowClone.hideParentProperty = function (val) {123 var labelObj = ShadowClone.parent.labelObject();124 if (labelObj) {125 if (ShadowClone.parent.labelElement().attr("transform") === "translate(0,15)" ||126 ShadowClone.parent.labelElement().attr("transform") === "translate(0,-15)")127 ShadowClone.parent.inverse().hide(val);128 }129 ShadowClone.parent.hide(val);130 };131 /** BASE HANDLING FUNCTIONS ------------------------------------------------- **/132 ShadowClone.id = function (index) {133 if (!arguments.length) {134 return ShadowClone.nodeId;135 }136 ShadowClone.nodeId = index;137 };138 ShadowClone.svgPathLayer = function (layer) {139 ShadowClone.pathLayer = layer.append('g');140 };141 ShadowClone.svgRoot = function (root) {142 if (!arguments.length)143 return ShadowClone.rootElement;144 ShadowClone.rootElement = root;145 ShadowClone.rootNodeLayer = ShadowClone.rootElement.append('g');146 };147 /** DRAWING FUNCTIONS ------------------------------------------------- **/148 ShadowClone.drawClone = function () {149 ShadowClone.pathElement = ShadowClone.pathLayer.append('line');150 ShadowClone.pathElement.attr("x1", 0)151 .attr("y1", 0)152 .attr("x2", 0)153 .attr("y2", 0);154 };155 ShadowClone.updateElement = function () {156 ShadowClone.pathElement.attr("x1", ShadowClone.e_x)157 .attr("y1", ShadowClone.e_y)158 .attr("x2", ShadowClone.s_x)159 .attr("y2", ShadowClone.s_y);160 var cx = 0.5 * (ShadowClone.s_x + ShadowClone.e_x);161 var cy = 0.5 * (ShadowClone.s_y + ShadowClone.e_y);162 ShadowClone.rootNodeLayer.attr("transform", "translate(" + cx + "," + cy + ")");163 };164 ShadowClone.setInitialPosition = function () {165 var renElment = ShadowClone.parent.labelObject();166 if (renElment.linkRangeIntersection && renElment.linkDomainIntersection) {167 var iP_range = renElment.linkRangeIntersection;168 var iP_domain = renElment.linkDomainIntersection;169 ShadowClone.e_x = iP_domain.x;170 ShadowClone.e_y = iP_domain.y;171 ShadowClone.s_x = iP_range.x;172 ShadowClone.s_y = iP_range.y;173 }174 ShadowClone.updateElement();175 return;176 //177 // var rex=ShadowClone.parent.range().x;178 // var rey=ShadowClone.parent.range().y;179 //180 //181 // var dex=ShadowClone.parent.domain().x;182 // var dey=ShadowClone.parent.domain().y;183 //184 //185 // var dir_X= rex-dex;186 // var dir_Y= rey-dey;187 //188 // var len=Math.sqrt(dir_X*dir_X+dir_Y*dir_Y);189 // var nX=dir_X/len;190 // var nY=dir_Y/len;191 // ShadowClone.s_x=rex-nX*ShadowClone.parent.range().actualRadius();192 // ShadowClone.s_y=rey-nY*ShadowClone.parent.range().actualRadius();193 //194 // ShadowClone.e_x=dex+nX*ShadowClone.parent.domain().actualRadius();195 // ShadowClone.e_y=dey+nY*ShadowClone.parent.domain().actualRadius();196 // ShadowClone.updateElement();197 };198 ShadowClone.setPositionDomain = function (e_x, e_y) {199 var rex = ShadowClone.parent.range().x;200 var rey = ShadowClone.parent.range().y;201 if (elementTools.isDatatype(ShadowClone.parent.range()) === true) {202 var intersection = math.calculateIntersection({ x: e_x, y: e_y }, ShadowClone.parent.range(), 0);203 ShadowClone.s_x = intersection.x;204 ShadowClone.s_y = intersection.y;205 } else {206 var dir_X = rex - e_x;207 var dir_Y = rey - e_y;208 var len = Math.sqrt(dir_X * dir_X + dir_Y * dir_Y);209 var nX = dir_X / len;210 var nY = dir_Y / len;211 ShadowClone.s_x = rex - nX * ShadowClone.parent.range().actualRadius();212 ShadowClone.s_y = rey - nY * ShadowClone.parent.range().actualRadius();213 }214 ShadowClone.e_x = e_x;215 ShadowClone.e_y = e_y;216 ShadowClone.updateElement();217 };218 ShadowClone.setPosition = function (s_x, s_y) {219 ShadowClone.s_x = s_x;220 ShadowClone.s_y = s_y;221 // add normalized dir;222 var dex = ShadowClone.parent.domain().x;223 var dey = ShadowClone.parent.domain().y;224 var dir_X = s_x - dex;225 var dir_Y = s_y - dey;226 var len = Math.sqrt(dir_X * dir_X + dir_Y * dir_Y);227 var nX = dir_X / len;228 var nY = dir_Y / len;229 ShadowClone.e_x = dex + nX * ShadowClone.parent.domain().actualRadius();230 ShadowClone.e_y = dey + nY * ShadowClone.parent.domain().actualRadius();231 ShadowClone.updateElement();232 };233 /** MOUSE HANDLING FUNCTIONS ------------------------------------------------- **/234 return ShadowClone;...

Full Screen

Full Screen

shadowmap_pars_fragment.glsl.js

Source:shadowmap_pars_fragment.glsl.js Github

copy

Full Screen

1export default /* glsl */`2#ifdef USE_SHADOWMAP3 #if NUM_DIR_LIGHT_SHADOWS > 04 uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];5 varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];6 #endif7 #if NUM_SPOT_LIGHT_SHADOWS > 08 uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];9 varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];10 #endif11 #if NUM_POINT_LIGHT_SHADOWS > 012 uniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];13 varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];14 #endif15 /*16 #if NUM_RECT_AREA_LIGHTS > 017 // TODO (abelnation): create uniforms for area light shadows18 #endif19 */20 float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {21 return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );22 }23 vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {24 return unpack2HalfToRGBA( texture2D( shadow, uv ) );25 }26 float VSMShadow (sampler2D shadow, vec2 uv, float compare ){27 float occlusion = 1.0;28 vec2 distribution = texture2DDistribution( shadow, uv );29 float hard_shadow = step( compare , distribution.x ); // Hard Shadow30 if (hard_shadow != 1.0 ) {31 float distance = compare - distribution.x ;32 float variance = max( 0.00000, distribution.y * distribution.y );33 float softness_probability = variance / (variance + distance * distance ); // Chebeyshevs inequality34 softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); // 0.3 reduces light bleed35 occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );36 }37 return occlusion;38 }39 float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {40 const vec2 offset = vec2( 0.0, 1.0 );41 vec2 texelSize = vec2( 1.0 ) / size;42 vec2 centroidUV = ( floor( uv * size - 0.5 ) + 0.5 ) * texelSize;43 float lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );44 float lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );45 float rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );46 float rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );47 vec2 f = fract( uv * size + 0.5 );48 float a = mix( lb, lt, f.y );49 float b = mix( rb, rt, f.y );50 float c = mix( a, b, f.x );51 return c;52 }53 float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {54 float shadow = 1.0;55 shadowCoord.xyz /= shadowCoord.w;56 shadowCoord.z += shadowBias;57 // if ( something && something ) breaks ATI OpenGL shader compiler58 // if ( all( something, something ) ) using this instead59 bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );60 bool inFrustum = all( inFrustumVec );61 bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );62 bool frustumTest = all( frustumTestVec );63 if ( frustumTest ) {64 #if defined( SHADOWMAP_TYPE_PCF )65 vec2 texelSize = vec2( 1.0 ) / shadowMapSize;66 float dx0 = - texelSize.x * shadowRadius;67 float dy0 = - texelSize.y * shadowRadius;68 float dx1 = + texelSize.x * shadowRadius;69 float dy1 = + texelSize.y * shadowRadius;70 float dx2 = dx0 / 2.0;71 float dy2 = dy0 / 2.0;72 float dx3 = dx1 / 2.0;73 float dy3 = dy1 / 2.0;74 shadow = (75 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +76 texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +77 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +78 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +79 texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +80 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +81 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +82 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +83 texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +84 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +85 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +86 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +87 texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +88 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +89 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +90 texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +91 texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )92 ) * ( 1.0 / 17.0 );93 #elif defined( SHADOWMAP_TYPE_PCF_SOFT )94 vec2 texelSize = vec2( 1.0 ) / shadowMapSize;95 float dx0 = - texelSize.x * shadowRadius;96 float dy0 = - texelSize.y * shadowRadius;97 float dx1 = + texelSize.x * shadowRadius;98 float dy1 = + texelSize.y * shadowRadius;99 shadow = (100 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +101 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +102 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +103 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +104 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +105 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +106 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +107 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +108 texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )109 ) * ( 1.0 / 9.0 );110 #elif defined( SHADOWMAP_TYPE_VSM )111 shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );112 #else // no percentage-closer filtering:113 shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );114 #endif115 }116 return shadow;117 }118 // cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D119 // vector suitable for 2D texture mapping. This code uses the following layout for the120 // 2D texture:121 //122 // xzXZ123 // y Y124 //125 // Y - Positive y direction126 // y - Negative y direction127 // X - Positive x direction128 // x - Negative x direction129 // Z - Positive z direction130 // z - Negative z direction131 //132 // Source and test bed:133 // https://gist.github.com/tschw/da10c43c467ce8afd0c4134 vec2 cubeToUV( vec3 v, float texelSizeY ) {135 // Number of texels to avoid at the edge of each square136 vec3 absV = abs( v );137 // Intersect unit cube138 float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );139 absV *= scaleToCube;140 // Apply scale to avoid seams141 // two texels less per square (one texel will do for NEAREST)142 v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );143 // Unwrap144 // space: -1 ... 1 range for each square145 //146 // #X## dim := ( 4 , 2 )147 // # # center := ( 1 , 1 )148 vec2 planar = v.xy;149 float almostATexel = 1.5 * texelSizeY;150 float almostOne = 1.0 - almostATexel;151 if ( absV.z >= almostOne ) {152 if ( v.z > 0.0 )153 planar.x = 4.0 - v.x;154 } else if ( absV.x >= almostOne ) {155 float signX = sign( v.x );156 planar.x = v.z * signX + 2.0 * signX;157 } else if ( absV.y >= almostOne ) {158 float signY = sign( v.y );159 planar.x = v.x + 2.0 * signY + 2.0;160 planar.y = v.z * signY - 2.0;161 }162 // Transform to UV space163 // scale := 0.5 / dim164 // translate := ( center + 0.5 ) / dim165 return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );166 }167 float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {168 vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );169 // for point lights, the uniform @vShadowCoord is re-purposed to hold170 // the vector from the light to the world-space position of the fragment.171 vec3 lightToPosition = shadowCoord.xyz;172 // dp = normalized distance from light to fragment position173 float dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); // need to clamp?174 dp += shadowBias;175 // bd3D = base direction 3D176 vec3 bd3D = normalize( lightToPosition );177 #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )178 vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;179 return (180 texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +181 texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +182 texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +183 texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +184 texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +185 texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +186 texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +187 texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +188 texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )189 ) * ( 1.0 / 9.0 );190 #else // no percentage-closer filtering191 return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );192 #endif193 }194#endif...

Full Screen

Full Screen

shadowVisibility.js

Source:shadowVisibility.js Github

copy

Full Screen

1//This file is automatically rebuilt by the Cesium build process.2define(function() {3 'use strict';4 return "\n\5float czm_private_shadowVisibility(float visibility, float nDotL, float normalShadingSmooth, float darkness)\n\6{\n\7#ifdef USE_NORMAL_SHADING\n\8#ifdef USE_NORMAL_SHADING_SMOOTH\n\9 float strength = clamp(nDotL / normalShadingSmooth, 0.0, 1.0);\n\10#else\n\11 float strength = step(0.0, nDotL);\n\12#endif\n\13 visibility *= strength;\n\14#endif\n\15\n\16 visibility = max(visibility, darkness);\n\17 return visibility;\n\18}\n\19\n\20#ifdef USE_CUBE_MAP_SHADOW\n\21float czm_shadowVisibility(samplerCube shadowMap, czm_shadowParameters shadowParameters)\n\22{\n\23 float depthBias = shadowParameters.depthBias;\n\24 float depth = shadowParameters.depth;\n\25 float nDotL = shadowParameters.nDotL;\n\26 float normalShadingSmooth = shadowParameters.normalShadingSmooth;\n\27 float darkness = shadowParameters.darkness;\n\28 vec3 uvw = shadowParameters.texCoords;\n\29\n\30 depth -= depthBias;\n\31 float visibility = czm_shadowDepthCompare(shadowMap, uvw, depth);\n\32 return czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);\n\33}\n\34#else\n\35float czm_shadowVisibility(sampler2D shadowMap, czm_shadowParameters shadowParameters)\n\36{\n\37 float depthBias = shadowParameters.depthBias;\n\38 float depth = shadowParameters.depth;\n\39 float nDotL = shadowParameters.nDotL;\n\40 float normalShadingSmooth = shadowParameters.normalShadingSmooth;\n\41 float darkness = shadowParameters.darkness;\n\42 vec2 uv = shadowParameters.texCoords;\n\43\n\44 depth -= depthBias;\n\45#ifdef USE_SOFT_SHADOWS\n\46 vec2 texelStepSize = shadowParameters.texelStepSize;\n\47 float radius = 1.0;\n\48 float dx0 = -texelStepSize.x * radius;\n\49 float dy0 = -texelStepSize.y * radius;\n\50 float dx1 = texelStepSize.x * radius;\n\51 float dy1 = texelStepSize.y * radius;\n\52 float visibility = (\n\53 czm_shadowDepthCompare(shadowMap, uv, depth) +\n\54 czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, dy0), depth) +\n\55 czm_shadowDepthCompare(shadowMap, uv + vec2(0.0, dy0), depth) +\n\56 czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, dy0), depth) +\n\57 czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, 0.0), depth) +\n\58 czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, 0.0), depth) +\n\59 czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, dy1), depth) +\n\60 czm_shadowDepthCompare(shadowMap, uv + vec2(0.0, dy1), depth) +\n\61 czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, dy1), depth)\n\62 ) * (1.0 / 9.0);\n\63#else\n\64 float visibility = czm_shadowDepthCompare(shadowMap, uv, depth);\n\65#endif\n\66\n\67 return czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);\n\68}\n\69#endif\n\70";...

Full Screen

Full Screen

DirectionalLight.js

Source:DirectionalLight.js Github

copy

Full Screen

1/**2 * @author mrdoob / http://mrdoob.com/3 * @author alteredq / http://alteredqualia.com/4 */5THREE.DirectionalLight = function ( color, intensity ) {6 THREE.Light.call( this, color );7 this.type = 'DirectionalLight';8 this.position.set( 0, 1, 0 );9 this.target = new THREE.Object3D();10 this.intensity = ( intensity !== undefined ) ? intensity : 1;11 this.castShadow = false;12 this.onlyShadow = false;13 //14 this.shadowCameraNear = 50;15 this.shadowCameraFar = 5000;16 this.shadowCameraLeft = - 500;17 this.shadowCameraRight = 500;18 this.shadowCameraTop = 500;19 this.shadowCameraBottom = - 500;20 this.shadowCameraVisible = false;21 this.shadowBias = 0;22 this.shadowDarkness = 0.5;23 this.shadowMapWidth = 512;24 this.shadowMapHeight = 512;25 //26 this.shadowCascade = false;27 this.shadowCascadeOffset = new THREE.Vector3( 0, 0, - 1000 );28 this.shadowCascadeCount = 2;29 this.shadowCascadeBias = [ 0, 0, 0 ];30 this.shadowCascadeWidth = [ 512, 512, 512 ];31 this.shadowCascadeHeight = [ 512, 512, 512 ];32 this.shadowCascadeNearZ = [ - 1.000, 0.990, 0.998 ];33 this.shadowCascadeFarZ = [ 0.990, 0.998, 1.000 ];34 this.shadowCascadeArray = [];35 //36 this.shadowMap = null;37 this.shadowMapSize = null;38 this.shadowCamera = null;39 this.shadowMatrix = null;40};41THREE.DirectionalLight.prototype = Object.create( THREE.Light.prototype );42THREE.DirectionalLight.prototype.clone = function () {43 var light = new THREE.DirectionalLight();44 THREE.Light.prototype.clone.call( this, light );45 light.target = this.target.clone();46 light.intensity = this.intensity;47 light.castShadow = this.castShadow;48 light.onlyShadow = this.onlyShadow;49 //50 light.shadowCameraNear = this.shadowCameraNear;51 light.shadowCameraFar = this.shadowCameraFar;52 light.shadowCameraLeft = this.shadowCameraLeft;53 light.shadowCameraRight = this.shadowCameraRight;54 light.shadowCameraTop = this.shadowCameraTop;55 light.shadowCameraBottom = this.shadowCameraBottom;56 light.shadowCameraVisible = this.shadowCameraVisible;57 light.shadowBias = this.shadowBias;58 light.shadowDarkness = this.shadowDarkness;59 light.shadowMapWidth = this.shadowMapWidth;60 light.shadowMapHeight = this.shadowMapHeight;61 //62 light.shadowCascade = this.shadowCascade;63 light.shadowCascadeOffset.copy( this.shadowCascadeOffset );64 light.shadowCascadeCount = this.shadowCascadeCount;65 light.shadowCascadeBias = this.shadowCascadeBias.slice( 0 );66 light.shadowCascadeWidth = this.shadowCascadeWidth.slice( 0 );67 light.shadowCascadeHeight = this.shadowCascadeHeight.slice( 0 );68 light.shadowCascadeNearZ = this.shadowCascadeNearZ.slice( 0 );69 light.shadowCascadeFarZ = this.shadowCascadeFarZ.slice( 0 );70 return light;...

Full Screen

Full Screen

shadows.js

Source:shadows.js Github

copy

Full Screen

1const shadowKeyUmbraOpacity = 0.2;2const shadowKeyPenumbraOpacity = 0.14;3const shadowAmbientShadowOpacity = 0.12;4function createShadow(...px) {5 return [6 `${px[0]}px ${px[1]}px ${px[2]}px ${px[3]}px rgba(0,0,0,${shadowKeyUmbraOpacity})`,7 `${px[4]}px ${px[5]}px ${px[6]}px ${px[7]}px rgba(0,0,0,${shadowKeyPenumbraOpacity})`,8 `${px[8]}px ${px[9]}px ${px[10]}px ${px[11]}px rgba(0,0,0,${shadowAmbientShadowOpacity})`,9 ].join(',');10}11const shadows = [12 'none',13 createShadow(0, 1, 3, 0, 0, 1, 1, 0, 0, 2, 1, -1),14 createShadow(0, 1, 5, 0, 0, 2, 2, 0, 0, 3, 1, -2),15 createShadow(0, 1, 8, 0, 0, 3, 4, 0, 0, 3, 3, -2),16 createShadow(0, 2, 4, -1, 0, 4, 5, 0, 0, 1, 10, 0),17 createShadow(0, 3, 5, -1, 0, 5, 8, 0, 0, 1, 14, 0),18 createShadow(0, 3, 5, -1, 0, 6, 10, 0, 0, 1, 18, 0),19 createShadow(0, 4, 5, -2, 0, 7, 10, 1, 0, 2, 16, 1),20 createShadow(0, 5, 5, -3, 0, 8, 10, 1, 0, 3, 14, 2),21 createShadow(0, 5, 6, -3, 0, 9, 12, 1, 0, 3, 16, 2),22 createShadow(0, 6, 6, -3, 0, 10, 14, 1, 0, 4, 18, 3),23 createShadow(0, 6, 7, -4, 0, 11, 15, 1, 0, 4, 20, 3),24 createShadow(0, 7, 8, -4, 0, 12, 17, 2, 0, 5, 22, 4),25 createShadow(0, 7, 8, -4, 0, 13, 19, 2, 0, 5, 24, 4),26 createShadow(0, 7, 9, -4, 0, 14, 21, 2, 0, 5, 26, 4),27 createShadow(0, 8, 9, -5, 0, 15, 22, 2, 0, 6, 28, 5),28 createShadow(0, 8, 10, -5, 0, 16, 24, 2, 0, 6, 30, 5),29 createShadow(0, 8, 11, -5, 0, 17, 26, 2, 0, 6, 32, 5),30 createShadow(0, 9, 11, -5, 0, 18, 28, 2, 0, 7, 34, 6),31 createShadow(0, 9, 12, -6, 0, 19, 29, 2, 0, 7, 36, 6),32 createShadow(0, 10, 13, -6, 0, 20, 31, 3, 0, 8, 38, 7),33 createShadow(0, 10, 13, -6, 0, 21, 33, 3, 0, 8, 40, 7),34 createShadow(0, 10, 14, -6, 0, 22, 35, 3, 0, 8, 42, 7),35 createShadow(0, 11, 14, -7, 0, 23, 36, 3, 0, 9, 44, 8),36 createShadow(0, 11, 15, -7, 0, 24, 38, 3, 0, 9, 46, 8),37];...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var options = {3};4wptools.api.setOptions(options);5wptools.page('Albert Einstein').get(function(err, resp) {6 console.log(resp);7});8var wptools = require('wptools');9var options = {10};11wptools.api.setOptions(options);12wptools.page('Albert Einstein').get(function(err, resp) {13 console.log(resp);14});15var wptools = require('wptools');16var options = {17};18wptools.page('Albert Einstein').get(function(err, resp) {19 console.log(resp);20});21TypeError: wptools.page(...).get is not a function22var wptools = require('wptools');23var options = {24};25wptools.page('Albert Einstein').get(function(err, resp) {26 console.log(resp);27});28TypeError: wptools.page(...).get is not a function

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2wptools.setOptions({ method: 'shadow' });3var page = wptools.page('wikipedia');4page.get(function(err, resp) {5 console.log(resp);6});7var wptools = require('wptools');8wptools.setOptions({ method: 'web' });9var page = wptools.page('wikipedia');10page.get(function(err, resp) {11 console.log(resp);12});13var wptools = require('wptools');14wptools.setOptions({ method: 'web' });15var page = wptools.page('wikipedia');16page.get(function(err, resp) {17 console.log(resp);18});19var wptools = require('wptools');20wptools.setOptions({ method: 'web' });21var page = wptools.page('wikipedia');22page.get(function(err, resp) {23 console.log(resp);24});25var wptools = require('wptools');26wptools.setOptions({ method: 'web' });27var page = wptools.page('wikipedia');28page.get(function(err, resp) {29 console.log(resp);30});31var wptools = require('wptools');32wptools.setOptions({ method: 'web' });33var page = wptools.page('wikipedia');34page.get(function(err, resp) {35 console.log(resp);36});37var wptools = require('wptools');38wptools.setOptions({ method: 'web' });39var page = wptools.page('wikipedia');40page.get(function(err, resp) {41 console.log(resp);42});43var wptools = require('wptools');44wptools.setOptions({ method: 'web' });45var page = wptools.page('wikipedia');46page.get(function(err, resp) {

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('wpt');2var wpt = new WebPageTest('www.webpagetest.org', 'A.1234567890abcdef1234567890abcdef');3 if (err) {4 console.log(err);5 } else {6 console.log(data);7 }8});9var wpt = require('wpt');10var wpt = new WebPageTest('www.webpagetest.org', 'A.1234567890abcdef1234567890abcdef');11 if (err) {12 console.log(err);13 } else {14 console.log(data);15 }16});17var wpt = require('wpt');18var wpt = new WebPageTest('www.webpagetest.org', 'A.1234567890abcdef1234567890abcdef');19 if (err) {20 console.log(err);21 } else {22 console.log(data);23 }24});25var wpt = require('wpt');26var wpt = new WebPageTest('www.webpagetest.org', 'A.1234567890abcdef1234567890abcdef');27 if (err) {28 console.log(err);29 } else {30 console.log(data);31 }32});33var wpt = require('wpt');34var wpt = new WebPageTest('www.webpagetest.org', 'A.1234567890abcdef1234567890abcdef');35 if (err) {36 console.log(err);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2var wpt = new WebPageTest('www.webpagetest.org');3var options = {4};5wpt.runTest(url, options, function(err, data) {6 if (err) return console.error(err);7 console.log('Test started: ' + data.data.testId);8 console.log('View your test at: ' + data.data.userUrl);9 wpt.getTestResults(data.data.testId, function(err, data) {10 if (err) return console.error(err);11 console.log('Test completed');12 console.log(data);13 });14});15var wpt = require('webpagetest');16var wpt = new WebPageTest('www.webpagetest.org');17var options = {18};19wpt.runTest(url, options, function(err, data) {20 if (err) return console.error(err);21 console.log('Test started: ' + data.data.testId);22 console.log('View your test at: ' + data.data.userUrl);23 wpt.getTestResults(data.data.testId, function(err, data) {24 if (err) return console.error(err);25 console.log('Test completed');26 console.log(data);27 });28});29var wpt = require('webpagetest');30var wpt = new WebPageTest('www.webpagetest.org');31var options = {

Full Screen

Using AI Code Generation

copy

Full Screen

1const wptools = require('wptools');2wptools.setOptions({ method: 'shadow' });3wptools.page('Albert Einstein').get(function(err, response) {4 console.log(response);5});6const wptools = require('wptools');7wptools.setOptions({ method: 'shadow' });8wptools.page('Albert Einstein').get(function(err, response) {9 console.log(response);10});11const wptools = require('wptools');12wptools.setOptions({ method: 'shadow' });13wptools.page('Albert Einstein').get(function(err, response) {14 console.log(response);15});16const wptools = require('wptools');17wptools.setOptions({ method: 'shadow' });18wptools.page('Albert Einstein').get(function(err, response) {19 console.log(response);20});21const wptools = require('wptools');22wptools.setOptions({ method: 'shadow' });23wptools.page('Albert Einstein').get(function(err, response) {24 console.log(response);25});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptool = require('wptool');2wp.shadow(function(err, data){3 if(err){4 console.log(err);5 }6 else{7 console.log(data);8 }9});10var wptool = require('wptool');11wp.shadow(function(err, data){12 if(err){13 console.log(err);14 }15 else{16 console.log(data);17 }18});19var wptool = require('wptool');20wp.shadow(function(err, data){21 if(err){22 console.log(err);23 }24 else{25 console.log(data);26 }27});28var wptool = require('wptool');29wp.shadow(function(err, data){30 if(err){31 console.log(err);32 }33 else{34 console.log(data);35 }36});37var wptool = require('wptool');38wp.shadow(function(err, data){39 if(err){40 console.log(err);41 }42 else{43 console.log(data);44 }45});46var wptool = require('wptool');47wp.shadow(function(err, data){48 if(err){49 console.log(err);50 }51 else{52 console.log(data);53 }54});55var wptool = require('wptool');56wp.shadow(function(err, data){57 if(err){58 console.log(err);59 }60 else{61 console.log(data);62 }63});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptoolkit = require('wptoolkit').default();2wptoolkit.getPosts()3 .then((data) => {4 console.log(data);5 })6 .catch((error) => {7 console.log(error);8 });9var wptoolkit = require('wptoolkit').shadow();10wptoolkit.getPosts()11 .then((data) => {12 console.log(data);13 })14 .catch((error) => {15 console.log(error);16 });

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful