}
*/
PhysicsRadialExplosionEvent.prototype.getImpostorForceAndContactPoint = function (impostor, origin, radius, strength, falloff) {
if (impostor.mass === 0) {
return null;
}
if (!this._intersectsWithSphere(impostor, origin, radius)) {
return null;
}
if (impostor.object.getClassName() !== 'Mesh' && impostor.object.getClassName() !== 'InstancedMesh') {
return null;
}
var impostorObjectCenter = impostor.getObjectCenter();
var direction = impostorObjectCenter.subtract(origin);
var ray = new BABYLON.Ray(origin, direction, radius);
this._rays.push(ray);
var hit = ray.intersectsMesh(impostor.object);
var contactPoint = hit.pickedPoint;
if (!contactPoint) {
return null;
}
var distanceFromOrigin = BABYLON.Vector3.Distance(origin, contactPoint);
if (distanceFromOrigin > radius) {
return null;
}
var multiplier = falloff === PhysicsRadialImpulseFalloff.Constant
? strength
: strength * (1 - (distanceFromOrigin / radius));
var force = direction.multiplyByFloats(multiplier, multiplier, multiplier);
return { force: force, contactPoint: contactPoint };
};
/**
* Disposes the sphere.
* @param {bolean} force
*/
PhysicsRadialExplosionEvent.prototype.dispose = function (force) {
var _this = this;
if (force === void 0) { force = true; }
if (force) {
this._sphere.dispose();
}
else {
setTimeout(function () {
if (!_this._dataFetched) {
_this._sphere.dispose();
}
}, 0);
}
};
/*** Helpers ***/
PhysicsRadialExplosionEvent.prototype._prepareSphere = function () {
if (!this._sphere) {
this._sphere = BABYLON.MeshBuilder.CreateSphere("radialExplosionEventSphere", this._sphereOptions, this._scene);
this._sphere.isVisible = false;
}
};
PhysicsRadialExplosionEvent.prototype._intersectsWithSphere = function (impostor, origin, radius) {
var impostorObject = impostor.object;
this._prepareSphere();
this._sphere.position = origin;
this._sphere.scaling = new BABYLON.Vector3(radius * 2, radius * 2, radius * 2);
this._sphere._updateBoundingInfo();
this._sphere.computeWorldMatrix(true);
return this._sphere.intersectsMesh(impostorObject, true);
};
return PhysicsRadialExplosionEvent;
}());
BABYLON.PhysicsRadialExplosionEvent = PhysicsRadialExplosionEvent;
/***** Gravitational Field *****/
var PhysicsGravitationalFieldEvent = /** @class */ (function () {
function PhysicsGravitationalFieldEvent(physicsHelper, scene, origin, radius, strength, falloff) {
if (falloff === void 0) { falloff = PhysicsRadialImpulseFalloff.Constant; }
this._dataFetched = false; // check if the has been fetched the data. If not, do cleanup
this._physicsHelper = physicsHelper;
this._scene = scene;
this._origin = origin;
this._radius = radius;
this._strength = strength;
this._falloff = falloff;
this._tickCallback = this._tick.bind(this);
}
/**
* Returns the data related to the gravitational field event (sphere).
* @returns {PhysicsGravitationalFieldEventData}
*/
PhysicsGravitationalFieldEvent.prototype.getData = function () {
this._dataFetched = true;
return {
sphere: this._sphere,
};
};
/**
* Enables the gravitational field.
*/
PhysicsGravitationalFieldEvent.prototype.enable = function () {
this._tickCallback.call(this);
this._scene.registerBeforeRender(this._tickCallback);
};
/**
* Disables the gravitational field.
*/
PhysicsGravitationalFieldEvent.prototype.disable = function () {
this._scene.unregisterBeforeRender(this._tickCallback);
};
/**
* Disposes the sphere.
* @param {bolean} force
*/
PhysicsGravitationalFieldEvent.prototype.dispose = function (force) {
var _this = this;
if (force === void 0) { force = true; }
if (force) {
this._sphere.dispose();
}
else {
setTimeout(function () {
if (!_this._dataFetched) {
_this._sphere.dispose();
}
}, 0);
}
};
PhysicsGravitationalFieldEvent.prototype._tick = function () {
// Since the params won't change, we fetch the event only once
if (this._sphere) {
this._physicsHelper.applyRadialExplosionForce(this._origin, this._radius, this._strength * -1, this._falloff);
}
else {
var radialExplosionEvent = this._physicsHelper.applyRadialExplosionForce(this._origin, this._radius, this._strength * -1, this._falloff);
if (radialExplosionEvent) {
this._sphere = radialExplosionEvent.getData().sphere.clone('radialExplosionEventSphereClone');
}
}
};
return PhysicsGravitationalFieldEvent;
}());
BABYLON.PhysicsGravitationalFieldEvent = PhysicsGravitationalFieldEvent;
/***** Updraft *****/
var PhysicsUpdraftEvent = /** @class */ (function () {
function PhysicsUpdraftEvent(_scene, _origin, _radius, _strength, _height, _updraftMode) {
this._scene = _scene;
this._origin = _origin;
this._radius = _radius;
this._strength = _strength;
this._height = _height;
this._updraftMode = _updraftMode;
this._originTop = BABYLON.Vector3.Zero(); // the most upper part of the cylinder
this._originDirection = BABYLON.Vector3.Zero(); // used if the updraftMode is perpendicular
this._cylinderPosition = BABYLON.Vector3.Zero(); // to keep the cylinders position, because normally the origin is in the center and not on the bottom
this._dataFetched = false; // check if the has been fetched the data. If not, do cleanup
this._physicsEngine = this._scene.getPhysicsEngine();
this._origin.addToRef(new BABYLON.Vector3(0, this._height / 2, 0), this._cylinderPosition);
this._origin.addToRef(new BABYLON.Vector3(0, this._height, 0), this._originTop);
if (this._updraftMode === PhysicsUpdraftMode.Perpendicular) {
this._originDirection = this._origin.subtract(this._originTop).normalize();
}
this._tickCallback = this._tick.bind(this);
}
/**
* Returns the data related to the updraft event (cylinder).
* @returns {PhysicsUpdraftEventData}
*/
PhysicsUpdraftEvent.prototype.getData = function () {
this._dataFetched = true;
return {
cylinder: this._cylinder,
};
};
/**
* Enables the updraft.
*/
PhysicsUpdraftEvent.prototype.enable = function () {
this._tickCallback.call(this);
this._scene.registerBeforeRender(this._tickCallback);
};
/**
* Disables the cortex.
*/
PhysicsUpdraftEvent.prototype.disable = function () {
this._scene.unregisterBeforeRender(this._tickCallback);
};
/**
* Disposes the sphere.
* @param {bolean} force
*/
PhysicsUpdraftEvent.prototype.dispose = function (force) {
var _this = this;
if (force === void 0) { force = true; }
if (force) {
this._cylinder.dispose();
}
else {
setTimeout(function () {
if (!_this._dataFetched) {
_this._cylinder.dispose();
}
}, 0);
}
};
PhysicsUpdraftEvent.prototype.getImpostorForceAndContactPoint = function (impostor) {
if (impostor.mass === 0) {
return null;
}
if (!this._intersectsWithCylinder(impostor)) {
return null;
}
var impostorObjectCenter = impostor.getObjectCenter();
if (this._updraftMode === PhysicsUpdraftMode.Perpendicular) {
var direction = this._originDirection;
}
else {
var direction = impostorObjectCenter.subtract(this._originTop);
}
var multiplier = this._strength * -1;
var force = direction.multiplyByFloats(multiplier, multiplier, multiplier);
return { force: force, contactPoint: impostorObjectCenter };
};
PhysicsUpdraftEvent.prototype._tick = function () {
var _this = this;
this._physicsEngine.getImpostors().forEach(function (impostor) {
var impostorForceAndContactPoint = _this.getImpostorForceAndContactPoint(impostor);
if (!impostorForceAndContactPoint) {
return;
}
impostor.applyForce(impostorForceAndContactPoint.force, impostorForceAndContactPoint.contactPoint);
});
};
/*** Helpers ***/
PhysicsUpdraftEvent.prototype._prepareCylinder = function () {
if (!this._cylinder) {
this._cylinder = BABYLON.MeshBuilder.CreateCylinder("updraftEventCylinder", {
height: this._height,
diameter: this._radius * 2,
}, this._scene);
this._cylinder.isVisible = false;
}
};
PhysicsUpdraftEvent.prototype._intersectsWithCylinder = function (impostor) {
var impostorObject = impostor.object;
this._prepareCylinder();
this._cylinder.position = this._cylinderPosition;
return this._cylinder.intersectsMesh(impostorObject, true);
};
return PhysicsUpdraftEvent;
}());
BABYLON.PhysicsUpdraftEvent = PhysicsUpdraftEvent;
/***** Vortex *****/
var PhysicsVortexEvent = /** @class */ (function () {
function PhysicsVortexEvent(_scene, _origin, _radius, _strength, _height) {
this._scene = _scene;
this._origin = _origin;
this._radius = _radius;
this._strength = _strength;
this._height = _height;
this._originTop = BABYLON.Vector3.Zero(); // the most upper part of the cylinder
this._centripetalForceThreshold = 0.7; // at which distance, relative to the radius the centripetal forces should kick in
this._updraftMultiplier = 0.02;
this._cylinderPosition = BABYLON.Vector3.Zero(); // to keep the cylinders position, because normally the origin is in the center and not on the bottom
this._dataFetched = false; // check if the has been fetched the data. If not, do cleanup
this._physicsEngine = this._scene.getPhysicsEngine();
this._origin.addToRef(new BABYLON.Vector3(0, this._height / 2, 0), this._cylinderPosition);
this._origin.addToRef(new BABYLON.Vector3(0, this._height, 0), this._originTop);
this._tickCallback = this._tick.bind(this);
}
/**
* Returns the data related to the vortex event (cylinder).
* @returns {PhysicsVortexEventData}
*/
PhysicsVortexEvent.prototype.getData = function () {
this._dataFetched = true;
return {
cylinder: this._cylinder,
};
};
/**
* Enables the vortex.
*/
PhysicsVortexEvent.prototype.enable = function () {
this._tickCallback.call(this);
this._scene.registerBeforeRender(this._tickCallback);
};
/**
* Disables the cortex.
*/
PhysicsVortexEvent.prototype.disable = function () {
this._scene.unregisterBeforeRender(this._tickCallback);
};
/**
* Disposes the sphere.
* @param {bolean} force
*/
PhysicsVortexEvent.prototype.dispose = function (force) {
var _this = this;
if (force === void 0) { force = true; }
if (force) {
this._cylinder.dispose();
}
else {
setTimeout(function () {
if (!_this._dataFetched) {
_this._cylinder.dispose();
}
}, 0);
}
};
PhysicsVortexEvent.prototype.getImpostorForceAndContactPoint = function (impostor) {
if (impostor.mass === 0) {
return null;
}
if (!this._intersectsWithCylinder(impostor)) {
return null;
}
if (impostor.object.getClassName() !== 'Mesh' && impostor.object.getClassName() !== 'InstancedMesh') {
return null;
}
var impostorObjectCenter = impostor.getObjectCenter();
var originOnPlane = new BABYLON.Vector3(this._origin.x, impostorObjectCenter.y, this._origin.z); // the distance to the origin as if both objects were on a plane (Y-axis)
var originToImpostorDirection = impostorObjectCenter.subtract(originOnPlane);
var ray = new BABYLON.Ray(originOnPlane, originToImpostorDirection, this._radius);
var hit = ray.intersectsMesh(impostor.object);
var contactPoint = hit.pickedPoint;
if (!contactPoint) {
return null;
}
var absoluteDistanceFromOrigin = hit.distance / this._radius;
var perpendicularDirection = BABYLON.Vector3.Cross(originOnPlane, impostorObjectCenter).normalize();
var directionToOrigin = contactPoint.normalize();
if (absoluteDistanceFromOrigin > this._centripetalForceThreshold) {
directionToOrigin = directionToOrigin.negate();
}
// TODO: find a more physically based solution
if (absoluteDistanceFromOrigin > this._centripetalForceThreshold) {
var forceX = directionToOrigin.x * this._strength / 8;
var forceY = directionToOrigin.y * this._updraftMultiplier;
var forceZ = directionToOrigin.z * this._strength / 8;
}
else {
var forceX = (perpendicularDirection.x + directionToOrigin.x) / 2;
var forceY = this._originTop.y * this._updraftMultiplier;
var forceZ = (perpendicularDirection.z + directionToOrigin.z) / 2;
}
var force = new BABYLON.Vector3(forceX, forceY, forceZ);
force = force.multiplyByFloats(this._strength, this._strength, this._strength);
return { force: force, contactPoint: impostorObjectCenter };
};
PhysicsVortexEvent.prototype._tick = function () {
var _this = this;
this._physicsEngine.getImpostors().forEach(function (impostor) {
var impostorForceAndContactPoint = _this.getImpostorForceAndContactPoint(impostor);
if (!impostorForceAndContactPoint) {
return;
}
impostor.applyForce(impostorForceAndContactPoint.force, impostorForceAndContactPoint.contactPoint);
});
};
/*** Helpers ***/
PhysicsVortexEvent.prototype._prepareCylinder = function () {
if (!this._cylinder) {
this._cylinder = BABYLON.MeshBuilder.CreateCylinder("vortexEventCylinder", {
height: this._height,
diameter: this._radius * 2,
}, this._scene);
this._cylinder.isVisible = false;
}
};
PhysicsVortexEvent.prototype._intersectsWithCylinder = function (impostor) {
var impostorObject = impostor.object;
this._prepareCylinder();
this._cylinder.position = this._cylinderPosition;
return this._cylinder.intersectsMesh(impostorObject, true);
};
return PhysicsVortexEvent;
}());
BABYLON.PhysicsVortexEvent = PhysicsVortexEvent;
/***** Enums *****/
/**
* The strenght of the force in correspondence to the distance of the affected object
*/
var PhysicsRadialImpulseFalloff;
(function (PhysicsRadialImpulseFalloff) {
/** Defines that impulse is constant in strength across it's whole radius */
PhysicsRadialImpulseFalloff[PhysicsRadialImpulseFalloff["Constant"] = 0] = "Constant";
/** DEfines that impulse gets weaker if it's further from the origin */
PhysicsRadialImpulseFalloff[PhysicsRadialImpulseFalloff["Linear"] = 1] = "Linear";
})(PhysicsRadialImpulseFalloff = BABYLON.PhysicsRadialImpulseFalloff || (BABYLON.PhysicsRadialImpulseFalloff = {}));
/**
* The strenght of the force in correspondence to the distance of the affected object
*/
var PhysicsUpdraftMode;
(function (PhysicsUpdraftMode) {
/** Defines that the upstream forces will pull towards the top center of the cylinder */
PhysicsUpdraftMode[PhysicsUpdraftMode["Center"] = 0] = "Center";
/** Defines that once a impostor is inside the cylinder, it will shoot out perpendicular from the ground of the cylinder */
PhysicsUpdraftMode[PhysicsUpdraftMode["Perpendicular"] = 1] = "Perpendicular";
})(PhysicsUpdraftMode = BABYLON.PhysicsUpdraftMode || (BABYLON.PhysicsUpdraftMode = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.physicsHelper.js.map
var BABYLON;
(function (BABYLON) {
var CannonJSPlugin = /** @class */ (function () {
function CannonJSPlugin(_useDeltaForWorldStep, iterations) {
if (_useDeltaForWorldStep === void 0) { _useDeltaForWorldStep = true; }
if (iterations === void 0) { iterations = 10; }
this._useDeltaForWorldStep = _useDeltaForWorldStep;
this.name = "CannonJSPlugin";
this._physicsMaterials = new Array();
this._fixedTimeStep = 1 / 60;
//See https://github.com/schteppe/CANNON.js/blob/gh-pages/demos/collisionFilter.html
this.BJSCANNON = CANNON;
this._minus90X = new BABYLON.Quaternion(-0.7071067811865475, 0, 0, 0.7071067811865475);
this._plus90X = new BABYLON.Quaternion(0.7071067811865475, 0, 0, 0.7071067811865475);
this._tmpPosition = BABYLON.Vector3.Zero();
this._tmpDeltaPosition = BABYLON.Vector3.Zero();
this._tmpUnityRotation = new BABYLON.Quaternion();
if (!this.isSupported()) {
BABYLON.Tools.Error("CannonJS is not available. Please make sure you included the js file.");
return;
}
this._extendNamespace();
this.world = new this.BJSCANNON.World();
this.world.broadphase = new this.BJSCANNON.NaiveBroadphase();
this.world.solver.iterations = iterations;
}
CannonJSPlugin.prototype.setGravity = function (gravity) {
this.world.gravity.copy(gravity);
};
CannonJSPlugin.prototype.setTimeStep = function (timeStep) {
this._fixedTimeStep = timeStep;
};
CannonJSPlugin.prototype.getTimeStep = function () {
return this._fixedTimeStep;
};
CannonJSPlugin.prototype.executeStep = function (delta, impostors) {
this.world.step(this._fixedTimeStep, this._useDeltaForWorldStep ? delta : 0, 3);
};
CannonJSPlugin.prototype.applyImpulse = function (impostor, force, contactPoint) {
var worldPoint = new this.BJSCANNON.Vec3(contactPoint.x, contactPoint.y, contactPoint.z);
var impulse = new this.BJSCANNON.Vec3(force.x, force.y, force.z);
impostor.physicsBody.applyImpulse(impulse, worldPoint);
};
CannonJSPlugin.prototype.applyForce = function (impostor, force, contactPoint) {
var worldPoint = new this.BJSCANNON.Vec3(contactPoint.x, contactPoint.y, contactPoint.z);
var impulse = new this.BJSCANNON.Vec3(force.x, force.y, force.z);
impostor.physicsBody.applyForce(impulse, worldPoint);
};
CannonJSPlugin.prototype.generatePhysicsBody = function (impostor) {
//parent-child relationship. Does this impostor has a parent impostor?
if (impostor.parent) {
if (impostor.physicsBody) {
this.removePhysicsBody(impostor);
//TODO is that needed?
impostor.forceUpdate();
}
return;
}
//should a new body be created for this impostor?
if (impostor.isBodyInitRequired()) {
var shape = this._createShape(impostor);
//unregister events, if body is being changed
var oldBody = impostor.physicsBody;
if (oldBody) {
this.removePhysicsBody(impostor);
}
//create the body and material
var material = this._addMaterial("mat-" + impostor.uniqueId, impostor.getParam("friction"), impostor.getParam("restitution"));
var bodyCreationObject = {
mass: impostor.getParam("mass"),
material: material
};
// A simple extend, in case native options were used.
var nativeOptions = impostor.getParam("nativeOptions");
for (var key in nativeOptions) {
if (nativeOptions.hasOwnProperty(key)) {
bodyCreationObject[key] = nativeOptions[key];
}
}
impostor.physicsBody = new this.BJSCANNON.Body(bodyCreationObject);
impostor.physicsBody.addEventListener("collide", impostor.onCollide);
this.world.addEventListener("preStep", impostor.beforeStep);
this.world.addEventListener("postStep", impostor.afterStep);
impostor.physicsBody.addShape(shape);
this.world.add(impostor.physicsBody);
//try to keep the body moving in the right direction by taking old properties.
//Should be tested!
if (oldBody) {
['force', 'torque', 'velocity', 'angularVelocity'].forEach(function (param) {
impostor.physicsBody[param].copy(oldBody[param]);
});
}
this._processChildMeshes(impostor);
}
//now update the body's transformation
this._updatePhysicsBodyTransformation(impostor);
};
CannonJSPlugin.prototype._processChildMeshes = function (mainImpostor) {
var _this = this;
var meshChildren = mainImpostor.object.getChildMeshes ? mainImpostor.object.getChildMeshes(true) : [];
var currentRotation = mainImpostor.object.rotationQuaternion;
if (meshChildren.length) {
var processMesh = function (localPosition, mesh) {
if (!currentRotation || !mesh.rotationQuaternion) {
return;
}
var childImpostor = mesh.getPhysicsImpostor();
if (childImpostor) {
var parent = childImpostor.parent;
if (parent !== mainImpostor) {
var pPosition = mesh.getAbsolutePosition().subtract(mainImpostor.object.getAbsolutePosition());
var localRotation = mesh.rotationQuaternion.multiply(BABYLON.Quaternion.Inverse(currentRotation));
if (childImpostor.physicsBody) {
_this.removePhysicsBody(childImpostor);
childImpostor.physicsBody = null;
}
childImpostor.parent = mainImpostor;
childImpostor.resetUpdateFlags();
mainImpostor.physicsBody.addShape(_this._createShape(childImpostor), new _this.BJSCANNON.Vec3(pPosition.x, pPosition.y, pPosition.z), new _this.BJSCANNON.Quaternion(localRotation.x, localRotation.y, localRotation.z, localRotation.w));
//Add the mass of the children.
mainImpostor.physicsBody.mass += childImpostor.getParam("mass");
}
}
currentRotation.multiplyInPlace(mesh.rotationQuaternion);
mesh.getChildMeshes(true).filter(function (m) { return !!m.physicsImpostor; }).forEach(processMesh.bind(_this, mesh.getAbsolutePosition()));
};
meshChildren.filter(function (m) { return !!m.physicsImpostor; }).forEach(processMesh.bind(this, mainImpostor.object.getAbsolutePosition()));
}
};
CannonJSPlugin.prototype.removePhysicsBody = function (impostor) {
impostor.physicsBody.removeEventListener("collide", impostor.onCollide);
this.world.removeEventListener("preStep", impostor.beforeStep);
this.world.removeEventListener("postStep", impostor.afterStep);
this.world.remove(impostor.physicsBody);
};
CannonJSPlugin.prototype.generateJoint = function (impostorJoint) {
var mainBody = impostorJoint.mainImpostor.physicsBody;
var connectedBody = impostorJoint.connectedImpostor.physicsBody;
if (!mainBody || !connectedBody) {
return;
}
var constraint;
var jointData = impostorJoint.joint.jointData;
//TODO - https://github.com/schteppe/this.BJSCANNON.js/blob/gh-pages/demos/collisionFilter.html
var constraintData = {
pivotA: jointData.mainPivot ? new this.BJSCANNON.Vec3().copy(jointData.mainPivot) : null,
pivotB: jointData.connectedPivot ? new this.BJSCANNON.Vec3().copy(jointData.connectedPivot) : null,
axisA: jointData.mainAxis ? new this.BJSCANNON.Vec3().copy(jointData.mainAxis) : null,
axisB: jointData.connectedAxis ? new this.BJSCANNON.Vec3().copy(jointData.connectedAxis) : null,
maxForce: jointData.nativeParams.maxForce,
collideConnected: !!jointData.collision
};
switch (impostorJoint.joint.type) {
case BABYLON.PhysicsJoint.HingeJoint:
case BABYLON.PhysicsJoint.Hinge2Joint:
constraint = new this.BJSCANNON.HingeConstraint(mainBody, connectedBody, constraintData);
break;
case BABYLON.PhysicsJoint.DistanceJoint:
constraint = new this.BJSCANNON.DistanceConstraint(mainBody, connectedBody, jointData.maxDistance || 2);
break;
case BABYLON.PhysicsJoint.SpringJoint:
var springData = jointData;
constraint = new this.BJSCANNON.Spring(mainBody, connectedBody, {
restLength: springData.length,
stiffness: springData.stiffness,
damping: springData.damping,
localAnchorA: constraintData.pivotA,
localAnchorB: constraintData.pivotB
});
break;
case BABYLON.PhysicsJoint.LockJoint:
constraint = new this.BJSCANNON.LockConstraint(mainBody, connectedBody, constraintData);
break;
case BABYLON.PhysicsJoint.PointToPointJoint:
case BABYLON.PhysicsJoint.BallAndSocketJoint:
default:
constraint = new this.BJSCANNON.PointToPointConstraint(mainBody, constraintData.pivotA, connectedBody, constraintData.pivotA, constraintData.maxForce);
break;
}
//set the collideConnected flag after the creation, since DistanceJoint ignores it.
constraint.collideConnected = !!jointData.collision;
impostorJoint.joint.physicsJoint = constraint;
//don't add spring as constraint, as it is not one.
if (impostorJoint.joint.type !== BABYLON.PhysicsJoint.SpringJoint) {
this.world.addConstraint(constraint);
}
else {
impostorJoint.mainImpostor.registerAfterPhysicsStep(function () {
constraint.applyForce();
});
}
};
CannonJSPlugin.prototype.removeJoint = function (impostorJoint) {
this.world.removeConstraint(impostorJoint.joint.physicsJoint);
};
CannonJSPlugin.prototype._addMaterial = function (name, friction, restitution) {
var index;
var mat;
for (index = 0; index < this._physicsMaterials.length; index++) {
mat = this._physicsMaterials[index];
if (mat.friction === friction && mat.restitution === restitution) {
return mat;
}
}
var currentMat = new this.BJSCANNON.Material(name);
currentMat.friction = friction;
currentMat.restitution = restitution;
this._physicsMaterials.push(currentMat);
return currentMat;
};
CannonJSPlugin.prototype._checkWithEpsilon = function (value) {
return value < BABYLON.PhysicsEngine.Epsilon ? BABYLON.PhysicsEngine.Epsilon : value;
};
CannonJSPlugin.prototype._createShape = function (impostor) {
var object = impostor.object;
var returnValue;
var extendSize = impostor.getObjectExtendSize();
switch (impostor.type) {
case BABYLON.PhysicsImpostor.SphereImpostor:
var radiusX = extendSize.x;
var radiusY = extendSize.y;
var radiusZ = extendSize.z;
returnValue = new this.BJSCANNON.Sphere(Math.max(this._checkWithEpsilon(radiusX), this._checkWithEpsilon(radiusY), this._checkWithEpsilon(radiusZ)) / 2);
break;
//TMP also for cylinder - TODO Cannon supports cylinder natively.
case BABYLON.PhysicsImpostor.CylinderImpostor:
returnValue = new this.BJSCANNON.Cylinder(this._checkWithEpsilon(extendSize.x) / 2, this._checkWithEpsilon(extendSize.x) / 2, this._checkWithEpsilon(extendSize.y), 16);
break;
case BABYLON.PhysicsImpostor.BoxImpostor:
var box = extendSize.scale(0.5);
returnValue = new this.BJSCANNON.Box(new this.BJSCANNON.Vec3(this._checkWithEpsilon(box.x), this._checkWithEpsilon(box.y), this._checkWithEpsilon(box.z)));
break;
case BABYLON.PhysicsImpostor.PlaneImpostor:
BABYLON.Tools.Warn("Attention, PlaneImposter might not behave as you expect. Consider using BoxImposter instead");
returnValue = new this.BJSCANNON.Plane();
break;
case BABYLON.PhysicsImpostor.MeshImpostor:
// should transform the vertex data to world coordinates!!
var rawVerts = object.getVerticesData ? object.getVerticesData(BABYLON.VertexBuffer.PositionKind) : [];
var rawFaces = object.getIndices ? object.getIndices() : [];
if (!rawVerts)
return;
// get only scale! so the object could transform correctly.
var oldPosition = object.position.clone();
var oldRotation = object.rotation && object.rotation.clone();
var oldQuaternion = object.rotationQuaternion && object.rotationQuaternion.clone();
object.position.copyFromFloats(0, 0, 0);
object.rotation && object.rotation.copyFromFloats(0, 0, 0);
object.rotationQuaternion && object.rotationQuaternion.copyFrom(impostor.getParentsRotation());
object.rotationQuaternion && object.parent && object.rotationQuaternion.conjugateInPlace();
var transform = object.computeWorldMatrix(true);
// convert rawVerts to object space
var temp = new Array();
var index;
for (index = 0; index < rawVerts.length; index += 3) {
BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(rawVerts, index), transform).toArray(temp, index);
}
BABYLON.Tools.Warn("MeshImpostor only collides against spheres.");
returnValue = new this.BJSCANNON.Trimesh(temp, rawFaces);
//now set back the transformation!
object.position.copyFrom(oldPosition);
oldRotation && object.rotation && object.rotation.copyFrom(oldRotation);
oldQuaternion && object.rotationQuaternion && object.rotationQuaternion.copyFrom(oldQuaternion);
break;
case BABYLON.PhysicsImpostor.HeightmapImpostor:
var oldPosition2 = object.position.clone();
var oldRotation2 = object.rotation && object.rotation.clone();
var oldQuaternion2 = object.rotationQuaternion && object.rotationQuaternion.clone();
object.position.copyFromFloats(0, 0, 0);
object.rotation && object.rotation.copyFromFloats(0, 0, 0);
object.rotationQuaternion && object.rotationQuaternion.copyFrom(impostor.getParentsRotation());
object.rotationQuaternion && object.parent && object.rotationQuaternion.conjugateInPlace();
object.rotationQuaternion && object.rotationQuaternion.multiplyInPlace(this._minus90X);
returnValue = this._createHeightmap(object);
object.position.copyFrom(oldPosition2);
oldRotation2 && object.rotation && object.rotation.copyFrom(oldRotation2);
oldQuaternion2 && object.rotationQuaternion && object.rotationQuaternion.copyFrom(oldQuaternion2);
object.computeWorldMatrix(true);
break;
case BABYLON.PhysicsImpostor.ParticleImpostor:
returnValue = new this.BJSCANNON.Particle();
break;
}
return returnValue;
};
CannonJSPlugin.prototype._createHeightmap = function (object, pointDepth) {
var pos = (object.getVerticesData(BABYLON.VertexBuffer.PositionKind));
var transform = object.computeWorldMatrix(true);
// convert rawVerts to object space
var temp = new Array();
var index;
for (index = 0; index < pos.length; index += 3) {
BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(pos, index), transform).toArray(temp, index);
}
pos = temp;
var matrix = new Array();
//For now pointDepth will not be used and will be automatically calculated.
//Future reference - try and find the best place to add a reference to the pointDepth variable.
var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
var boundingInfo = object.getBoundingInfo();
var dim = Math.min(boundingInfo.boundingBox.extendSizeWorld.x, boundingInfo.boundingBox.extendSizeWorld.y);
var minY = boundingInfo.boundingBox.extendSizeWorld.z;
var elementSize = dim * 2 / arraySize;
for (var i = 0; i < pos.length; i = i + 3) {
var x = Math.round((pos[i + 0]) / elementSize + arraySize / 2);
var z = Math.round(((pos[i + 1]) / elementSize - arraySize / 2) * -1);
var y = -pos[i + 2] + minY;
if (!matrix[x]) {
matrix[x] = [];
}
if (!matrix[x][z]) {
matrix[x][z] = y;
}
matrix[x][z] = Math.max(y, matrix[x][z]);
}
for (var x = 0; x <= arraySize; ++x) {
if (!matrix[x]) {
var loc = 1;
while (!matrix[(x + loc) % arraySize]) {
loc++;
}
matrix[x] = matrix[(x + loc) % arraySize].slice();
//console.log("missing x", x);
}
for (var z = 0; z <= arraySize; ++z) {
if (!matrix[x][z]) {
var loc = 1;
var newValue;
while (newValue === undefined) {
newValue = matrix[x][(z + loc++) % arraySize];
}
matrix[x][z] = newValue;
}
}
}
var shape = new this.BJSCANNON.Heightfield(matrix, {
elementSize: elementSize
});
//For future reference, needed for body transformation
shape.minY = minY;
return shape;
};
CannonJSPlugin.prototype._updatePhysicsBodyTransformation = function (impostor) {
var object = impostor.object;
//make sure it is updated...
object.computeWorldMatrix && object.computeWorldMatrix(true);
// The delta between the mesh position and the mesh bounding box center
var bInfo = object.getBoundingInfo();
if (!bInfo)
return;
var center = impostor.getObjectCenter();
//m.getAbsolutePosition().subtract(m.getBoundingInfo().boundingBox.centerWorld)
this._tmpDeltaPosition.copyFrom(object.getAbsolutePivotPoint().subtract(center));
this._tmpDeltaPosition.divideInPlace(impostor.object.scaling);
this._tmpPosition.copyFrom(center);
var quaternion = object.rotationQuaternion;
if (!quaternion) {
return;
}
//is shape is a plane or a heightmap, it must be rotated 90 degs in the X axis.
if (impostor.type === BABYLON.PhysicsImpostor.PlaneImpostor || impostor.type === BABYLON.PhysicsImpostor.HeightmapImpostor || impostor.type === BABYLON.PhysicsImpostor.CylinderImpostor) {
//-90 DEG in X, precalculated
quaternion = quaternion.multiply(this._minus90X);
//Invert! (Precalculated, 90 deg in X)
//No need to clone. this will never change.
impostor.setDeltaRotation(this._plus90X);
}
//If it is a heightfield, if should be centered.
if (impostor.type === BABYLON.PhysicsImpostor.HeightmapImpostor) {
var mesh = object;
var boundingInfo = mesh.getBoundingInfo();
//calculate the correct body position:
var rotationQuaternion = mesh.rotationQuaternion;
mesh.rotationQuaternion = this._tmpUnityRotation;
mesh.computeWorldMatrix(true);
//get original center with no rotation
var c = center.clone();
var oldPivot = mesh.getPivotMatrix() || BABYLON.Matrix.Translation(0, 0, 0);
//calculate the new center using a pivot (since this.BJSCANNON.js doesn't center height maps)
var p = BABYLON.Matrix.Translation(boundingInfo.boundingBox.extendSizeWorld.x, 0, -boundingInfo.boundingBox.extendSizeWorld.z);
mesh.setPreTransformMatrix(p);
mesh.computeWorldMatrix(true);
//calculate the translation
var translation = boundingInfo.boundingBox.centerWorld.subtract(center).subtract(mesh.position).negate();
this._tmpPosition.copyFromFloats(translation.x, translation.y - boundingInfo.boundingBox.extendSizeWorld.y, translation.z);
//add it inverted to the delta
this._tmpDeltaPosition.copyFrom(boundingInfo.boundingBox.centerWorld.subtract(c));
this._tmpDeltaPosition.y += boundingInfo.boundingBox.extendSizeWorld.y;
//rotation is back
mesh.rotationQuaternion = rotationQuaternion;
mesh.setPreTransformMatrix(oldPivot);
mesh.computeWorldMatrix(true);
}
else if (impostor.type === BABYLON.PhysicsImpostor.MeshImpostor) {
this._tmpDeltaPosition.copyFromFloats(0, 0, 0);
//this._tmpPosition.copyFrom(object.position);
}
impostor.setDeltaPosition(this._tmpDeltaPosition);
//Now update the impostor object
impostor.physicsBody.position.copy(this._tmpPosition);
impostor.physicsBody.quaternion.copy(quaternion);
};
CannonJSPlugin.prototype.setTransformationFromPhysicsBody = function (impostor) {
impostor.object.position.copyFrom(impostor.physicsBody.position);
if (impostor.object.rotationQuaternion) {
impostor.object.rotationQuaternion.copyFrom(impostor.physicsBody.quaternion);
}
};
CannonJSPlugin.prototype.setPhysicsBodyTransformation = function (impostor, newPosition, newRotation) {
impostor.physicsBody.position.copy(newPosition);
impostor.physicsBody.quaternion.copy(newRotation);
};
CannonJSPlugin.prototype.isSupported = function () {
return this.BJSCANNON !== undefined;
};
CannonJSPlugin.prototype.setLinearVelocity = function (impostor, velocity) {
impostor.physicsBody.velocity.copy(velocity);
};
CannonJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
impostor.physicsBody.angularVelocity.copy(velocity);
};
CannonJSPlugin.prototype.getLinearVelocity = function (impostor) {
var v = impostor.physicsBody.velocity;
if (!v) {
return null;
}
return new BABYLON.Vector3(v.x, v.y, v.z);
};
CannonJSPlugin.prototype.getAngularVelocity = function (impostor) {
var v = impostor.physicsBody.angularVelocity;
if (!v) {
return null;
}
return new BABYLON.Vector3(v.x, v.y, v.z);
};
CannonJSPlugin.prototype.setBodyMass = function (impostor, mass) {
impostor.physicsBody.mass = mass;
impostor.physicsBody.updateMassProperties();
};
CannonJSPlugin.prototype.getBodyMass = function (impostor) {
return impostor.physicsBody.mass;
};
CannonJSPlugin.prototype.getBodyFriction = function (impostor) {
return impostor.physicsBody.material.friction;
};
CannonJSPlugin.prototype.setBodyFriction = function (impostor, friction) {
impostor.physicsBody.material.friction = friction;
};
CannonJSPlugin.prototype.getBodyRestitution = function (impostor) {
return impostor.physicsBody.material.restitution;
};
CannonJSPlugin.prototype.setBodyRestitution = function (impostor, restitution) {
impostor.physicsBody.material.restitution = restitution;
};
CannonJSPlugin.prototype.sleepBody = function (impostor) {
impostor.physicsBody.sleep();
};
CannonJSPlugin.prototype.wakeUpBody = function (impostor) {
impostor.physicsBody.wakeUp();
};
CannonJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
joint.physicsJoint.distance = maxDistance;
};
// private enableMotor(joint: IMotorEnabledJoint, motorIndex?: number) {
// if (!motorIndex) {
// joint.physicsJoint.enableMotor();
// }
// }
// private disableMotor(joint: IMotorEnabledJoint, motorIndex?: number) {
// if (!motorIndex) {
// joint.physicsJoint.disableMotor();
// }
// }
CannonJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {
if (!motorIndex) {
joint.physicsJoint.enableMotor();
joint.physicsJoint.setMotorSpeed(speed);
if (maxForce) {
this.setLimit(joint, maxForce);
}
}
};
CannonJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit) {
joint.physicsJoint.motorEquation.maxForce = upperLimit;
joint.physicsJoint.motorEquation.minForce = lowerLimit === void 0 ? -upperLimit : lowerLimit;
};
CannonJSPlugin.prototype.syncMeshWithImpostor = function (mesh, impostor) {
var body = impostor.physicsBody;
mesh.position.x = body.position.x;
mesh.position.y = body.position.y;
mesh.position.z = body.position.z;
if (mesh.rotationQuaternion) {
mesh.rotationQuaternion.x = body.quaternion.x;
mesh.rotationQuaternion.y = body.quaternion.y;
mesh.rotationQuaternion.z = body.quaternion.z;
mesh.rotationQuaternion.w = body.quaternion.w;
}
};
CannonJSPlugin.prototype.getRadius = function (impostor) {
var shape = impostor.physicsBody.shapes[0];
return shape.boundingSphereRadius;
};
CannonJSPlugin.prototype.getBoxSizeToRef = function (impostor, result) {
var shape = impostor.physicsBody.shapes[0];
result.x = shape.halfExtents.x * 2;
result.y = shape.halfExtents.y * 2;
result.z = shape.halfExtents.z * 2;
};
CannonJSPlugin.prototype.dispose = function () {
};
CannonJSPlugin.prototype._extendNamespace = function () {
//this will force cannon to execute at least one step when using interpolation
var step_tmp1 = new this.BJSCANNON.Vec3();
var Engine = this.BJSCANNON;
this.BJSCANNON.World.prototype.step = function (dt, timeSinceLastCalled, maxSubSteps) {
maxSubSteps = maxSubSteps || 10;
timeSinceLastCalled = timeSinceLastCalled || 0;
if (timeSinceLastCalled === 0) {
this.internalStep(dt);
this.time += dt;
}
else {
var internalSteps = Math.floor((this.time + timeSinceLastCalled) / dt) - Math.floor(this.time / dt);
internalSteps = Math.min(internalSteps, maxSubSteps) || 1;
var t0 = performance.now();
for (var i = 0; i !== internalSteps; i++) {
this.internalStep(dt);
if (performance.now() - t0 > dt * 1000) {
break;
}
}
this.time += timeSinceLastCalled;
var h = this.time % dt;
var h_div_dt = h / dt;
var interpvelo = step_tmp1;
var bodies = this.bodies;
for (var j = 0; j !== bodies.length; j++) {
var b = bodies[j];
if (b.type !== Engine.Body.STATIC && b.sleepState !== Engine.Body.SLEEPING) {
b.position.vsub(b.previousPosition, interpvelo);
interpvelo.scale(h_div_dt, interpvelo);
b.position.vadd(interpvelo, b.interpolatedPosition);
}
else {
b.interpolatedPosition.copy(b.position);
b.interpolatedQuaternion.copy(b.quaternion);
}
}
}
};
};
return CannonJSPlugin;
}());
BABYLON.CannonJSPlugin = CannonJSPlugin;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.cannonJSPlugin.js.map
var BABYLON;
(function (BABYLON) {
var OimoJSPlugin = /** @class */ (function () {
function OimoJSPlugin(iterations) {
this.name = "OimoJSPlugin";
this._tmpImpostorsArray = [];
this._tmpPositionVector = BABYLON.Vector3.Zero();
this.BJSOIMO = OIMO;
this.world = new this.BJSOIMO.World({
iterations: iterations
});
this.world.clear();
}
OimoJSPlugin.prototype.setGravity = function (gravity) {
this.world.gravity.copy(gravity);
};
OimoJSPlugin.prototype.setTimeStep = function (timeStep) {
this.world.timeStep = timeStep;
};
OimoJSPlugin.prototype.getTimeStep = function () {
return this.world.timeStep;
};
OimoJSPlugin.prototype.executeStep = function (delta, impostors) {
var _this = this;
impostors.forEach(function (impostor) {
impostor.beforeStep();
});
this.world.step();
impostors.forEach(function (impostor) {
impostor.afterStep();
//update the ordered impostors array
_this._tmpImpostorsArray[impostor.uniqueId] = impostor;
});
//check for collisions
var contact = this.world.contacts;
while (contact !== null) {
if (contact.touching && !contact.body1.sleeping && !contact.body2.sleeping) {
contact = contact.next;
continue;
}
//is this body colliding with any other? get the impostor
var mainImpostor = this._tmpImpostorsArray[+contact.body1.name];
var collidingImpostor = this._tmpImpostorsArray[+contact.body2.name];
if (!mainImpostor || !collidingImpostor) {
contact = contact.next;
continue;
}
mainImpostor.onCollide({ body: collidingImpostor.physicsBody });
collidingImpostor.onCollide({ body: mainImpostor.physicsBody });
contact = contact.next;
}
};
OimoJSPlugin.prototype.applyImpulse = function (impostor, force, contactPoint) {
var mass = impostor.physicsBody.mass;
impostor.physicsBody.applyImpulse(contactPoint.scale(this.world.invScale), force.scale(this.world.invScale * mass));
};
OimoJSPlugin.prototype.applyForce = function (impostor, force, contactPoint) {
BABYLON.Tools.Warn("Oimo doesn't support applying force. Using impule instead.");
this.applyImpulse(impostor, force, contactPoint);
};
OimoJSPlugin.prototype.generatePhysicsBody = function (impostor) {
var _this = this;
//parent-child relationship. Does this impostor has a parent impostor?
if (impostor.parent) {
if (impostor.physicsBody) {
this.removePhysicsBody(impostor);
//TODO is that needed?
impostor.forceUpdate();
}
return;
}
if (impostor.isBodyInitRequired()) {
var bodyConfig = {
name: impostor.uniqueId,
//Oimo must have mass, also for static objects.
config: [impostor.getParam("mass") || 1, impostor.getParam("friction"), impostor.getParam("restitution")],
size: [],
type: [],
pos: [],
posShape: [],
rot: [],
rotShape: [],
move: impostor.getParam("mass") !== 0,
density: impostor.getParam("mass"),
friction: impostor.getParam("friction"),
restitution: impostor.getParam("restitution"),
//Supporting older versions of Oimo
world: this.world
};
var impostors = [impostor];
var addToArray = function (parent) {
if (!parent.getChildMeshes)
return;
parent.getChildMeshes().forEach(function (m) {
if (m.physicsImpostor) {
impostors.push(m.physicsImpostor);
//m.physicsImpostor._init();
}
});
};
addToArray(impostor.object);
var checkWithEpsilon_1 = function (value) {
return Math.max(value, BABYLON.PhysicsEngine.Epsilon);
};
impostors.forEach(function (i) {
if (!i.object.rotationQuaternion) {
return;
}
//get the correct bounding box
var oldQuaternion = i.object.rotationQuaternion;
var rot = oldQuaternion.toEulerAngles();
var extendSize = i.getObjectExtendSize();
var radToDeg = 57.295779513082320876;
if (i === impostor) {
var center = impostor.getObjectCenter();
impostor.object.getAbsolutePivotPoint().subtractToRef(center, _this._tmpPositionVector);
_this._tmpPositionVector.divideInPlace(impostor.object.scaling);
//Can also use Array.prototype.push.apply
bodyConfig.pos.push(center.x);
bodyConfig.pos.push(center.y);
bodyConfig.pos.push(center.z);
bodyConfig.posShape.push(0, 0, 0);
//tmp solution
bodyConfig.rot.push(rot.x * radToDeg);
bodyConfig.rot.push(rot.y * radToDeg);
bodyConfig.rot.push(rot.z * radToDeg);
bodyConfig.rotShape.push(0, 0, 0);
}
else {
var localPosition = i.object.getAbsolutePosition().subtract(impostor.object.getAbsolutePosition());
bodyConfig.posShape.push(localPosition.x);
bodyConfig.posShape.push(localPosition.y);
bodyConfig.posShape.push(localPosition.z);
bodyConfig.pos.push(0, 0, 0);
//tmp solution until https://github.com/lo-th/OIMO.js/pull/37 is merged
bodyConfig.rot.push(0);
bodyConfig.rot.push(0);
bodyConfig.rot.push(0);
bodyConfig.rotShape.push(rot.x * radToDeg);
bodyConfig.rotShape.push(rot.y * radToDeg);
bodyConfig.rotShape.push(rot.z * radToDeg);
}
// register mesh
switch (i.type) {
case BABYLON.PhysicsImpostor.ParticleImpostor:
BABYLON.Tools.Warn("No Particle support in OIMO.js. using SphereImpostor instead");
case BABYLON.PhysicsImpostor.SphereImpostor:
var radiusX = extendSize.x;
var radiusY = extendSize.y;
var radiusZ = extendSize.z;
var size = Math.max(checkWithEpsilon_1(radiusX), checkWithEpsilon_1(radiusY), checkWithEpsilon_1(radiusZ)) / 2;
bodyConfig.type.push('sphere');
//due to the way oimo works with compounds, add 3 times
bodyConfig.size.push(size);
bodyConfig.size.push(size);
bodyConfig.size.push(size);
break;
case BABYLON.PhysicsImpostor.CylinderImpostor:
var sizeX = checkWithEpsilon_1(extendSize.x) / 2;
var sizeY = checkWithEpsilon_1(extendSize.y);
bodyConfig.type.push('cylinder');
bodyConfig.size.push(sizeX);
bodyConfig.size.push(sizeY);
//due to the way oimo works with compounds, add one more value.
bodyConfig.size.push(sizeY);
break;
case BABYLON.PhysicsImpostor.PlaneImpostor:
case BABYLON.PhysicsImpostor.BoxImpostor:
default:
var sizeX = checkWithEpsilon_1(extendSize.x);
var sizeY = checkWithEpsilon_1(extendSize.y);
var sizeZ = checkWithEpsilon_1(extendSize.z);
bodyConfig.type.push('box');
//if (i === impostor) {
bodyConfig.size.push(sizeX);
bodyConfig.size.push(sizeY);
bodyConfig.size.push(sizeZ);
//} else {
// bodyConfig.size.push(0,0,0);
//}
break;
}
//actually not needed, but hey...
i.object.rotationQuaternion = oldQuaternion;
});
impostor.physicsBody = this.world.add(bodyConfig);
}
else {
this._tmpPositionVector.copyFromFloats(0, 0, 0);
}
impostor.setDeltaPosition(this._tmpPositionVector);
//this._tmpPositionVector.addInPlace(impostor.mesh.getBoundingInfo().boundingBox.center);
//this.setPhysicsBodyTransformation(impostor, this._tmpPositionVector, impostor.mesh.rotationQuaternion);
};
OimoJSPlugin.prototype.removePhysicsBody = function (impostor) {
//impostor.physicsBody.dispose();
//Same as : (older oimo versions)
this.world.removeRigidBody(impostor.physicsBody);
};
OimoJSPlugin.prototype.generateJoint = function (impostorJoint) {
var mainBody = impostorJoint.mainImpostor.physicsBody;
var connectedBody = impostorJoint.connectedImpostor.physicsBody;
if (!mainBody || !connectedBody) {
return;
}
var jointData = impostorJoint.joint.jointData;
var options = jointData.nativeParams || {};
var type;
var nativeJointData = {
body1: mainBody,
body2: connectedBody,
axe1: options.axe1 || (jointData.mainAxis ? jointData.mainAxis.asArray() : null),
axe2: options.axe2 || (jointData.connectedAxis ? jointData.connectedAxis.asArray() : null),
pos1: options.pos1 || (jointData.mainPivot ? jointData.mainPivot.asArray() : null),
pos2: options.pos2 || (jointData.connectedPivot ? jointData.connectedPivot.asArray() : null),
min: options.min,
max: options.max,
collision: options.collision || jointData.collision,
spring: options.spring,
//supporting older version of Oimo
world: this.world
};
switch (impostorJoint.joint.type) {
case BABYLON.PhysicsJoint.BallAndSocketJoint:
type = "jointBall";
break;
case BABYLON.PhysicsJoint.SpringJoint:
BABYLON.Tools.Warn("OIMO.js doesn't support Spring Constraint. Simulating using DistanceJoint instead");
var springData = jointData;
nativeJointData.min = springData.length || nativeJointData.min;
//Max should also be set, just make sure it is at least min
nativeJointData.max = Math.max(nativeJointData.min, nativeJointData.max);
case BABYLON.PhysicsJoint.DistanceJoint:
type = "jointDistance";
nativeJointData.max = jointData.maxDistance;
break;
case BABYLON.PhysicsJoint.PrismaticJoint:
type = "jointPrisme";
break;
case BABYLON.PhysicsJoint.SliderJoint:
type = "jointSlide";
break;
case BABYLON.PhysicsJoint.WheelJoint:
type = "jointWheel";
break;
case BABYLON.PhysicsJoint.HingeJoint:
default:
type = "jointHinge";
break;
}
nativeJointData.type = type;
impostorJoint.joint.physicsJoint = this.world.add(nativeJointData);
};
OimoJSPlugin.prototype.removeJoint = function (impostorJoint) {
//Bug in Oimo prevents us from disposing a joint in the playground
//joint.joint.physicsJoint.dispose();
//So we will bruteforce it!
try {
this.world.removeJoint(impostorJoint.joint.physicsJoint);
}
catch (e) {
BABYLON.Tools.Warn(e);
}
};
OimoJSPlugin.prototype.isSupported = function () {
return this.BJSOIMO !== undefined;
};
OimoJSPlugin.prototype.setTransformationFromPhysicsBody = function (impostor) {
if (!impostor.physicsBody.sleeping) {
//TODO check that
/*if (impostor.physicsBody.shapes.next) {
var parentShape = this._getLastShape(impostor.physicsBody);
impostor.object.position.copyFrom(parentShape.position);
console.log(parentShape.position);
} else {*/
impostor.object.position.copyFrom(impostor.physicsBody.getPosition());
//}
if (impostor.object.rotationQuaternion) {
impostor.object.rotationQuaternion.copyFrom(impostor.physicsBody.getQuaternion());
}
}
};
OimoJSPlugin.prototype.setPhysicsBodyTransformation = function (impostor, newPosition, newRotation) {
var body = impostor.physicsBody;
body.position.copy(newPosition);
body.orientation.copy(newRotation);
body.syncShapes();
body.awake();
};
/*private _getLastShape(body: any): any {
var lastShape = body.shapes;
while (lastShape.next) {
lastShape = lastShape.next;
}
return lastShape;
}*/
OimoJSPlugin.prototype.setLinearVelocity = function (impostor, velocity) {
impostor.physicsBody.linearVelocity.init(velocity.x, velocity.y, velocity.z);
};
OimoJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
impostor.physicsBody.angularVelocity.init(velocity.x, velocity.y, velocity.z);
};
OimoJSPlugin.prototype.getLinearVelocity = function (impostor) {
var v = impostor.physicsBody.linearVelocity;
if (!v) {
return null;
}
return new BABYLON.Vector3(v.x, v.y, v.z);
};
OimoJSPlugin.prototype.getAngularVelocity = function (impostor) {
var v = impostor.physicsBody.angularVelocity;
if (!v) {
return null;
}
return new BABYLON.Vector3(v.x, v.y, v.z);
};
OimoJSPlugin.prototype.setBodyMass = function (impostor, mass) {
var staticBody = mass === 0;
//this will actually set the body's density and not its mass.
//But this is how oimo treats the mass variable.
impostor.physicsBody.shapes.density = staticBody ? 1 : mass;
impostor.physicsBody.setupMass(staticBody ? 0x2 : 0x1);
};
OimoJSPlugin.prototype.getBodyMass = function (impostor) {
return impostor.physicsBody.shapes.density;
};
OimoJSPlugin.prototype.getBodyFriction = function (impostor) {
return impostor.physicsBody.shapes.friction;
};
OimoJSPlugin.prototype.setBodyFriction = function (impostor, friction) {
impostor.physicsBody.shapes.friction = friction;
};
OimoJSPlugin.prototype.getBodyRestitution = function (impostor) {
return impostor.physicsBody.shapes.restitution;
};
OimoJSPlugin.prototype.setBodyRestitution = function (impostor, restitution) {
impostor.physicsBody.shapes.restitution = restitution;
};
OimoJSPlugin.prototype.sleepBody = function (impostor) {
impostor.physicsBody.sleep();
};
OimoJSPlugin.prototype.wakeUpBody = function (impostor) {
impostor.physicsBody.awake();
};
OimoJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
joint.physicsJoint.limitMotor.upperLimit = maxDistance;
if (minDistance !== void 0) {
joint.physicsJoint.limitMotor.lowerLimit = minDistance;
}
};
OimoJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {
//TODO separate rotational and transational motors.
var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor1 || joint.physicsJoint.rotationalLimitMotor || joint.physicsJoint.limitMotor;
if (motor) {
motor.setMotor(speed, maxForce);
}
};
OimoJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit, motorIndex) {
//TODO separate rotational and transational motors.
var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor1 || joint.physicsJoint.rotationalLimitMotor || joint.physicsJoint.limitMotor;
if (motor) {
motor.setLimit(upperLimit, lowerLimit === void 0 ? -upperLimit : lowerLimit);
}
};
OimoJSPlugin.prototype.syncMeshWithImpostor = function (mesh, impostor) {
var body = impostor.physicsBody;
mesh.position.x = body.position.x;
mesh.position.y = body.position.y;
mesh.position.z = body.position.z;
if (mesh.rotationQuaternion) {
mesh.rotationQuaternion.x = body.orientation.x;
mesh.rotationQuaternion.y = body.orientation.y;
mesh.rotationQuaternion.z = body.orientation.z;
mesh.rotationQuaternion.w = body.orientation.s;
}
};
OimoJSPlugin.prototype.getRadius = function (impostor) {
return impostor.physicsBody.shapes.radius;
};
OimoJSPlugin.prototype.getBoxSizeToRef = function (impostor, result) {
var shape = impostor.physicsBody.shapes;
result.x = shape.halfWidth * 2;
result.y = shape.halfHeight * 2;
result.z = shape.halfDepth * 2;
};
OimoJSPlugin.prototype.dispose = function () {
this.world.clear();
};
return OimoJSPlugin;
}());
BABYLON.OimoJSPlugin = OimoJSPlugin;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.oimoJSPlugin.js.map
var BABYLON;
(function (BABYLON) {
/*
* Based on jsTGALoader - Javascript loader for TGA file
* By Vincent Thibault
* @blog http://blog.robrowser.com/javascript-tga-loader.html
*/
var TGATools = /** @class */ (function () {
function TGATools() {
}
TGATools.GetTGAHeader = function (data) {
var offset = 0;
var header = {
id_length: data[offset++],
colormap_type: data[offset++],
image_type: data[offset++],
colormap_index: data[offset++] | data[offset++] << 8,
colormap_length: data[offset++] | data[offset++] << 8,
colormap_size: data[offset++],
origin: [
data[offset++] | data[offset++] << 8,
data[offset++] | data[offset++] << 8
],
width: data[offset++] | data[offset++] << 8,
height: data[offset++] | data[offset++] << 8,
pixel_size: data[offset++],
flags: data[offset++]
};
return header;
};
TGATools.UploadContent = function (gl, data) {
// Not enough data to contain header ?
if (data.length < 19) {
BABYLON.Tools.Error("Unable to load TGA file - Not enough data to contain header");
return;
}
// Read Header
var offset = 18;
var header = TGATools.GetTGAHeader(data);
// Assume it's a valid Targa file.
if (header.id_length + offset > data.length) {
BABYLON.Tools.Error("Unable to load TGA file - Not enough data");
return;
}
// Skip not needed data
offset += header.id_length;
var use_rle = false;
var use_pal = false;
var use_grey = false;
// Get some informations.
switch (header.image_type) {
case TGATools._TYPE_RLE_INDEXED:
use_rle = true;
case TGATools._TYPE_INDEXED:
use_pal = true;
break;
case TGATools._TYPE_RLE_RGB:
use_rle = true;
case TGATools._TYPE_RGB:
// use_rgb = true;
break;
case TGATools._TYPE_RLE_GREY:
use_rle = true;
case TGATools._TYPE_GREY:
use_grey = true;
break;
}
var pixel_data;
// var numAlphaBits = header.flags & 0xf;
var pixel_size = header.pixel_size >> 3;
var pixel_total = header.width * header.height * pixel_size;
// Read palettes
var palettes;
if (use_pal) {
palettes = data.subarray(offset, offset += header.colormap_length * (header.colormap_size >> 3));
}
// Read LRE
if (use_rle) {
pixel_data = new Uint8Array(pixel_total);
var c, count, i;
var localOffset = 0;
var pixels = new Uint8Array(pixel_size);
while (offset < pixel_total && localOffset < pixel_total) {
c = data[offset++];
count = (c & 0x7f) + 1;
// RLE pixels
if (c & 0x80) {
// Bind pixel tmp array
for (i = 0; i < pixel_size; ++i) {
pixels[i] = data[offset++];
}
// Copy pixel array
for (i = 0; i < count; ++i) {
pixel_data.set(pixels, localOffset + i * pixel_size);
}
localOffset += pixel_size * count;
}
// Raw pixels
else {
count *= pixel_size;
for (i = 0; i < count; ++i) {
pixel_data[localOffset + i] = data[offset++];
}
localOffset += count;
}
}
}
// RAW Pixels
else {
pixel_data = data.subarray(offset, offset += (use_pal ? header.width * header.height : pixel_total));
}
// Load to texture
var x_start, y_start, x_step, y_step, y_end, x_end;
switch ((header.flags & TGATools._ORIGIN_MASK) >> TGATools._ORIGIN_SHIFT) {
default:
case TGATools._ORIGIN_UL:
x_start = 0;
x_step = 1;
x_end = header.width;
y_start = 0;
y_step = 1;
y_end = header.height;
break;
case TGATools._ORIGIN_BL:
x_start = 0;
x_step = 1;
x_end = header.width;
y_start = header.height - 1;
y_step = -1;
y_end = -1;
break;
case TGATools._ORIGIN_UR:
x_start = header.width - 1;
x_step = -1;
x_end = -1;
y_start = 0;
y_step = 1;
y_end = header.height;
break;
case TGATools._ORIGIN_BR:
x_start = header.width - 1;
x_step = -1;
x_end = -1;
y_start = header.height - 1;
y_step = -1;
y_end = -1;
break;
}
// Load the specify method
var func = '_getImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits';
var imageData = TGATools[func](header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, header.width, header.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
};
TGATools._getImageData8bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data, colormap = palettes;
var width = header.width, height = header.height;
var color, i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i++) {
color = image[i];
imageData[(x + width * y) * 4 + 3] = 255;
imageData[(x + width * y) * 4 + 2] = colormap[(color * 3) + 0];
imageData[(x + width * y) * 4 + 1] = colormap[(color * 3) + 1];
imageData[(x + width * y) * 4 + 0] = colormap[(color * 3) + 2];
}
}
return imageData;
};
TGATools._getImageData16bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var color, i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i += 2) {
color = image[i + 0] + (image[i + 1] << 8); // Inversed ?
var r = (((color & 0x7C00) >> 10) * 255) / 0x1F | 0;
var g = (((color & 0x03E0) >> 5) * 255) / 0x1F | 0;
var b = ((color & 0x001F) * 255) / 0x1F | 0;
imageData[(x + width * y) * 4 + 0] = r;
imageData[(x + width * y) * 4 + 1] = g;
imageData[(x + width * y) * 4 + 2] = b;
imageData[(x + width * y) * 4 + 3] = (color & 0x8000) ? 0 : 255;
}
}
return imageData;
};
TGATools._getImageData24bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i += 3) {
imageData[(x + width * y) * 4 + 3] = 255;
imageData[(x + width * y) * 4 + 2] = image[i + 0];
imageData[(x + width * y) * 4 + 1] = image[i + 1];
imageData[(x + width * y) * 4 + 0] = image[i + 2];
}
}
return imageData;
};
TGATools._getImageData32bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i += 4) {
imageData[(x + width * y) * 4 + 2] = image[i + 0];
imageData[(x + width * y) * 4 + 1] = image[i + 1];
imageData[(x + width * y) * 4 + 0] = image[i + 2];
imageData[(x + width * y) * 4 + 3] = image[i + 3];
}
}
return imageData;
};
TGATools._getImageDataGrey8bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var color, i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i++) {
color = image[i];
imageData[(x + width * y) * 4 + 0] = color;
imageData[(x + width * y) * 4 + 1] = color;
imageData[(x + width * y) * 4 + 2] = color;
imageData[(x + width * y) * 4 + 3] = 255;
}
}
return imageData;
};
TGATools._getImageDataGrey16bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i += 2) {
imageData[(x + width * y) * 4 + 0] = image[i + 0];
imageData[(x + width * y) * 4 + 1] = image[i + 0];
imageData[(x + width * y) * 4 + 2] = image[i + 0];
imageData[(x + width * y) * 4 + 3] = image[i + 1];
}
}
return imageData;
};
//private static _TYPE_NO_DATA = 0;
TGATools._TYPE_INDEXED = 1;
TGATools._TYPE_RGB = 2;
TGATools._TYPE_GREY = 3;
TGATools._TYPE_RLE_INDEXED = 9;
TGATools._TYPE_RLE_RGB = 10;
TGATools._TYPE_RLE_GREY = 11;
TGATools._ORIGIN_MASK = 0x30;
TGATools._ORIGIN_SHIFT = 0x04;
TGATools._ORIGIN_BL = 0x00;
TGATools._ORIGIN_BR = 0x01;
TGATools._ORIGIN_UL = 0x02;
TGATools._ORIGIN_UR = 0x03;
return TGATools;
}());
BABYLON.TGATools = TGATools;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.tga.js.map
var BABYLON;
(function (BABYLON) {
// Based on demo done by Brandon Jones - http://media.tojicode.com/webgl-samples/dds.html
// All values and structures referenced from:
// http://msdn.microsoft.com/en-us/library/bb943991.aspx/
var DDS_MAGIC = 0x20534444;
var
//DDSD_CAPS = 0x1,
//DDSD_HEIGHT = 0x2,
//DDSD_WIDTH = 0x4,
//DDSD_PITCH = 0x8,
//DDSD_PIXELFORMAT = 0x1000,
DDSD_MIPMAPCOUNT = 0x20000;
//DDSD_LINEARSIZE = 0x80000,
//DDSD_DEPTH = 0x800000;
// var DDSCAPS_COMPLEX = 0x8,
// DDSCAPS_MIPMAP = 0x400000,
// DDSCAPS_TEXTURE = 0x1000;
var DDSCAPS2_CUBEMAP = 0x200;
// DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
// DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
// DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
// DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
// DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
// DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
// DDSCAPS2_VOLUME = 0x200000;
var
//DDPF_ALPHAPIXELS = 0x1,
//DDPF_ALPHA = 0x2,
DDPF_FOURCC = 0x4, DDPF_RGB = 0x40,
//DDPF_YUV = 0x200,
DDPF_LUMINANCE = 0x20000;
function FourCCToInt32(value) {
return value.charCodeAt(0) +
(value.charCodeAt(1) << 8) +
(value.charCodeAt(2) << 16) +
(value.charCodeAt(3) << 24);
}
function Int32ToFourCC(value) {
return String.fromCharCode(value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, (value >> 24) & 0xff);
}
var FOURCC_DXT1 = FourCCToInt32("DXT1");
var FOURCC_DXT3 = FourCCToInt32("DXT3");
var FOURCC_DXT5 = FourCCToInt32("DXT5");
var FOURCC_DX10 = FourCCToInt32("DX10");
var FOURCC_D3DFMT_R16G16B16A16F = 113;
var FOURCC_D3DFMT_R32G32B32A32F = 116;
var DXGI_FORMAT_R16G16B16A16_FLOAT = 10;
var DXGI_FORMAT_B8G8R8X8_UNORM = 88;
var headerLengthInt = 31; // The header length in 32 bit ints
// Offsets into the header array
var off_magic = 0;
var off_size = 1;
var off_flags = 2;
var off_height = 3;
var off_width = 4;
var off_mipmapCount = 7;
var off_pfFlags = 20;
var off_pfFourCC = 21;
var off_RGBbpp = 22;
var off_RMask = 23;
var off_GMask = 24;
var off_BMask = 25;
var off_AMask = 26;
// var off_caps1 = 27;
var off_caps2 = 28;
// var off_caps3 = 29;
// var off_caps4 = 30;
var off_dxgiFormat = 32;
;
var DDSTools = /** @class */ (function () {
function DDSTools() {
}
DDSTools.GetDDSInfo = function (arrayBuffer) {
var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
var extendedHeader = new Int32Array(arrayBuffer, 0, headerLengthInt + 4);
var mipmapCount = 1;
if (header[off_flags] & DDSD_MIPMAPCOUNT) {
mipmapCount = Math.max(1, header[off_mipmapCount]);
}
var fourCC = header[off_pfFourCC];
var dxgiFormat = (fourCC === FOURCC_DX10) ? extendedHeader[off_dxgiFormat] : 0;
var textureType = BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
switch (fourCC) {
case FOURCC_D3DFMT_R16G16B16A16F:
textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
break;
case FOURCC_D3DFMT_R32G32B32A32F:
textureType = BABYLON.Engine.TEXTURETYPE_FLOAT;
break;
case FOURCC_DX10:
if (dxgiFormat === DXGI_FORMAT_R16G16B16A16_FLOAT) {
textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
break;
}
}
return {
width: header[off_width],
height: header[off_height],
mipmapCount: mipmapCount,
isFourCC: (header[off_pfFlags] & DDPF_FOURCC) === DDPF_FOURCC,
isRGB: (header[off_pfFlags] & DDPF_RGB) === DDPF_RGB,
isLuminance: (header[off_pfFlags] & DDPF_LUMINANCE) === DDPF_LUMINANCE,
isCube: (header[off_caps2] & DDSCAPS2_CUBEMAP) === DDSCAPS2_CUBEMAP,
isCompressed: (fourCC === FOURCC_DXT1 || fourCC === FOURCC_DXT3 || fourCC === FOURCC_DXT5),
dxgiFormat: dxgiFormat,
textureType: textureType
};
};
DDSTools._ToHalfFloat = function (value) {
if (!DDSTools._FloatView) {
DDSTools._FloatView = new Float32Array(1);
DDSTools._Int32View = new Int32Array(DDSTools._FloatView.buffer);
}
DDSTools._FloatView[0] = value;
var x = DDSTools._Int32View[0];
var bits = (x >> 16) & 0x8000; /* Get the sign */
var m = (x >> 12) & 0x07ff; /* Keep one extra bit for rounding */
var e = (x >> 23) & 0xff; /* Using int is faster here */
/* If zero, or denormal, or exponent underflows too much for a denormal
* half, return signed zero. */
if (e < 103) {
return bits;
}
/* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
if (e > 142) {
bits |= 0x7c00;
/* If exponent was 0xff and one mantissa bit was set, it means NaN,
* not Inf, so make sure we set one mantissa bit too. */
bits |= ((e == 255) ? 0 : 1) && (x & 0x007fffff);
return bits;
}
/* If exponent underflows but not too much, return a denormal */
if (e < 113) {
m |= 0x0800;
/* Extra rounding may overflow and set mantissa to 0 and exponent
* to 1, which is OK. */
bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1);
return bits;
}
bits |= ((e - 112) << 10) | (m >> 1);
bits += m & 1;
return bits;
};
DDSTools._FromHalfFloat = function (value) {
var s = (value & 0x8000) >> 15;
var e = (value & 0x7C00) >> 10;
var f = value & 0x03FF;
if (e === 0) {
return (s ? -1 : 1) * Math.pow(2, -14) * (f / Math.pow(2, 10));
}
else if (e == 0x1F) {
return f ? NaN : ((s ? -1 : 1) * Infinity);
}
return (s ? -1 : 1) * Math.pow(2, e - 15) * (1 + (f / Math.pow(2, 10)));
};
DDSTools._GetHalfFloatAsFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
var destArray = new Float32Array(dataLength);
var srcData = new Uint16Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = DDSTools._FromHalfFloat(srcData[srcPos]);
destArray[index + 1] = DDSTools._FromHalfFloat(srcData[srcPos + 1]);
destArray[index + 2] = DDSTools._FromHalfFloat(srcData[srcPos + 2]);
if (DDSTools.StoreLODInAlphaChannel) {
destArray[index + 3] = lod;
}
else {
destArray[index + 3] = DDSTools._FromHalfFloat(srcData[srcPos + 3]);
}
index += 4;
}
}
return destArray;
};
DDSTools._GetHalfFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
if (DDSTools.StoreLODInAlphaChannel) {
var destArray = new Uint16Array(dataLength);
var srcData = new Uint16Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = srcData[srcPos];
destArray[index + 1] = srcData[srcPos + 1];
destArray[index + 2] = srcData[srcPos + 2];
destArray[index + 3] = DDSTools._ToHalfFloat(lod);
index += 4;
}
}
return destArray;
}
return new Uint16Array(arrayBuffer, dataOffset, dataLength);
};
DDSTools._GetFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
if (DDSTools.StoreLODInAlphaChannel) {
var destArray = new Float32Array(dataLength);
var srcData = new Float32Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = srcData[srcPos];
destArray[index + 1] = srcData[srcPos + 1];
destArray[index + 2] = srcData[srcPos + 2];
destArray[index + 3] = lod;
index += 4;
}
}
return destArray;
}
return new Float32Array(arrayBuffer, dataOffset, dataLength);
};
DDSTools._GetFloatAsUIntRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
var destArray = new Uint8Array(dataLength);
var srcData = new Float32Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = BABYLON.Scalar.Clamp(srcData[srcPos]) * 255;
destArray[index + 1] = BABYLON.Scalar.Clamp(srcData[srcPos + 1]) * 255;
destArray[index + 2] = BABYLON.Scalar.Clamp(srcData[srcPos + 2]) * 255;
if (DDSTools.StoreLODInAlphaChannel) {
destArray[index + 3] = lod;
}
else {
destArray[index + 3] = BABYLON.Scalar.Clamp(srcData[srcPos + 3]) * 255;
}
index += 4;
}
}
return destArray;
};
DDSTools._GetHalfFloatAsUIntRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
var destArray = new Uint8Array(dataLength);
var srcData = new Uint16Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = BABYLON.Scalar.Clamp(DDSTools._FromHalfFloat(srcData[srcPos])) * 255;
destArray[index + 1] = BABYLON.Scalar.Clamp(DDSTools._FromHalfFloat(srcData[srcPos + 1])) * 255;
destArray[index + 2] = BABYLON.Scalar.Clamp(DDSTools._FromHalfFloat(srcData[srcPos + 2])) * 255;
if (DDSTools.StoreLODInAlphaChannel) {
destArray[index + 3] = lod;
}
else {
destArray[index + 3] = BABYLON.Scalar.Clamp(DDSTools._FromHalfFloat(srcData[srcPos + 3])) * 255;
}
index += 4;
}
}
return destArray;
};
DDSTools._GetRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset, aOffset) {
var byteArray = new Uint8Array(dataLength);
var srcData = new Uint8Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
byteArray[index] = srcData[srcPos + rOffset];
byteArray[index + 1] = srcData[srcPos + gOffset];
byteArray[index + 2] = srcData[srcPos + bOffset];
byteArray[index + 3] = srcData[srcPos + aOffset];
index += 4;
}
}
return byteArray;
};
DDSTools._ExtractLongWordOrder = function (value) {
if (value === 0 || value === 255 || value === -16777216) {
return 0;
}
return 1 + DDSTools._ExtractLongWordOrder(value >> 8);
};
DDSTools._GetRGBArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset) {
var byteArray = new Uint8Array(dataLength);
var srcData = new Uint8Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 3;
byteArray[index] = srcData[srcPos + rOffset];
byteArray[index + 1] = srcData[srcPos + gOffset];
byteArray[index + 2] = srcData[srcPos + bOffset];
index += 3;
}
}
return byteArray;
};
DDSTools._GetLuminanceArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer) {
var byteArray = new Uint8Array(dataLength);
var srcData = new Uint8Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width);
byteArray[index] = srcData[srcPos];
index++;
}
}
return byteArray;
};
DDSTools.UploadDDSLevels = function (engine, gl, arrayBuffer, info, loadMipmaps, faces, lodIndex, currentFace) {
if (lodIndex === void 0) { lodIndex = -1; }
var sphericalPolynomialFaces = null;
if (info.sphericalPolynomial) {
sphericalPolynomialFaces = new Array();
}
var ext = engine.getCaps().s3tc;
var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
var fourCC, width, height, dataLength = 0, dataOffset;
var byteArray, mipmapCount, mip;
var internalFormat = 0;
var format = 0;
var blockBytes = 1;
if (header[off_magic] !== DDS_MAGIC) {
BABYLON.Tools.Error("Invalid magic number in DDS header");
return;
}
if (!info.isFourCC && !info.isRGB && !info.isLuminance) {
BABYLON.Tools.Error("Unsupported format, must contain a FourCC, RGB or LUMINANCE code");
return;
}
if (info.isCompressed && !ext) {
BABYLON.Tools.Error("Compressed textures are not supported on this platform.");
return;
}
var bpp = header[off_RGBbpp];
dataOffset = header[off_size] + 4;
var computeFormats = false;
if (info.isFourCC) {
fourCC = header[off_pfFourCC];
switch (fourCC) {
case FOURCC_DXT1:
blockBytes = 8;
internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case FOURCC_DXT3:
blockBytes = 16;
internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case FOURCC_DXT5:
blockBytes = 16;
internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
case FOURCC_D3DFMT_R16G16B16A16F:
computeFormats = true;
break;
case FOURCC_D3DFMT_R32G32B32A32F:
computeFormats = true;
break;
case FOURCC_DX10:
// There is an additionnal header so dataOffset need to be changed
dataOffset += 5 * 4; // 5 uints
var supported = false;
switch (info.dxgiFormat) {
case DXGI_FORMAT_R16G16B16A16_FLOAT:
computeFormats = true;
supported = true;
break;
case DXGI_FORMAT_B8G8R8X8_UNORM:
info.isRGB = true;
info.isFourCC = false;
bpp = 32;
supported = true;
break;
}
if (supported) {
break;
}
default:
console.error("Unsupported FourCC code:", Int32ToFourCC(fourCC));
return;
}
}
var rOffset = DDSTools._ExtractLongWordOrder(header[off_RMask]);
var gOffset = DDSTools._ExtractLongWordOrder(header[off_GMask]);
var bOffset = DDSTools._ExtractLongWordOrder(header[off_BMask]);
var aOffset = DDSTools._ExtractLongWordOrder(header[off_AMask]);
if (computeFormats) {
format = engine._getWebGLTextureType(info.textureType);
internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
}
mipmapCount = 1;
if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
mipmapCount = Math.max(1, header[off_mipmapCount]);
}
for (var face = 0; face < faces; face++) {
var sampler = faces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face + (currentFace ? currentFace : 0));
width = header[off_width];
height = header[off_height];
for (mip = 0; mip < mipmapCount; ++mip) {
if (lodIndex === -1 || lodIndex === mip) {
// In case of fixed LOD, if the lod has just been uploaded, early exit.
var i = (lodIndex === -1) ? mip : 0;
if (!info.isCompressed && info.isFourCC) {
dataLength = width * height * 4;
var floatArray = null;
if (engine._badOS || engine._badDesktopOS || (!engine.getCaps().textureHalfFloat && !engine.getCaps().textureFloat)) { // Required because iOS has many issues with float and half float generation
if (bpp === 128) {
floatArray = DDSTools._GetFloatAsUIntRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
if (sphericalPolynomialFaces && i == 0) {
sphericalPolynomialFaces.push(DDSTools._GetFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i));
}
}
else if (bpp === 64) {
floatArray = DDSTools._GetHalfFloatAsUIntRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
if (sphericalPolynomialFaces && i == 0) {
sphericalPolynomialFaces.push(DDSTools._GetHalfFloatAsFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i));
}
}
info.textureType = BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
format = engine._getWebGLTextureType(info.textureType);
internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
}
else {
if (bpp === 128) {
floatArray = DDSTools._GetFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
if (sphericalPolynomialFaces && i == 0) {
sphericalPolynomialFaces.push(floatArray);
}
}
else if (bpp === 64 && !engine.getCaps().textureHalfFloat) {
floatArray = DDSTools._GetHalfFloatAsFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
if (sphericalPolynomialFaces && i == 0) {
sphericalPolynomialFaces.push(floatArray);
}
info.textureType = BABYLON.Engine.TEXTURETYPE_FLOAT;
format = engine._getWebGLTextureType(info.textureType);
internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
}
else { // 64
floatArray = DDSTools._GetHalfFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
if (sphericalPolynomialFaces && i == 0) {
sphericalPolynomialFaces.push(DDSTools._GetHalfFloatAsFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i));
}
}
}
if (floatArray) {
engine._uploadDataToTexture(sampler, i, internalFormat, width, height, gl.RGBA, format, floatArray);
}
}
else if (info.isRGB) {
if (bpp === 24) {
dataLength = width * height * 3;
byteArray = DDSTools._GetRGBArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset);
engine._uploadDataToTexture(sampler, i, gl.RGB, width, height, gl.RGB, gl.UNSIGNED_BYTE, byteArray);
}
else { // 32
dataLength = width * height * 4;
byteArray = DDSTools._GetRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset, aOffset);
engine._uploadDataToTexture(sampler, i, gl.RGBA, width, height, gl.RGBA, gl.UNSIGNED_BYTE, byteArray);
}
}
else if (info.isLuminance) {
var unpackAlignment = gl.getParameter(gl.UNPACK_ALIGNMENT);
var unpaddedRowSize = width;
var paddedRowSize = Math.floor((width + unpackAlignment - 1) / unpackAlignment) * unpackAlignment;
dataLength = paddedRowSize * (height - 1) + unpaddedRowSize;
byteArray = DDSTools._GetLuminanceArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
engine._uploadDataToTexture(sampler, i, gl.LUMINANCE, width, height, gl.LUMINANCE, gl.UNSIGNED_BYTE, byteArray);
}
else {
dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength);
engine._uploadCompressedDataToTexture(sampler, i, internalFormat, width, height, byteArray);
}
}
dataOffset += bpp ? (width * height * (bpp / 8)) : dataLength;
width *= 0.5;
height *= 0.5;
width = Math.max(1.0, width);
height = Math.max(1.0, height);
}
if (currentFace !== undefined) {
// Loading a single face
break;
}
}
if (sphericalPolynomialFaces && sphericalPolynomialFaces.length > 0) {
info.sphericalPolynomial = BABYLON.CubeMapToSphericalPolynomialTools.ConvertCubeMapToSphericalPolynomial({
size: header[off_width],
right: sphericalPolynomialFaces[0],
left: sphericalPolynomialFaces[1],
up: sphericalPolynomialFaces[2],
down: sphericalPolynomialFaces[3],
front: sphericalPolynomialFaces[4],
back: sphericalPolynomialFaces[5],
format: BABYLON.Engine.TEXTUREFORMAT_RGBA,
type: BABYLON.Engine.TEXTURETYPE_FLOAT,
gammaSpace: false,
});
}
else {
info.sphericalPolynomial = undefined;
}
};
DDSTools.StoreLODInAlphaChannel = false;
return DDSTools;
}());
BABYLON.DDSTools = DDSTools;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.dds.js.map
var BABYLON;
(function (BABYLON) {
/**
* for description see https://www.khronos.org/opengles/sdk/tools/KTX/
* for file layout see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
*/
var KhronosTextureContainer = /** @class */ (function () {
/**
* @param {ArrayBuffer} arrayBuffer- contents of the KTX container file
* @param {number} facesExpected- should be either 1 or 6, based whether a cube texture or or
* @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented
* @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented
*/
function KhronosTextureContainer(arrayBuffer, facesExpected, threeDExpected, textureArrayExpected) {
this.arrayBuffer = arrayBuffer;
// Test that it is a ktx formatted file, based on the first 12 bytes, character representation is:
// '�', 'K', 'T', 'X', ' ', '1', '1', '�', '\r', '\n', '\x1A', '\n'
// 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
var identifier = new Uint8Array(this.arrayBuffer, 0, 12);
if (identifier[0] !== 0xAB || identifier[1] !== 0x4B || identifier[2] !== 0x54 || identifier[3] !== 0x58 || identifier[4] !== 0x20 || identifier[5] !== 0x31 ||
identifier[6] !== 0x31 || identifier[7] !== 0xBB || identifier[8] !== 0x0D || identifier[9] !== 0x0A || identifier[10] !== 0x1A || identifier[11] !== 0x0A) {
BABYLON.Tools.Error("texture missing KTX identifier");
return;
}
// load the reset of the header in native 32 bit int
var header = new Int32Array(this.arrayBuffer, 12, 13);
// determine of the remaining header values are recorded in the opposite endianness & require conversion
var oppositeEndianess = header[0] === 0x01020304;
// read all the header elements in order they exist in the file, without modification (sans endainness)
this.glType = oppositeEndianess ? this.switchEndainness(header[1]) : header[1]; // must be 0 for compressed textures
this.glTypeSize = oppositeEndianess ? this.switchEndainness(header[2]) : header[2]; // must be 1 for compressed textures
this.glFormat = oppositeEndianess ? this.switchEndainness(header[3]) : header[3]; // must be 0 for compressed textures
this.glInternalFormat = oppositeEndianess ? this.switchEndainness(header[4]) : header[4]; // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
this.glBaseInternalFormat = oppositeEndianess ? this.switchEndainness(header[5]) : header[5]; // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
this.pixelWidth = oppositeEndianess ? this.switchEndainness(header[6]) : header[6]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
this.pixelHeight = oppositeEndianess ? this.switchEndainness(header[7]) : header[7]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
this.pixelDepth = oppositeEndianess ? this.switchEndainness(header[8]) : header[8]; // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
this.numberOfArrayElements = oppositeEndianess ? this.switchEndainness(header[9]) : header[9]; // used for texture arrays
this.numberOfFaces = oppositeEndianess ? this.switchEndainness(header[10]) : header[10]; // used for cubemap textures, should either be 1 or 6
this.numberOfMipmapLevels = oppositeEndianess ? this.switchEndainness(header[11]) : header[11]; // number of levels; disregard possibility of 0 for compressed textures
this.bytesOfKeyValueData = oppositeEndianess ? this.switchEndainness(header[12]) : header[12]; // the amount of space after the header for meta-data
// Make sure we have a compressed type. Not only reduces work, but probably better to let dev know they are not compressing.
if (this.glType !== 0) {
BABYLON.Tools.Error("only compressed formats currently supported");
return;
}
else {
// value of zero is an indication to generate mipmaps @ runtime. Not usually allowed for compressed, so disregard.
this.numberOfMipmapLevels = Math.max(1, this.numberOfMipmapLevels);
}
if (this.pixelHeight === 0 || this.pixelDepth !== 0) {
BABYLON.Tools.Error("only 2D textures currently supported");
return;
}
if (this.numberOfArrayElements !== 0) {
BABYLON.Tools.Error("texture arrays not currently supported");
return;
}
if (this.numberOfFaces !== facesExpected) {
BABYLON.Tools.Error("number of faces expected" + facesExpected + ", but found " + this.numberOfFaces);
return;
}
// we now have a completely validated file, so could use existence of loadType as success
// would need to make this more elaborate & adjust checks above to support more than one load type
this.loadType = KhronosTextureContainer.COMPRESSED_2D;
}
// not as fast hardware based, but will probably never need to use
KhronosTextureContainer.prototype.switchEndainness = function (val) {
return ((val & 0xFF) << 24)
| ((val & 0xFF00) << 8)
| ((val >> 8) & 0xFF00)
| ((val >> 24) & 0xFF);
};
/**
* It is assumed that the texture has already been created & is currently bound
*/
KhronosTextureContainer.prototype.uploadLevels = function (gl, loadMipmaps) {
switch (this.loadType) {
case KhronosTextureContainer.COMPRESSED_2D:
this._upload2DCompressedLevels(gl, loadMipmaps);
break;
case KhronosTextureContainer.TEX_2D:
case KhronosTextureContainer.COMPRESSED_3D:
case KhronosTextureContainer.TEX_3D:
}
};
KhronosTextureContainer.prototype._upload2DCompressedLevels = function (gl, loadMipmaps) {
// initialize width & height for level 1
var dataOffset = KhronosTextureContainer.HEADER_LEN + this.bytesOfKeyValueData;
var width = this.pixelWidth;
var height = this.pixelHeight;
var mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
for (var level = 0; level < mipmapCount; level++) {
var imageSize = new Int32Array(this.arrayBuffer, dataOffset, 1)[0]; // size per face, since not supporting array cubemaps
for (var face = 0; face < this.numberOfFaces; face++) {
var sampler = this.numberOfFaces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face);
var byteArray = new Uint8Array(this.arrayBuffer, dataOffset + 4, imageSize);
gl.compressedTexImage2D(sampler, level, this.glInternalFormat, width, height, 0, byteArray);
dataOffset += imageSize + 4; // size of the image + 4 for the imageSize field
dataOffset += 3 - ((imageSize + 3) % 4); // add padding for odd sized image
}
width = Math.max(1.0, width * 0.5);
height = Math.max(1.0, height * 0.5);
}
};
KhronosTextureContainer.HEADER_LEN = 12 + (13 * 4); // identifier + header elements (not including key value meta-data pairs)
// load types
KhronosTextureContainer.COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D()
KhronosTextureContainer.COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D()
KhronosTextureContainer.TEX_2D = 2; // uses a gl.texImage2D()
KhronosTextureContainer.TEX_3D = 3; // uses a gl.texImage3D()
return KhronosTextureContainer;
}());
BABYLON.KhronosTextureContainer = KhronosTextureContainer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.khronosTextureContainer.js.map
var BABYLON;
(function (BABYLON) {
var Debug;
(function (Debug) {
/**
* Demo available here: http://www.babylonjs-playground.com/#1BZJVJ#8
*/
var SkeletonViewer = /** @class */ (function () {
function SkeletonViewer(skeleton, mesh, scene, autoUpdateBonesMatrices, renderingGroupId) {
if (autoUpdateBonesMatrices === void 0) { autoUpdateBonesMatrices = true; }
if (renderingGroupId === void 0) { renderingGroupId = 1; }
this.skeleton = skeleton;
this.mesh = mesh;
this.autoUpdateBonesMatrices = autoUpdateBonesMatrices;
this.renderingGroupId = renderingGroupId;
this.color = BABYLON.Color3.White();
this._debugLines = new Array();
this._isEnabled = false;
this._scene = scene;
this.update();
this._renderFunction = this.update.bind(this);
}
Object.defineProperty(SkeletonViewer.prototype, "isEnabled", {
get: function () {
return this._isEnabled;
},
set: function (value) {
if (this._isEnabled === value) {
return;
}
this._isEnabled = value;
if (value) {
this._scene.registerBeforeRender(this._renderFunction);
}
else {
this._scene.unregisterBeforeRender(this._renderFunction);
}
},
enumerable: true,
configurable: true
});
SkeletonViewer.prototype._getBonePosition = function (position, bone, meshMat, x, y, z) {
if (x === void 0) { x = 0; }
if (y === void 0) { y = 0; }
if (z === void 0) { z = 0; }
var tmat = BABYLON.Tmp.Matrix[0];
var parentBone = bone.getParent();
tmat.copyFrom(bone.getLocalMatrix());
if (x !== 0 || y !== 0 || z !== 0) {
var tmat2 = BABYLON.Tmp.Matrix[1];
BABYLON.Matrix.IdentityToRef(tmat2);
tmat2.m[12] = x;
tmat2.m[13] = y;
tmat2.m[14] = z;
tmat2.multiplyToRef(tmat, tmat);
}
if (parentBone) {
tmat.multiplyToRef(parentBone.getAbsoluteTransform(), tmat);
}
tmat.multiplyToRef(meshMat, tmat);
position.x = tmat.m[12];
position.y = tmat.m[13];
position.z = tmat.m[14];
};
SkeletonViewer.prototype._getLinesForBonesWithLength = function (bones, meshMat) {
var len = bones.length;
var meshPos = this.mesh.position;
for (var i = 0; i < len; i++) {
var bone = bones[i];
var points = this._debugLines[i];
if (!points) {
points = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this._debugLines[i] = points;
}
this._getBonePosition(points[0], bone, meshMat);
this._getBonePosition(points[1], bone, meshMat, 0, bone.length, 0);
points[0].subtractInPlace(meshPos);
points[1].subtractInPlace(meshPos);
}
};
SkeletonViewer.prototype._getLinesForBonesNoLength = function (bones, meshMat) {
var len = bones.length;
var boneNum = 0;
var meshPos = this.mesh.position;
for (var i = len - 1; i >= 0; i--) {
var childBone = bones[i];
var parentBone = childBone.getParent();
if (!parentBone) {
continue;
}
var points = this._debugLines[boneNum];
if (!points) {
points = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this._debugLines[boneNum] = points;
}
childBone.getAbsolutePositionToRef(this.mesh, points[0]);
parentBone.getAbsolutePositionToRef(this.mesh, points[1]);
points[0].subtractInPlace(meshPos);
points[1].subtractInPlace(meshPos);
boneNum++;
}
};
SkeletonViewer.prototype.update = function () {
if (this.autoUpdateBonesMatrices) {
this.skeleton.computeAbsoluteTransforms();
}
if (this.skeleton.bones[0].length === undefined) {
this._getLinesForBonesNoLength(this.skeleton.bones, this.mesh.getWorldMatrix());
}
else {
this._getLinesForBonesWithLength(this.skeleton.bones, this.mesh.getWorldMatrix());
}
if (!this._debugMesh) {
this._debugMesh = BABYLON.MeshBuilder.CreateLineSystem("", { lines: this._debugLines, updatable: true, instance: null }, this._scene);
this._debugMesh.renderingGroupId = this.renderingGroupId;
}
else {
BABYLON.MeshBuilder.CreateLineSystem("", { lines: this._debugLines, updatable: true, instance: this._debugMesh }, this._scene);
}
this._debugMesh.position.copyFrom(this.mesh.position);
this._debugMesh.color = this.color;
};
SkeletonViewer.prototype.dispose = function () {
if (this._debugMesh) {
this.isEnabled = false;
this._debugMesh.dispose();
this._debugMesh = null;
}
};
return SkeletonViewer;
}());
Debug.SkeletonViewer = SkeletonViewer;
})(Debug = BABYLON.Debug || (BABYLON.Debug = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.skeletonViewer.js.map
/**
* Module Debug contains the (visual) components to debug a scene correctly
*/
var BABYLON;
(function (BABYLON) {
var Debug;
(function (Debug) {
/**
* The Axes viewer will show 3 axes in a specific point in space
*/
var AxesViewer = /** @class */ (function () {
function AxesViewer(scene, scaleLines) {
if (scaleLines === void 0) { scaleLines = 1; }
this._xline = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this._yline = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this._zline = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this.scaleLines = 1;
this.scaleLines = scaleLines;
this._xmesh = BABYLON.Mesh.CreateLines("xline", this._xline, scene, true);
this._ymesh = BABYLON.Mesh.CreateLines("yline", this._yline, scene, true);
this._zmesh = BABYLON.Mesh.CreateLines("zline", this._zline, scene, true);
this._xmesh.renderingGroupId = 2;
this._ymesh.renderingGroupId = 2;
this._zmesh.renderingGroupId = 2;
this._xmesh.material.checkReadyOnlyOnce = true;
this._xmesh.color = new BABYLON.Color3(1, 0, 0);
this._ymesh.material.checkReadyOnlyOnce = true;
this._ymesh.color = new BABYLON.Color3(0, 1, 0);
this._zmesh.material.checkReadyOnlyOnce = true;
this._zmesh.color = new BABYLON.Color3(0, 0, 1);
this.scene = scene;
}
AxesViewer.prototype.update = function (position, xaxis, yaxis, zaxis) {
var scaleLines = this.scaleLines;
if (this._xmesh) {
this._xmesh.position.copyFrom(position);
}
if (this._ymesh) {
this._ymesh.position.copyFrom(position);
}
if (this._zmesh) {
this._zmesh.position.copyFrom(position);
}
var point2 = this._xline[1];
point2.x = xaxis.x * scaleLines;
point2.y = xaxis.y * scaleLines;
point2.z = xaxis.z * scaleLines;
BABYLON.Mesh.CreateLines("", this._xline, null, false, this._xmesh);
point2 = this._yline[1];
point2.x = yaxis.x * scaleLines;
point2.y = yaxis.y * scaleLines;
point2.z = yaxis.z * scaleLines;
BABYLON.Mesh.CreateLines("", this._yline, null, false, this._ymesh);
point2 = this._zline[1];
point2.x = zaxis.x * scaleLines;
point2.y = zaxis.y * scaleLines;
point2.z = zaxis.z * scaleLines;
BABYLON.Mesh.CreateLines("", this._zline, null, false, this._zmesh);
};
AxesViewer.prototype.dispose = function () {
if (this._xmesh) {
this._xmesh.dispose();
}
if (this._ymesh) {
this._ymesh.dispose();
}
if (this._zmesh) {
this._zmesh.dispose();
}
this._xmesh = null;
this._ymesh = null;
this._zmesh = null;
this.scene = null;
};
return AxesViewer;
}());
Debug.AxesViewer = AxesViewer;
})(Debug = BABYLON.Debug || (BABYLON.Debug = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.axesViewer.js.map
var BABYLON;
(function (BABYLON) {
var Debug;
(function (Debug) {
/**
* The BoneAxesViewer will attach 3 axes to a specific bone of a specific mesh
*/
var BoneAxesViewer = /** @class */ (function (_super) {
__extends(BoneAxesViewer, _super);
function BoneAxesViewer(scene, bone, mesh, scaleLines) {
if (scaleLines === void 0) { scaleLines = 1; }
var _this = _super.call(this, scene, scaleLines) || this;
_this.pos = BABYLON.Vector3.Zero();
_this.xaxis = BABYLON.Vector3.Zero();
_this.yaxis = BABYLON.Vector3.Zero();
_this.zaxis = BABYLON.Vector3.Zero();
_this.mesh = mesh;
_this.bone = bone;
return _this;
}
BoneAxesViewer.prototype.update = function () {
if (!this.mesh || !this.bone) {
return;
}
var bone = this.bone;
bone.getAbsolutePositionToRef(this.mesh, this.pos);
bone.getDirectionToRef(BABYLON.Axis.X, this.mesh, this.xaxis);
bone.getDirectionToRef(BABYLON.Axis.Y, this.mesh, this.yaxis);
bone.getDirectionToRef(BABYLON.Axis.Z, this.mesh, this.zaxis);
_super.prototype.update.call(this, this.pos, this.xaxis, this.yaxis, this.zaxis);
};
BoneAxesViewer.prototype.dispose = function () {
if (this.mesh) {
this.mesh = null;
this.bone = null;
_super.prototype.dispose.call(this);
}
};
return BoneAxesViewer;
}(Debug.AxesViewer));
Debug.BoneAxesViewer = BoneAxesViewer;
})(Debug = BABYLON.Debug || (BABYLON.Debug = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.boneAxesViewer.js.map
var BABYLON;
(function (BABYLON) {
var RayHelper = /** @class */ (function () {
function RayHelper(ray) {
this.ray = ray;
}
RayHelper.CreateAndShow = function (ray, scene, color) {
var helper = new RayHelper(ray);
helper.show(scene, color);
return helper;
};
RayHelper.prototype.show = function (scene, color) {
if (!this._renderFunction && this.ray) {
var ray = this.ray;
this._renderFunction = this._render.bind(this);
this._scene = scene;
this._renderPoints = [ray.origin, ray.origin.add(ray.direction.scale(ray.length))];
this._renderLine = BABYLON.Mesh.CreateLines("ray", this._renderPoints, scene, true);
if (this._renderFunction) {
this._scene.registerBeforeRender(this._renderFunction);
}
}
if (color && this._renderLine) {
this._renderLine.color.copyFrom(color);
}
};
RayHelper.prototype.hide = function () {
if (this._renderFunction && this._scene) {
this._scene.unregisterBeforeRender(this._renderFunction);
this._scene = null;
this._renderFunction = null;
if (this._renderLine) {
this._renderLine.dispose();
this._renderLine = null;
}
this._renderPoints = [];
}
};
RayHelper.prototype._render = function () {
var ray = this.ray;
if (!ray) {
return;
}
var point = this._renderPoints[1];
var len = Math.min(ray.length, 1000000);
point.copyFrom(ray.direction);
point.scaleInPlace(len);
point.addInPlace(ray.origin);
BABYLON.Mesh.CreateLines("ray", this._renderPoints, this._scene, true, this._renderLine);
};
RayHelper.prototype.attachToMesh = function (mesh, meshSpaceDirection, meshSpaceOrigin, length) {
this._attachedToMesh = mesh;
var ray = this.ray;
if (!ray) {
return;
}
if (!ray.direction) {
ray.direction = BABYLON.Vector3.Zero();
}
if (!ray.origin) {
ray.origin = BABYLON.Vector3.Zero();
}
if (length) {
ray.length = length;
}
if (!meshSpaceOrigin) {
meshSpaceOrigin = BABYLON.Vector3.Zero();
}
if (!meshSpaceDirection) {
// -1 so that this will work with Mesh.lookAt
meshSpaceDirection = new BABYLON.Vector3(0, 0, -1);
}
if (!this._meshSpaceDirection) {
this._meshSpaceDirection = meshSpaceDirection.clone();
this._meshSpaceOrigin = meshSpaceOrigin.clone();
}
else {
this._meshSpaceDirection.copyFrom(meshSpaceDirection);
this._meshSpaceOrigin.copyFrom(meshSpaceOrigin);
}
if (!this._updateToMeshFunction) {
this._updateToMeshFunction = this._updateToMesh.bind(this);
this._attachedToMesh.getScene().registerBeforeRender(this._updateToMeshFunction);
}
this._updateToMesh();
};
RayHelper.prototype.detachFromMesh = function () {
if (this._attachedToMesh) {
if (this._updateToMeshFunction) {
this._attachedToMesh.getScene().unregisterBeforeRender(this._updateToMeshFunction);
}
this._attachedToMesh = null;
this._updateToMeshFunction = null;
}
};
RayHelper.prototype._updateToMesh = function () {
var ray = this.ray;
if (!this._attachedToMesh || !ray) {
return;
}
if (this._attachedToMesh._isDisposed) {
this.detachFromMesh();
return;
}
this._attachedToMesh.getDirectionToRef(this._meshSpaceDirection, ray.direction);
BABYLON.Vector3.TransformCoordinatesToRef(this._meshSpaceOrigin, this._attachedToMesh.getWorldMatrix(), ray.origin);
};
RayHelper.prototype.dispose = function () {
this.hide();
this.detachFromMesh();
this.ray = null;
};
return RayHelper;
}());
BABYLON.RayHelper = RayHelper;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.rayHelper.js.map
var BABYLON;
(function (BABYLON) {
// load the inspector using require, if not present in the global namespace.
var DebugLayer = /** @class */ (function () {
function DebugLayer(scene) {
this.BJSINSPECTOR = typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
this._scene = scene;
// load inspector using require, if it doesn't exist on the global namespace.
}
/** Creates the inspector window. */
DebugLayer.prototype._createInspector = function (config) {
if (config === void 0) { config = {}; }
var popup = config.popup || false;
var initialTab = config.initialTab || 0;
var parentElement = config.parentElement || null;
if (!this._inspector) {
this.BJSINSPECTOR = this.BJSINSPECTOR || typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
this._inspector = new this.BJSINSPECTOR.Inspector(this._scene, popup, initialTab, parentElement, config.newColors);
} // else nothing to do,; instance is already existing
};
DebugLayer.prototype.isVisible = function () {
if (!this._inspector) {
return false;
}
return true;
};
DebugLayer.prototype.hide = function () {
if (this._inspector) {
try {
this._inspector.dispose();
}
catch (e) {
// If the inspector has been removed directly from the inspector tool
}
this._inspector = null;
}
};
DebugLayer.prototype.show = function (config) {
if (config === void 0) { config = {}; }
if (typeof this.BJSINSPECTOR == 'undefined') {
// Load inspector and add it to the DOM
BABYLON.Tools.LoadScript(DebugLayer.InspectorURL, this._createInspector.bind(this, config));
}
else {
// Otherwise creates the inspector
this._createInspector(config);
}
};
DebugLayer.InspectorURL = 'https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js';
return DebugLayer;
}());
BABYLON.DebugLayer = DebugLayer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.debugLayer.js.map
var BABYLON;
(function (BABYLON) {
var Debug;
(function (Debug) {
/**
* Used to show the physics impostor around the specific mesh.
*/
var PhysicsViewer = /** @class */ (function () {
function PhysicsViewer(scene) {
this._impostors = [];
this._meshes = [];
this._numMeshes = 0;
this._scene = scene || BABYLON.Engine.LastCreatedScene;
var physicEngine = this._scene.getPhysicsEngine();
if (physicEngine) {
this._physicsEnginePlugin = physicEngine.getPhysicsPlugin();
}
}
PhysicsViewer.prototype._updateDebugMeshes = function () {
var plugin = this._physicsEnginePlugin;
for (var i = 0; i < this._numMeshes; i++) {
var impostor = this._impostors[i];
if (!impostor) {
continue;
}
if (impostor.isDisposed) {
this.hideImpostor(this._impostors[i--]);
}
else {
var mesh = this._meshes[i];
if (mesh && plugin) {
plugin.syncMeshWithImpostor(mesh, impostor);
}
}
}
};
PhysicsViewer.prototype.showImpostor = function (impostor) {
if (!this._scene) {
return;
}
for (var i = 0; i < this._numMeshes; i++) {
if (this._impostors[i] == impostor) {
return;
}
}
var debugMesh = this._getDebugMesh(impostor, this._scene);
if (debugMesh) {
this._impostors[this._numMeshes] = impostor;
this._meshes[this._numMeshes] = debugMesh;
if (this._numMeshes === 0) {
this._renderFunction = this._updateDebugMeshes.bind(this);
this._scene.registerBeforeRender(this._renderFunction);
}
this._numMeshes++;
}
};
PhysicsViewer.prototype.hideImpostor = function (impostor) {
if (!impostor || !this._scene) {
return;
}
var removed = false;
for (var i = 0; i < this._numMeshes; i++) {
if (this._impostors[i] == impostor) {
var mesh = this._meshes[i];
if (!mesh) {
continue;
}
this._scene.removeMesh(mesh);
mesh.dispose();
this._numMeshes--;
if (this._numMeshes > 0) {
this._meshes[i] = this._meshes[this._numMeshes];
this._impostors[i] = this._impostors[this._numMeshes];
this._meshes[this._numMeshes] = null;
this._impostors[this._numMeshes] = null;
}
else {
this._meshes[0] = null;
this._impostors[0] = null;
}
removed = true;
break;
}
}
if (removed && this._numMeshes === 0) {
this._scene.unregisterBeforeRender(this._renderFunction);
}
};
PhysicsViewer.prototype._getDebugMaterial = function (scene) {
if (!this._debugMaterial) {
this._debugMaterial = new BABYLON.StandardMaterial('', scene);
this._debugMaterial.wireframe = true;
}
return this._debugMaterial;
};
PhysicsViewer.prototype._getDebugBoxMesh = function (scene) {
if (!this._debugBoxMesh) {
this._debugBoxMesh = BABYLON.MeshBuilder.CreateBox('physicsBodyBoxViewMesh', { size: 1 }, scene);
this._debugBoxMesh.renderingGroupId = 1;
this._debugBoxMesh.rotationQuaternion = BABYLON.Quaternion.Identity();
this._debugBoxMesh.material = this._getDebugMaterial(scene);
scene.removeMesh(this._debugBoxMesh);
}
return this._debugBoxMesh.createInstance('physicsBodyBoxViewInstance');
};
PhysicsViewer.prototype._getDebugSphereMesh = function (scene) {
if (!this._debugSphereMesh) {
this._debugSphereMesh = BABYLON.MeshBuilder.CreateSphere('physicsBodySphereViewMesh', { diameter: 1 }, scene);
this._debugSphereMesh.renderingGroupId = 1;
this._debugSphereMesh.rotationQuaternion = BABYLON.Quaternion.Identity();
this._debugSphereMesh.material = this._getDebugMaterial(scene);
scene.removeMesh(this._debugSphereMesh);
}
return this._debugSphereMesh.createInstance('physicsBodyBoxViewInstance');
};
PhysicsViewer.prototype._getDebugMesh = function (impostor, scene) {
var mesh = null;
if (impostor.type == BABYLON.PhysicsImpostor.BoxImpostor) {
mesh = this._getDebugBoxMesh(scene);
impostor.getBoxSizeToRef(mesh.scaling);
}
else if (impostor.type == BABYLON.PhysicsImpostor.SphereImpostor) {
mesh = this._getDebugSphereMesh(scene);
var radius = impostor.getRadius();
mesh.scaling.x = radius * 2;
mesh.scaling.y = radius * 2;
mesh.scaling.z = radius * 2;
}
return mesh;
};
PhysicsViewer.prototype.dispose = function () {
for (var i = 0; i < this._numMeshes; i++) {
this.hideImpostor(this._impostors[i]);
}
if (this._debugBoxMesh) {
this._debugBoxMesh.dispose();
}
if (this._debugSphereMesh) {
this._debugSphereMesh.dispose();
}
if (this._debugMaterial) {
this._debugMaterial.dispose();
}
this._impostors.length = 0;
this._scene = null;
this._physicsEnginePlugin = null;
};
return PhysicsViewer;
}());
Debug.PhysicsViewer = PhysicsViewer;
})(Debug = BABYLON.Debug || (BABYLON.Debug = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.physicsViewer.js.map
var BABYLON;
(function (BABYLON) {
var BoundingBoxRenderer = /** @class */ (function () {
function BoundingBoxRenderer(scene) {
this.frontColor = new BABYLON.Color3(1, 1, 1);
this.backColor = new BABYLON.Color3(0.1, 0.1, 0.1);
this.showBackLines = true;
this.renderList = new BABYLON.SmartArray(32);
this._vertexBuffers = {};
this._scene = scene;
}
BoundingBoxRenderer.prototype._prepareRessources = function () {
if (this._colorShader) {
return;
}
this._colorShader = new BABYLON.ShaderMaterial("colorShader", this._scene, "color", {
attributes: [BABYLON.VertexBuffer.PositionKind],
uniforms: ["world", "viewProjection", "color"]
});
var engine = this._scene.getEngine();
var boxdata = BABYLON.VertexData.CreateBox({ size: 1.0 });
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = new BABYLON.VertexBuffer(engine, boxdata.positions, BABYLON.VertexBuffer.PositionKind, false);
this._createIndexBuffer();
};
BoundingBoxRenderer.prototype._createIndexBuffer = function () {
var engine = this._scene.getEngine();
this._indexBuffer = engine.createIndexBuffer([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 7, 1, 6, 2, 5, 3, 4]);
};
BoundingBoxRenderer.prototype._rebuild = function () {
var vb = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vb) {
vb._rebuild();
}
this._createIndexBuffer();
};
BoundingBoxRenderer.prototype.reset = function () {
this.renderList.reset();
};
BoundingBoxRenderer.prototype.render = function () {
if (this.renderList.length === 0) {
return;
}
this._prepareRessources();
if (!this._colorShader.isReady()) {
return;
}
var engine = this._scene.getEngine();
engine.setDepthWrite(false);
this._colorShader._preBind();
for (var boundingBoxIndex = 0; boundingBoxIndex < this.renderList.length; boundingBoxIndex++) {
var boundingBox = this.renderList.data[boundingBoxIndex];
var min = boundingBox.minimum;
var max = boundingBox.maximum;
var diff = max.subtract(min);
var median = min.add(diff.scale(0.5));
var worldMatrix = BABYLON.Matrix.Scaling(diff.x, diff.y, diff.z)
.multiply(BABYLON.Matrix.Translation(median.x, median.y, median.z))
.multiply(boundingBox.getWorldMatrix());
// VBOs
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, this._colorShader.getEffect());
if (this.showBackLines) {
// Back
engine.setDepthFunctionToGreaterOrEqual();
this._scene.resetCachedMaterial();
this._colorShader.setColor4("color", this.backColor.toColor4());
this._colorShader.bind(worldMatrix);
// Draw order
engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
}
// Front
engine.setDepthFunctionToLess();
this._scene.resetCachedMaterial();
this._colorShader.setColor4("color", this.frontColor.toColor4());
this._colorShader.bind(worldMatrix);
// Draw order
engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
}
this._colorShader.unbind();
engine.setDepthFunctionToLessOrEqual();
engine.setDepthWrite(true);
};
BoundingBoxRenderer.prototype.renderOcclusionBoundingBox = function (mesh) {
this._prepareRessources();
if (!this._colorShader.isReady() || !mesh._boundingInfo) {
return;
}
var engine = this._scene.getEngine();
engine.setDepthWrite(false);
engine.setColorWrite(false);
this._colorShader._preBind();
var boundingBox = mesh._boundingInfo.boundingBox;
var min = boundingBox.minimum;
var max = boundingBox.maximum;
var diff = max.subtract(min);
var median = min.add(diff.scale(0.5));
var worldMatrix = BABYLON.Matrix.Scaling(diff.x, diff.y, diff.z)
.multiply(BABYLON.Matrix.Translation(median.x, median.y, median.z))
.multiply(boundingBox.getWorldMatrix());
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, this._colorShader.getEffect());
engine.setDepthFunctionToLess();
this._scene.resetCachedMaterial();
this._colorShader.bind(worldMatrix);
engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
this._colorShader.unbind();
engine.setDepthFunctionToLessOrEqual();
engine.setDepthWrite(true);
engine.setColorWrite(true);
};
BoundingBoxRenderer.prototype.dispose = function () {
if (!this._colorShader) {
return;
}
this.renderList.dispose();
this._colorShader.dispose();
var buffer = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (buffer) {
buffer.dispose();
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = null;
}
this._scene.getEngine()._releaseBuffer(this._indexBuffer);
};
return BoundingBoxRenderer;
}());
BABYLON.BoundingBoxRenderer = BoundingBoxRenderer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.boundingBoxRenderer.js.map
var BABYLON;
(function (BABYLON) {
/**
* Defines a target to use with MorphTargetManager
* @see http://doc.babylonjs.com/how_to/how_to_use_morphtargets
*/
var MorphTarget = /** @class */ (function () {
/**
* Creates a new MorphTarget
* @param name defines the name of the target
* @param influence defines the influence to use
*/
function MorphTarget(
/** defines the name of the target */
name, influence, scene) {
if (influence === void 0) { influence = 0; }
if (scene === void 0) { scene = null; }
this.name = name;
/**
* Gets or sets the list of animations
*/
this.animations = new Array();
this._positions = null;
this._normals = null;
this._tangents = null;
/**
* Observable raised when the influence changes
*/
this.onInfluenceChanged = new BABYLON.Observable();
this._animationPropertiesOverride = null;
this._scene = scene || BABYLON.Engine.LastCreatedScene;
this.influence = influence;
}
Object.defineProperty(MorphTarget.prototype, "influence", {
/**
* Gets or sets the influence of this target (ie. its weight in the overall morphing)
*/
get: function () {
return this._influence;
},
set: function (influence) {
if (this._influence === influence) {
return;
}
var previous = this._influence;
this._influence = influence;
if (this.onInfluenceChanged.hasObservers) {
this.onInfluenceChanged.notifyObservers(previous === 0 || influence === 0);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTarget.prototype, "animationPropertiesOverride", {
/**
* Gets or sets the animation properties override
*/
get: function () {
if (!this._animationPropertiesOverride && this._scene) {
return this._scene.animationPropertiesOverride;
}
return this._animationPropertiesOverride;
},
set: function (value) {
this._animationPropertiesOverride = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTarget.prototype, "hasPositions", {
/**
* Gets a boolean defining if the target contains position data
*/
get: function () {
return !!this._positions;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTarget.prototype, "hasNormals", {
/**
* Gets a boolean defining if the target contains normal data
*/
get: function () {
return !!this._normals;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTarget.prototype, "hasTangents", {
/**
* Gets a boolean defining if the target contains tangent data
*/
get: function () {
return !!this._tangents;
},
enumerable: true,
configurable: true
});
/**
* Affects position data to this target
* @param data defines the position data to use
*/
MorphTarget.prototype.setPositions = function (data) {
this._positions = data;
};
/**
* Gets the position data stored in this target
* @returns a FloatArray containing the position data (or null if not present)
*/
MorphTarget.prototype.getPositions = function () {
return this._positions;
};
/**
* Affects normal data to this target
* @param data defines the normal data to use
*/
MorphTarget.prototype.setNormals = function (data) {
this._normals = data;
};
/**
* Gets the normal data stored in this target
* @returns a FloatArray containing the normal data (or null if not present)
*/
MorphTarget.prototype.getNormals = function () {
return this._normals;
};
/**
* Affects tangent data to this target
* @param data defines the tangent data to use
*/
MorphTarget.prototype.setTangents = function (data) {
this._tangents = data;
};
/**
* Gets the tangent data stored in this target
* @returns a FloatArray containing the tangent data (or null if not present)
*/
MorphTarget.prototype.getTangents = function () {
return this._tangents;
};
/**
* Serializes the current target into a Serialization object
* @returns the serialized object
*/
MorphTarget.prototype.serialize = function () {
var serializationObject = {};
serializationObject.name = this.name;
serializationObject.influence = this.influence;
serializationObject.positions = Array.prototype.slice.call(this.getPositions());
if (this.hasNormals) {
serializationObject.normals = Array.prototype.slice.call(this.getNormals());
}
if (this.hasTangents) {
serializationObject.tangents = Array.prototype.slice.call(this.getTangents());
}
// Animations
BABYLON.Animation.AppendSerializedAnimations(this, serializationObject);
return serializationObject;
};
// Statics
/**
* Creates a new target from serialized data
* @param serializationObject defines the serialized data to use
* @returns a new MorphTarget
*/
MorphTarget.Parse = function (serializationObject) {
var result = new MorphTarget(serializationObject.name, serializationObject.influence);
result.setPositions(serializationObject.positions);
if (serializationObject.normals) {
result.setNormals(serializationObject.normals);
}
if (serializationObject.tangents) {
result.setTangents(serializationObject.tangents);
}
// Animations
if (serializationObject.animations) {
for (var animationIndex = 0; animationIndex < serializationObject.animations.length; animationIndex++) {
var parsedAnimation = serializationObject.animations[animationIndex];
result.animations.push(BABYLON.Animation.Parse(parsedAnimation));
}
}
return result;
};
/**
* Creates a MorphTarget from mesh data
* @param mesh defines the source mesh
* @param name defines the name to use for the new target
* @param influence defines the influence to attach to the target
* @returns a new MorphTarget
*/
MorphTarget.FromMesh = function (mesh, name, influence) {
if (!name) {
name = mesh.name;
}
var result = new MorphTarget(name, influence, mesh.getScene());
result.setPositions(mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind));
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
result.setNormals(mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind));
}
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.TangentKind)) {
result.setTangents(mesh.getVerticesData(BABYLON.VertexBuffer.TangentKind));
}
return result;
};
return MorphTarget;
}());
BABYLON.MorphTarget = MorphTarget;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.morphTarget.js.map
var BABYLON;
(function (BABYLON) {
/**
* This class is used to deform meshes using morphing between different targets
* @see http://doc.babylonjs.com/how_to/how_to_use_morphtargets
*/
var MorphTargetManager = /** @class */ (function () {
/**
* Creates a new MorphTargetManager
* @param scene defines the current scene
*/
function MorphTargetManager(scene) {
if (scene === void 0) { scene = null; }
this._targets = new Array();
this._targetObservable = new Array();
this._activeTargets = new BABYLON.SmartArray(16);
this._supportsNormals = false;
this._supportsTangents = false;
this._vertexCount = 0;
this._uniqueId = 0;
this._tempInfluences = new Array();
if (!scene) {
scene = BABYLON.Engine.LastCreatedScene;
}
this._scene = scene;
if (this._scene) {
this._scene.morphTargetManagers.push(this);
this._uniqueId = this._scene.getUniqueId();
}
}
Object.defineProperty(MorphTargetManager.prototype, "uniqueId", {
/**
* Gets the unique ID of this manager
*/
get: function () {
return this._uniqueId;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "vertexCount", {
/**
* Gets the number of vertices handled by this manager
*/
get: function () {
return this._vertexCount;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "supportsNormals", {
/**
* Gets a boolean indicating if this manager supports morphing of normals
*/
get: function () {
return this._supportsNormals;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "supportsTangents", {
/**
* Gets a boolean indicating if this manager supports morphing of tangents
*/
get: function () {
return this._supportsTangents;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "numTargets", {
/**
* Gets the number of targets stored in this manager
*/
get: function () {
return this._targets.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "numInfluencers", {
/**
* Gets the number of influencers (ie. the number of targets with influences > 0)
*/
get: function () {
return this._activeTargets.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "influences", {
/**
* Gets the list of influences (one per target)
*/
get: function () {
return this._influences;
},
enumerable: true,
configurable: true
});
/**
* Gets the active target at specified index. An active target is a target with an influence > 0
* @param index defines the index to check
* @returns the requested target
*/
MorphTargetManager.prototype.getActiveTarget = function (index) {
return this._activeTargets.data[index];
};
/**
* Gets the target at specified index
* @param index defines the index to check
* @returns the requested target
*/
MorphTargetManager.prototype.getTarget = function (index) {
return this._targets[index];
};
/**
* Add a new target to this manager
* @param target defines the target to add
*/
MorphTargetManager.prototype.addTarget = function (target) {
var _this = this;
this._targets.push(target);
this._targetObservable.push(target.onInfluenceChanged.add(function (needUpdate) {
_this._syncActiveTargets(needUpdate);
}));
this._syncActiveTargets(true);
};
/**
* Removes a target from the manager
* @param target defines the target to remove
*/
MorphTargetManager.prototype.removeTarget = function (target) {
var index = this._targets.indexOf(target);
if (index >= 0) {
this._targets.splice(index, 1);
target.onInfluenceChanged.remove(this._targetObservable.splice(index, 1)[0]);
this._syncActiveTargets(true);
}
};
/**
* Serializes the current manager into a Serialization object
* @returns the serialized object
*/
MorphTargetManager.prototype.serialize = function () {
var serializationObject = {};
serializationObject.id = this.uniqueId;
serializationObject.targets = [];
for (var _i = 0, _a = this._targets; _i < _a.length; _i++) {
var target = _a[_i];
serializationObject.targets.push(target.serialize());
}
return serializationObject;
};
MorphTargetManager.prototype._syncActiveTargets = function (needUpdate) {
var influenceCount = 0;
this._activeTargets.reset();
this._supportsNormals = true;
this._supportsTangents = true;
this._vertexCount = 0;
for (var _i = 0, _a = this._targets; _i < _a.length; _i++) {
var target = _a[_i];
this._activeTargets.push(target);
this._tempInfluences[influenceCount++] = target.influence;
var positions = target.getPositions();
if (positions) {
this._supportsNormals = this._supportsNormals && target.hasNormals;
this._supportsTangents = this._supportsTangents && target.hasTangents;
var vertexCount = positions.length / 3;
if (this._vertexCount === 0) {
this._vertexCount = vertexCount;
}
else if (this._vertexCount !== vertexCount) {
BABYLON.Tools.Error("Incompatible target. Targets must all have the same vertices count.");
return;
}
}
}
if (!this._influences || this._influences.length !== influenceCount) {
this._influences = new Float32Array(influenceCount);
}
for (var index = 0; index < influenceCount; index++) {
this._influences[index] = this._tempInfluences[index];
}
if (needUpdate) {
this.synchronize();
}
};
/**
* Syncrhonize the targets with all the meshes using this morph target manager
*/
MorphTargetManager.prototype.synchronize = function () {
if (!this._scene) {
return;
}
// Flag meshes as dirty to resync with the active targets
for (var _i = 0, _a = this._scene.meshes; _i < _a.length; _i++) {
var mesh = _a[_i];
if (mesh.morphTargetManager === this) {
mesh._syncGeometryWithMorphTargetManager();
}
}
};
// Statics
/**
* Creates a new MorphTargetManager from serialized data
* @param serializationObject defines the serialized data
* @param scene defines the hosting scene
* @returns the new MorphTargetManager
*/
MorphTargetManager.Parse = function (serializationObject, scene) {
var result = new MorphTargetManager(scene);
result._uniqueId = serializationObject.id;
for (var _i = 0, _a = serializationObject.targets; _i < _a.length; _i++) {
var targetData = _a[_i];
result.addTarget(BABYLON.MorphTarget.Parse(targetData));
}
return result;
};
return MorphTargetManager;
}());
BABYLON.MorphTargetManager = MorphTargetManager;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.morphTargetManager.js.map
var BABYLON;
(function (BABYLON) {
var Octree = /** @class */ (function () {
function Octree(creationFunc, maxBlockCapacity, maxDepth) {
if (maxDepth === void 0) { maxDepth = 2; }
this.maxDepth = maxDepth;
this.dynamicContent = new Array();
this._maxBlockCapacity = maxBlockCapacity || 64;
this._selectionContent = new BABYLON.SmartArrayNoDuplicate(1024);
this._creationFunc = creationFunc;
}
// Methods
Octree.prototype.update = function (worldMin, worldMax, entries) {
Octree._CreateBlocks(worldMin, worldMax, entries, this._maxBlockCapacity, 0, this.maxDepth, this, this._creationFunc);
};
Octree.prototype.addMesh = function (entry) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.addEntry(entry);
}
};
Octree.prototype.select = function (frustumPlanes, allowDuplicate) {
this._selectionContent.reset();
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.select(frustumPlanes, this._selectionContent, allowDuplicate);
}
if (allowDuplicate) {
this._selectionContent.concat(this.dynamicContent);
}
else {
this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
}
return this._selectionContent;
};
Octree.prototype.intersects = function (sphereCenter, sphereRadius, allowDuplicate) {
this._selectionContent.reset();
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.intersects(sphereCenter, sphereRadius, this._selectionContent, allowDuplicate);
}
if (allowDuplicate) {
this._selectionContent.concat(this.dynamicContent);
}
else {
this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
}
return this._selectionContent;
};
Octree.prototype.intersectsRay = function (ray) {
this._selectionContent.reset();
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.intersectsRay(ray, this._selectionContent);
}
this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
return this._selectionContent;
};
Octree._CreateBlocks = function (worldMin, worldMax, entries, maxBlockCapacity, currentDepth, maxDepth, target, creationFunc) {
target.blocks = new Array();
var blockSize = new BABYLON.Vector3((worldMax.x - worldMin.x) / 2, (worldMax.y - worldMin.y) / 2, (worldMax.z - worldMin.z) / 2);
// Segmenting space
for (var x = 0; x < 2; x++) {
for (var y = 0; y < 2; y++) {
for (var z = 0; z < 2; z++) {
var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
var localMax = worldMin.add(blockSize.multiplyByFloats(x + 1, y + 1, z + 1));
var block = new BABYLON.OctreeBlock(localMin, localMax, maxBlockCapacity, currentDepth + 1, maxDepth, creationFunc);
block.addEntries(entries);
target.blocks.push(block);
}
}
}
};
Octree.CreationFuncForMeshes = function (entry, block) {
var boundingInfo = entry.getBoundingInfo();
if (!entry.isBlocked && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
block.entries.push(entry);
}
};
Octree.CreationFuncForSubMeshes = function (entry, block) {
var boundingInfo = entry.getBoundingInfo();
if (boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
block.entries.push(entry);
}
};
return Octree;
}());
BABYLON.Octree = Octree;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.octree.js.map
var BABYLON;
(function (BABYLON) {
var OctreeBlock = /** @class */ (function () {
function OctreeBlock(minPoint, maxPoint, capacity, depth, maxDepth, creationFunc) {
this.entries = new Array();
this._boundingVectors = new Array();
this._capacity = capacity;
this._depth = depth;
this._maxDepth = maxDepth;
this._creationFunc = creationFunc;
this._minPoint = minPoint;
this._maxPoint = maxPoint;
this._boundingVectors.push(minPoint.clone());
this._boundingVectors.push(maxPoint.clone());
this._boundingVectors.push(minPoint.clone());
this._boundingVectors[2].x = maxPoint.x;
this._boundingVectors.push(minPoint.clone());
this._boundingVectors[3].y = maxPoint.y;
this._boundingVectors.push(minPoint.clone());
this._boundingVectors[4].z = maxPoint.z;
this._boundingVectors.push(maxPoint.clone());
this._boundingVectors[5].z = minPoint.z;
this._boundingVectors.push(maxPoint.clone());
this._boundingVectors[6].x = minPoint.x;
this._boundingVectors.push(maxPoint.clone());
this._boundingVectors[7].y = minPoint.y;
}
Object.defineProperty(OctreeBlock.prototype, "capacity", {
// Property
get: function () {
return this._capacity;
},
enumerable: true,
configurable: true
});
Object.defineProperty(OctreeBlock.prototype, "minPoint", {
get: function () {
return this._minPoint;
},
enumerable: true,
configurable: true
});
Object.defineProperty(OctreeBlock.prototype, "maxPoint", {
get: function () {
return this._maxPoint;
},
enumerable: true,
configurable: true
});
// Methods
OctreeBlock.prototype.addEntry = function (entry) {
if (this.blocks) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.addEntry(entry);
}
return;
}
this._creationFunc(entry, this);
if (this.entries.length > this.capacity && this._depth < this._maxDepth) {
this.createInnerBlocks();
}
};
OctreeBlock.prototype.addEntries = function (entries) {
for (var index = 0; index < entries.length; index++) {
var mesh = entries[index];
this.addEntry(mesh);
}
};
OctreeBlock.prototype.select = function (frustumPlanes, selection, allowDuplicate) {
if (BABYLON.BoundingBox.IsInFrustum(this._boundingVectors, frustumPlanes)) {
if (this.blocks) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.select(frustumPlanes, selection, allowDuplicate);
}
return;
}
if (allowDuplicate) {
selection.concat(this.entries);
}
else {
selection.concatWithNoDuplicate(this.entries);
}
}
};
OctreeBlock.prototype.intersects = function (sphereCenter, sphereRadius, selection, allowDuplicate) {
if (BABYLON.BoundingBox.IntersectsSphere(this._minPoint, this._maxPoint, sphereCenter, sphereRadius)) {
if (this.blocks) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.intersects(sphereCenter, sphereRadius, selection, allowDuplicate);
}
return;
}
if (allowDuplicate) {
selection.concat(this.entries);
}
else {
selection.concatWithNoDuplicate(this.entries);
}
}
};
OctreeBlock.prototype.intersectsRay = function (ray, selection) {
if (ray.intersectsBoxMinMax(this._minPoint, this._maxPoint)) {
if (this.blocks) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.intersectsRay(ray, selection);
}
return;
}
selection.concatWithNoDuplicate(this.entries);
}
};
OctreeBlock.prototype.createInnerBlocks = function () {
BABYLON.Octree._CreateBlocks(this._minPoint, this._maxPoint, this.entries, this._capacity, this._depth, this._maxDepth, this, this._creationFunc);
};
return OctreeBlock;
}());
BABYLON.OctreeBlock = OctreeBlock;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.octreeBlock.js.map
var BABYLON;
(function (BABYLON) {
var VRDistortionCorrectionPostProcess = /** @class */ (function (_super) {
__extends(VRDistortionCorrectionPostProcess, _super);
function VRDistortionCorrectionPostProcess(name, camera, isRightEye, vrMetrics) {
var _this = _super.call(this, name, "vrDistortionCorrection", [
'LensCenter',
'Scale',
'ScaleIn',
'HmdWarpParam'
], null, vrMetrics.postProcessScaleFactor, camera, BABYLON.Texture.BILINEAR_SAMPLINGMODE) || this;
_this._isRightEye = isRightEye;
_this._distortionFactors = vrMetrics.distortionK;
_this._postProcessScaleFactor = vrMetrics.postProcessScaleFactor;
_this._lensCenterOffset = vrMetrics.lensCenterOffset;
_this.adaptScaleToCurrentViewport = true;
_this.onSizeChangedObservable.add(function () {
_this._scaleIn = new BABYLON.Vector2(2, 2 / _this.aspectRatio);
_this._scaleFactor = new BABYLON.Vector2(.5 * (1 / _this._postProcessScaleFactor), .5 * (1 / _this._postProcessScaleFactor) * _this.aspectRatio);
_this._lensCenter = new BABYLON.Vector2(_this._isRightEye ? 0.5 - _this._lensCenterOffset * 0.5 : 0.5 + _this._lensCenterOffset * 0.5, 0.5);
});
_this.onApplyObservable.add(function (effect) {
effect.setFloat2("LensCenter", _this._lensCenter.x, _this._lensCenter.y);
effect.setFloat2("Scale", _this._scaleFactor.x, _this._scaleFactor.y);
effect.setFloat2("ScaleIn", _this._scaleIn.x, _this._scaleIn.y);
effect.setFloat4("HmdWarpParam", _this._distortionFactors[0], _this._distortionFactors[1], _this._distortionFactors[2], _this._distortionFactors[3]);
});
return _this;
}
return VRDistortionCorrectionPostProcess;
}(BABYLON.PostProcess));
BABYLON.VRDistortionCorrectionPostProcess = VRDistortionCorrectionPostProcess;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.vrDistortionCorrectionPostProcess.js.map
var BABYLON;
(function (BABYLON) {
/**
* Postprocess used to generate anaglyphic rendering
*/
var AnaglyphPostProcess = /** @class */ (function (_super) {
__extends(AnaglyphPostProcess, _super);
/**
* Creates a new AnaglyphPostProcess
* @param name defines postprocess name
* @param options defines creation options or target ratio scale
* @param rigCameras defines cameras using this postprocess
* @param samplingMode defines required sampling mode (BABYLON.Texture.NEAREST_SAMPLINGMODE by default)
* @param engine defines hosting engine
* @param reusable defines if the postprocess will be reused multiple times per frame
*/
function AnaglyphPostProcess(name, options, rigCameras, samplingMode, engine, reusable) {
var _this = _super.call(this, name, "anaglyph", null, ["leftSampler"], options, rigCameras[1], samplingMode, engine, reusable) || this;
_this._passedProcess = rigCameras[0]._rigPostProcess;
_this.onApplyObservable.add(function (effect) {
effect.setTextureFromPostProcess("leftSampler", _this._passedProcess);
});
return _this;
}
return AnaglyphPostProcess;
}(BABYLON.PostProcess));
BABYLON.AnaglyphPostProcess = AnaglyphPostProcess;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.anaglyphPostProcess.js.map
var BABYLON;
(function (BABYLON) {
var StereoscopicInterlacePostProcess = /** @class */ (function (_super) {
__extends(StereoscopicInterlacePostProcess, _super);
function StereoscopicInterlacePostProcess(name, rigCameras, isStereoscopicHoriz, samplingMode, engine, reusable) {
var _this = _super.call(this, name, "stereoscopicInterlace", ['stepSize'], ['camASampler'], 1, rigCameras[1], samplingMode, engine, reusable, isStereoscopicHoriz ? "#define IS_STEREOSCOPIC_HORIZ 1" : undefined) || this;
_this._passedProcess = rigCameras[0]._rigPostProcess;
_this._stepSize = new BABYLON.Vector2(1 / _this.width, 1 / _this.height);
_this.onSizeChangedObservable.add(function () {
_this._stepSize = new BABYLON.Vector2(1 / _this.width, 1 / _this.height);
});
_this.onApplyObservable.add(function (effect) {
effect.setTextureFromPostProcess("camASampler", _this._passedProcess);
effect.setFloat2("stepSize", _this._stepSize.x, _this._stepSize.y);
});
return _this;
}
return StereoscopicInterlacePostProcess;
}(BABYLON.PostProcess));
BABYLON.StereoscopicInterlacePostProcess = StereoscopicInterlacePostProcess;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.stereoscopicInterlacePostProcess.js.map
var BABYLON;
(function (BABYLON) {
/**
* Takes information about the orientation of the device as reported by the deviceorientation event to orient the camera.
* Screen rotation is taken into account.
*/
var FreeCameraDeviceOrientationInput = /** @class */ (function () {
function FreeCameraDeviceOrientationInput() {
var _this = this;
this._screenOrientationAngle = 0;
this._screenQuaternion = new BABYLON.Quaternion();
this._alpha = 0;
this._beta = 0;
this._gamma = 0;
this._orientationChanged = function () {
_this._screenOrientationAngle = (window.orientation !== undefined ? +window.orientation : (window.screen.orientation && window.screen.orientation['angle'] ? window.screen.orientation.angle : 0));
_this._screenOrientationAngle = -BABYLON.Tools.ToRadians(_this._screenOrientationAngle / 2);
_this._screenQuaternion.copyFromFloats(0, Math.sin(_this._screenOrientationAngle), 0, Math.cos(_this._screenOrientationAngle));
};
this._deviceOrientation = function (evt) {
_this._alpha = evt.alpha !== null ? evt.alpha : 0;
_this._beta = evt.beta !== null ? evt.beta : 0;
_this._gamma = evt.gamma !== null ? evt.gamma : 0;
};
this._constantTranform = new BABYLON.Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
this._orientationChanged();
}
Object.defineProperty(FreeCameraDeviceOrientationInput.prototype, "camera", {
get: function () {
return this._camera;
},
set: function (camera) {
this._camera = camera;
if (this._camera != null && !this._camera.rotationQuaternion) {
this._camera.rotationQuaternion = new BABYLON.Quaternion();
}
},
enumerable: true,
configurable: true
});
FreeCameraDeviceOrientationInput.prototype.attachControl = function (element, noPreventDefault) {
window.addEventListener("orientationchange", this._orientationChanged);
window.addEventListener("deviceorientation", this._deviceOrientation);
//In certain cases, the attach control is called AFTER orientation was changed,
//So this is needed.
this._orientationChanged();
};
FreeCameraDeviceOrientationInput.prototype.detachControl = function (element) {
window.removeEventListener("orientationchange", this._orientationChanged);
window.removeEventListener("deviceorientation", this._deviceOrientation);
};
FreeCameraDeviceOrientationInput.prototype.checkInputs = function () {
//if no device orientation provided, don't update the rotation.
//Only testing against alpha under the assumption thatnorientation will never be so exact when set.
if (!this._alpha)
return;
BABYLON.Quaternion.RotationYawPitchRollToRef(BABYLON.Tools.ToRadians(this._alpha), BABYLON.Tools.ToRadians(this._beta), -BABYLON.Tools.ToRadians(this._gamma), this.camera.rotationQuaternion);
this._camera.rotationQuaternion.multiplyInPlace(this._screenQuaternion);
this._camera.rotationQuaternion.multiplyInPlace(this._constantTranform);
//Mirror on XY Plane
this._camera.rotationQuaternion.z *= -1;
this._camera.rotationQuaternion.w *= -1;
};
FreeCameraDeviceOrientationInput.prototype.getClassName = function () {
return "FreeCameraDeviceOrientationInput";
};
FreeCameraDeviceOrientationInput.prototype.getSimpleName = function () {
return "deviceOrientation";
};
return FreeCameraDeviceOrientationInput;
}());
BABYLON.FreeCameraDeviceOrientationInput = FreeCameraDeviceOrientationInput;
BABYLON.CameraInputTypes["FreeCameraDeviceOrientationInput"] = FreeCameraDeviceOrientationInput;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.freeCameraDeviceOrientationInput.js.map
var BABYLON;
(function (BABYLON) {
var ArcRotateCameraVRDeviceOrientationInput = /** @class */ (function () {
function ArcRotateCameraVRDeviceOrientationInput() {
this.alphaCorrection = 1;
this.betaCorrection = 1;
this.gammaCorrection = 1;
this._alpha = 0;
this._gamma = 0;
this._dirty = false;
this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
}
ArcRotateCameraVRDeviceOrientationInput.prototype.attachControl = function (element, noPreventDefault) {
this.camera.attachControl(element, noPreventDefault);
window.addEventListener("deviceorientation", this._deviceOrientationHandler);
};
ArcRotateCameraVRDeviceOrientationInput.prototype._onOrientationEvent = function (evt) {
if (evt.alpha !== null) {
this._alpha = +evt.alpha | 0;
}
if (evt.gamma !== null) {
this._gamma = +evt.gamma | 0;
}
this._dirty = true;
};
ArcRotateCameraVRDeviceOrientationInput.prototype.checkInputs = function () {
if (this._dirty) {
this._dirty = false;
if (this._gamma < 0) {
this._gamma = 180 + this._gamma;
}
this.camera.alpha = (-this._alpha / 180.0 * Math.PI) % Math.PI * 2;
this.camera.beta = (this._gamma / 180.0 * Math.PI);
}
};
ArcRotateCameraVRDeviceOrientationInput.prototype.detachControl = function (element) {
window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
};
ArcRotateCameraVRDeviceOrientationInput.prototype.getClassName = function () {
return "ArcRotateCameraVRDeviceOrientationInput";
};
ArcRotateCameraVRDeviceOrientationInput.prototype.getSimpleName = function () {
return "VRDeviceOrientation";
};
return ArcRotateCameraVRDeviceOrientationInput;
}());
BABYLON.ArcRotateCameraVRDeviceOrientationInput = ArcRotateCameraVRDeviceOrientationInput;
BABYLON.CameraInputTypes["ArcRotateCameraVRDeviceOrientationInput"] = ArcRotateCameraVRDeviceOrientationInput;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.arcRotateCameraVRDeviceOrientationInput.js.map
var BABYLON;
(function (BABYLON) {
var VRCameraMetrics = /** @class */ (function () {
function VRCameraMetrics() {
this.compensateDistortion = true;
}
Object.defineProperty(VRCameraMetrics.prototype, "aspectRatio", {
get: function () {
return this.hResolution / (2 * this.vResolution);
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "aspectRatioFov", {
get: function () {
return (2 * Math.atan((this.postProcessScaleFactor * this.vScreenSize) / (2 * this.eyeToScreenDistance)));
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "leftHMatrix", {
get: function () {
var meters = (this.hScreenSize / 4) - (this.lensSeparationDistance / 2);
var h = (4 * meters) / this.hScreenSize;
return BABYLON.Matrix.Translation(h, 0, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "rightHMatrix", {
get: function () {
var meters = (this.hScreenSize / 4) - (this.lensSeparationDistance / 2);
var h = (4 * meters) / this.hScreenSize;
return BABYLON.Matrix.Translation(-h, 0, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "leftPreViewMatrix", {
get: function () {
return BABYLON.Matrix.Translation(0.5 * this.interpupillaryDistance, 0, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "rightPreViewMatrix", {
get: function () {
return BABYLON.Matrix.Translation(-0.5 * this.interpupillaryDistance, 0, 0);
},
enumerable: true,
configurable: true
});
VRCameraMetrics.GetDefault = function () {
var result = new VRCameraMetrics();
result.hResolution = 1280;
result.vResolution = 800;
result.hScreenSize = 0.149759993;
result.vScreenSize = 0.0935999975;
result.vScreenCenter = 0.0467999987;
result.eyeToScreenDistance = 0.0410000011;
result.lensSeparationDistance = 0.0635000020;
result.interpupillaryDistance = 0.0640000030;
result.distortionK = [1.0, 0.219999999, 0.239999995, 0.0];
result.chromaAbCorrection = [0.995999992, -0.00400000019, 1.01400006, 0.0];
result.postProcessScaleFactor = 1.714605507808412;
result.lensCenterOffset = 0.151976421;
return result;
};
return VRCameraMetrics;
}());
BABYLON.VRCameraMetrics = VRCameraMetrics;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.vrCameraMetrics.js.map
var BABYLON;
(function (BABYLON) {
/**
* This represents a WebVR camera.
* The WebVR camera is Babylon's simple interface to interaction with Windows Mixed Reality, HTC Vive and Oculus Rift.
* @example http://doc.babylonjs.com/how_to/webvr_camera
*/
var WebVRFreeCamera = /** @class */ (function (_super) {
__extends(WebVRFreeCamera, _super);
/**
* Instantiates a WebVRFreeCamera.
* @param name The name of the WebVRFreeCamera
* @param position The starting anchor position for the camera
* @param scene The scene the camera belongs to
* @param webVROptions a set of customizable options for the webVRCamera
*/
function WebVRFreeCamera(name, position, scene, webVROptions) {
if (webVROptions === void 0) { webVROptions = {}; }
var _this = _super.call(this, name, position, scene) || this;
_this.webVROptions = webVROptions;
/**
* The vrDisplay tied to the camera. See https://developer.mozilla.org/en-US/docs/Web/API/VRDisplay
*/
_this._vrDevice = null;
/**
* The rawPose of the vrDevice.
*/
_this.rawPose = null;
_this._specsVersion = "1.1";
_this._attached = false;
_this._descendants = [];
// Represents device position and rotation in room space. Should only be used to help calculate babylon space values
_this._deviceRoomPosition = BABYLON.Vector3.Zero();
_this._deviceRoomRotationQuaternion = BABYLON.Quaternion.Identity();
_this._standingMatrix = null;
/**
* Represents device position in babylon space.
*/
_this.devicePosition = BABYLON.Vector3.Zero();
/**
* Represents device rotation in babylon space.
*/
_this.deviceRotationQuaternion = BABYLON.Quaternion.Identity();
/**
* The scale of the device to be used when translating from device space to babylon space.
*/
_this.deviceScaleFactor = 1;
_this._deviceToWorld = BABYLON.Matrix.Identity();
_this._worldToDevice = BABYLON.Matrix.Identity();
/**
* References to the webVR controllers for the vrDevice.
*/
_this.controllers = [];
/**
* Emits an event when a controller is attached.
*/
_this.onControllersAttachedObservable = new BABYLON.Observable();
/**
* Emits an event when a controller's mesh has been loaded;
*/
_this.onControllerMeshLoadedObservable = new BABYLON.Observable();
/**
* If the rig cameras be used as parent instead of this camera.
*/
_this.rigParenting = true;
_this._defaultHeight = undefined;
_this._workingVector = BABYLON.Vector3.Zero();
_this._oneVector = BABYLON.Vector3.One();
_this._workingMatrix = BABYLON.Matrix.Identity();
_this._cache.position = BABYLON.Vector3.Zero();
if (webVROptions.defaultHeight) {
_this._defaultHeight = webVROptions.defaultHeight;
_this.position.y = _this._defaultHeight;
}
_this.minZ = 0.1;
//legacy support - the compensation boolean was removed.
if (arguments.length === 5) {
_this.webVROptions = arguments[4];
}
// default webVR options
if (_this.webVROptions.trackPosition == undefined) {
_this.webVROptions.trackPosition = true;
}
if (_this.webVROptions.controllerMeshes == undefined) {
_this.webVROptions.controllerMeshes = true;
}
if (_this.webVROptions.defaultLightingOnControllers == undefined) {
_this.webVROptions.defaultLightingOnControllers = true;
}
_this.rotationQuaternion = new BABYLON.Quaternion();
if (_this.webVROptions && _this.webVROptions.positionScale) {
_this.deviceScaleFactor = _this.webVROptions.positionScale;
}
//enable VR
var engine = _this.getEngine();
_this._onVREnabled = function (success) { if (success) {
_this.initControllers();
} };
engine.onVRRequestPresentComplete.add(_this._onVREnabled);
engine.initWebVR().add(function (event) {
if (!event.vrDisplay || _this._vrDevice === event.vrDisplay) {
return;
}
_this._vrDevice = event.vrDisplay;
//reset the rig parameters.
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_WEBVR, { parentCamera: _this, vrDisplay: _this._vrDevice, frameData: _this._frameData, specs: _this._specsVersion });
if (_this._attached) {
_this.getEngine().enableVR();
}
});
if (typeof (VRFrameData) !== "undefined")
_this._frameData = new VRFrameData();
/**
* The idea behind the following lines:
* objects that have the camera as parent should actually have the rig cameras as a parent.
* BUT, each of those cameras has a different view matrix, which means that if we set the parent to the first rig camera,
* the second will not show it correctly.
*
* To solve this - each object that has the camera as parent will be added to a protected array.
* When the rig camera renders, it will take this array and set all of those to be its children.
* This way, the right camera will be used as a parent, and the mesh will be rendered correctly.
* Amazing!
*/
scene.onBeforeCameraRenderObservable.add(function (camera) {
if (camera.parent === _this && _this.rigParenting) {
_this._descendants = _this.getDescendants(true, function (n) {
// don't take the cameras or the controllers!
var isController = _this.controllers.some(function (controller) { return controller._mesh === n; });
var isRigCamera = _this._rigCameras.indexOf(n) !== -1;
return !isController && !isRigCamera;
});
_this._descendants.forEach(function (node) {
node.parent = camera;
});
}
});
scene.onAfterCameraRenderObservable.add(function (camera) {
if (camera.parent === _this && _this.rigParenting) {
_this._descendants.forEach(function (node) {
node.parent = _this;
});
}
});
return _this;
}
/**
* Gets the device distance from the ground in meters.
* @returns the distance in meters from the vrDevice to ground in device space. If standing matrix is not supported for the vrDevice 0 is returned.
*/
WebVRFreeCamera.prototype.deviceDistanceToRoomGround = function () {
if (this._standingMatrix) {
// Add standing matrix offset to get real offset from ground in room
this._standingMatrix.getTranslationToRef(this._workingVector);
return this._deviceRoomPosition.y + this._workingVector.y;
}
//If VRDisplay does not inform stage parameters and no default height is set we fallback to zero.
return this._defaultHeight || 0;
};
/**
* Enables the standing matrix when supported. This can be used to position the user's view the correct height from the ground.
* @param callback will be called when the standing matrix is set. Callback parameter is if the standing matrix is supported.
*/
WebVRFreeCamera.prototype.useStandingMatrix = function (callback) {
var _this = this;
if (callback === void 0) { callback = function (bool) { }; }
// Use standing matrix if available
this.getEngine().initWebVRAsync().then(function (result) {
if (!result.vrDisplay || !result.vrDisplay.stageParameters || !result.vrDisplay.stageParameters.sittingToStandingTransform) {
callback(false);
}
else {
_this._standingMatrix = new BABYLON.Matrix();
BABYLON.Matrix.FromFloat32ArrayToRefScaled(result.vrDisplay.stageParameters.sittingToStandingTransform, 0, 1, _this._standingMatrix);
if (!_this.getScene().useRightHandedSystem) {
[2, 6, 8, 9, 14].forEach(function (num) {
if (_this._standingMatrix) {
_this._standingMatrix.m[num] *= -1;
}
});
}
callback(true);
}
});
};
/**
* Enables the standing matrix when supported. This can be used to position the user's view the correct height from the ground.
* @returns A promise with a boolean set to if the standing matrix is supported.
*/
WebVRFreeCamera.prototype.useStandingMatrixAsync = function () {
var _this = this;
return new Promise(function (res, rej) {
_this.useStandingMatrix(function (supported) {
res(supported);
});
});
};
/**
* Disposes the camera
*/
WebVRFreeCamera.prototype.dispose = function () {
this.getEngine().onVRRequestPresentComplete.removeCallback(this._onVREnabled);
_super.prototype.dispose.call(this);
};
/**
* Gets a vrController by name.
* @param name The name of the controller to retreive
* @returns the controller matching the name specified or null if not found
*/
WebVRFreeCamera.prototype.getControllerByName = function (name) {
for (var _i = 0, _a = this.controllers; _i < _a.length; _i++) {
var gp = _a[_i];
if (gp.hand === name) {
return gp;
}
}
return null;
};
Object.defineProperty(WebVRFreeCamera.prototype, "leftController", {
/**
* The controller corrisponding to the users left hand.
*/
get: function () {
if (!this._leftController) {
this._leftController = this.getControllerByName("left");
}
return this._leftController;
},
enumerable: true,
configurable: true
});
;
Object.defineProperty(WebVRFreeCamera.prototype, "rightController", {
/**
* The controller corrisponding to the users right hand.
*/
get: function () {
if (!this._rightController) {
this._rightController = this.getControllerByName("right");
}
return this._rightController;
},
enumerable: true,
configurable: true
});
;
/**
* Casts a ray forward from the vrCamera's gaze.
* @param length Length of the ray (default: 100)
* @returns the ray corrisponding to the gaze
*/
WebVRFreeCamera.prototype.getForwardRay = function (length) {
if (length === void 0) { length = 100; }
if (this.leftCamera) {
// Use left eye to avoid computation to compute center on every call
return _super.prototype.getForwardRay.call(this, length, this.leftCamera.getWorldMatrix(), this.leftCamera.globalPosition); // Need the actual rendered camera
}
else {
return _super.prototype.getForwardRay.call(this, length);
}
};
/**
* Updates the camera based on device's frame data
*/
WebVRFreeCamera.prototype._checkInputs = function () {
if (this._vrDevice && this._vrDevice.isPresenting) {
this._vrDevice.getFrameData(this._frameData);
this.updateFromDevice(this._frameData.pose);
}
_super.prototype._checkInputs.call(this);
};
/**
* Updates the poseControlled values based on the input device pose.
* @param poseData Pose coming from the device
*/
WebVRFreeCamera.prototype.updateFromDevice = function (poseData) {
if (poseData && poseData.orientation) {
this.rawPose = poseData;
this._deviceRoomRotationQuaternion.copyFromFloats(poseData.orientation[0], poseData.orientation[1], -poseData.orientation[2], -poseData.orientation[3]);
if (this.getScene().useRightHandedSystem) {
this._deviceRoomRotationQuaternion.z *= -1;
this._deviceRoomRotationQuaternion.w *= -1;
}
if (this.webVROptions.trackPosition && this.rawPose.position) {
this._deviceRoomPosition.copyFromFloats(this.rawPose.position[0], this.rawPose.position[1], -this.rawPose.position[2]);
if (this.getScene().useRightHandedSystem) {
this._deviceRoomPosition.z *= -1;
}
}
}
};
/**
* WebVR's attach control will start broadcasting frames to the device.
* Note that in certain browsers (chrome for example) this function must be called
* within a user-interaction callback. Example:
* scene.onPointerDown = function() { camera.attachControl(canvas); }
*
* @param element html element to attach the vrDevice to
* @param noPreventDefault prevent the default html element operation when attaching the vrDevice
*/
WebVRFreeCamera.prototype.attachControl = function (element, noPreventDefault) {
_super.prototype.attachControl.call(this, element, noPreventDefault);
this._attached = true;
noPreventDefault = BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
if (this._vrDevice) {
this.getEngine().enableVR();
}
};
/**
* Detaches the camera from the html element and disables VR
*
* @param element html element to detach from
*/
WebVRFreeCamera.prototype.detachControl = function (element) {
this.getScene().gamepadManager.onGamepadConnectedObservable.remove(this._onGamepadConnectedObserver);
this.getScene().gamepadManager.onGamepadDisconnectedObservable.remove(this._onGamepadDisconnectedObserver);
_super.prototype.detachControl.call(this, element);
this._attached = false;
this.getEngine().disableVR();
};
/**
* @returns the name of this class
*/
WebVRFreeCamera.prototype.getClassName = function () {
return "WebVRFreeCamera";
};
/**
* Calls resetPose on the vrDisplay
* See: https://developer.mozilla.org/en-US/docs/Web/API/VRDisplay/resetPose
*/
WebVRFreeCamera.prototype.resetToCurrentRotation = function () {
//uses the vrDisplay's "resetPose()".
//pitch and roll won't be affected.
this._vrDevice.resetPose();
};
/**
* Updates the rig cameras (left and right eye)
*/
WebVRFreeCamera.prototype._updateRigCameras = function () {
var camLeft = this._rigCameras[0];
var camRight = this._rigCameras[1];
camLeft.rotationQuaternion.copyFrom(this._deviceRoomRotationQuaternion);
camRight.rotationQuaternion.copyFrom(this._deviceRoomRotationQuaternion);
camLeft.position.copyFrom(this._deviceRoomPosition);
camRight.position.copyFrom(this._deviceRoomPosition);
};
/**
* Updates the cached values of the camera
* @param ignoreParentClass ignores updating the parent class's cache (default: false)
*/
WebVRFreeCamera.prototype._updateCache = function (ignoreParentClass) {
var _this = this;
if (!this.rotationQuaternion.equals(this._cache.rotationQuaternion) || !this.position.equals(this._cache.position)) {
// Update to ensure devicePosition is up to date with most recent _deviceRoomPosition
if (!this.updateCacheCalled) {
// make sure it is only called once per loop. this.update() might cause an infinite loop.
this.updateCacheCalled = true;
this.update();
}
// Set working vector to the device position in room space rotated by the new rotation
this.rotationQuaternion.toRotationMatrix(this._workingMatrix);
BABYLON.Vector3.TransformCoordinatesToRef(this._deviceRoomPosition, this._workingMatrix, this._workingVector);
// Subtract this vector from the current device position in world to get the translation for the device world matrix
this.devicePosition.subtractToRef(this._workingVector, this._workingVector);
BABYLON.Matrix.ComposeToRef(this._oneVector, this.rotationQuaternion, this._workingVector, this._deviceToWorld);
// Add translation from anchor position
this._deviceToWorld.getTranslationToRef(this._workingVector);
this._workingVector.addInPlace(this.position);
this._workingVector.subtractInPlace(this._cache.position);
this._deviceToWorld.setTranslation(this._workingVector);
// Set an inverted matrix to be used when updating the camera
this._deviceToWorld.invertToRef(this._worldToDevice);
// Update the gamepad to ensure the mesh is updated on the same frame as camera
this.controllers.forEach(function (controller) {
controller._deviceToWorld.copyFrom(_this._deviceToWorld);
controller.update();
});
}
if (!ignoreParentClass) {
_super.prototype._updateCache.call(this);
}
this.updateCacheCalled = false;
};
/**
* Updates the current device position and rotation in the babylon world
*/
WebVRFreeCamera.prototype.update = function () {
// Get current device position in babylon world
BABYLON.Vector3.TransformCoordinatesToRef(this._deviceRoomPosition, this._deviceToWorld, this.devicePosition);
// Get current device rotation in babylon world
BABYLON.Matrix.FromQuaternionToRef(this._deviceRoomRotationQuaternion, this._workingMatrix);
this._workingMatrix.multiplyToRef(this._deviceToWorld, this._workingMatrix);
BABYLON.Quaternion.FromRotationMatrixToRef(this._workingMatrix, this.deviceRotationQuaternion);
_super.prototype.update.call(this);
};
/**
* Gets the view matrix of this camera (Always set to identity as left and right eye cameras contain the actual view matrix)
* @returns an identity matrix
*/
WebVRFreeCamera.prototype._getViewMatrix = function () {
return BABYLON.Matrix.Identity();
};
/**
* This function is called by the two RIG cameras.
* 'this' is the left or right camera (and NOT (!!!) the WebVRFreeCamera instance)
*/
WebVRFreeCamera.prototype._getWebVRViewMatrix = function () {
var _this = this;
// Update the parent camera prior to using a child camera to avoid desynchronization
var parentCamera = this._cameraRigParams["parentCamera"];
parentCamera._updateCache();
//WebVR 1.1
var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
BABYLON.Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
if (!this.getScene().useRightHandedSystem) {
[2, 6, 8, 9, 14].forEach(function (num) {
_this._webvrViewMatrix.m[num] *= -1;
});
}
// update the camera rotation matrix
this._webvrViewMatrix.getRotationMatrixToRef(this._cameraRotationMatrix);
BABYLON.Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
// Computing target and final matrix
this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
// should the view matrix be updated with scale and position offset?
if (parentCamera.deviceScaleFactor !== 1) {
this._webvrViewMatrix.invert();
// scale the position, if set
if (parentCamera.deviceScaleFactor) {
this._webvrViewMatrix.m[12] *= parentCamera.deviceScaleFactor;
this._webvrViewMatrix.m[13] *= parentCamera.deviceScaleFactor;
this._webvrViewMatrix.m[14] *= parentCamera.deviceScaleFactor;
}
this._webvrViewMatrix.invert();
}
parentCamera._worldToDevice.multiplyToRef(this._webvrViewMatrix, this._webvrViewMatrix);
// Compute global position
this._workingMatrix = this._workingMatrix || BABYLON.Matrix.Identity();
this._webvrViewMatrix.invertToRef(this._workingMatrix);
this._workingMatrix.multiplyToRef(parentCamera.getWorldMatrix(), this._workingMatrix);
this._workingMatrix.getTranslationToRef(this._globalPosition);
this._markSyncedWithParent();
return this._webvrViewMatrix;
};
WebVRFreeCamera.prototype._getWebVRProjectionMatrix = function () {
var _this = this;
var parentCamera = this.parent;
parentCamera._vrDevice.depthNear = parentCamera.minZ;
parentCamera._vrDevice.depthFar = parentCamera.maxZ;
var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
BABYLON.Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
//babylon compatible matrix
if (!this.getScene().useRightHandedSystem) {
[8, 9, 10, 11].forEach(function (num) {
_this._projectionMatrix.m[num] *= -1;
});
}
return this._projectionMatrix;
};
/**
* Initializes the controllers and their meshes
*/
WebVRFreeCamera.prototype.initControllers = function () {
var _this = this;
this.controllers = [];
var manager = this.getScene().gamepadManager;
this._onGamepadDisconnectedObserver = manager.onGamepadDisconnectedObservable.add(function (gamepad) {
if (gamepad.type === BABYLON.Gamepad.POSE_ENABLED) {
var webVrController = gamepad;
if (webVrController.defaultModel) {
webVrController.defaultModel.setEnabled(false);
}
if (webVrController.hand === "right") {
_this._rightController = null;
}
if (webVrController.hand === "left") {
_this._leftController = null;
}
var controllerIndex = _this.controllers.indexOf(webVrController);
if (controllerIndex !== -1) {
_this.controllers.splice(controllerIndex, 1);
}
}
});
this._onGamepadConnectedObserver = manager.onGamepadConnectedObservable.add(function (gamepad) {
if (gamepad.type === BABYLON.Gamepad.POSE_ENABLED) {
var webVrController_1 = gamepad;
webVrController_1.deviceScaleFactor = _this.deviceScaleFactor;
webVrController_1._deviceToWorld.copyFrom(_this._deviceToWorld);
if (_this.webVROptions.controllerMeshes) {
if (webVrController_1.defaultModel) {
webVrController_1.defaultModel.setEnabled(true);
}
else {
// Load the meshes
webVrController_1.initControllerMesh(_this.getScene(), function (loadedMesh) {
loadedMesh.scaling.scaleInPlace(_this.deviceScaleFactor);
_this.onControllerMeshLoadedObservable.notifyObservers(webVrController_1);
if (_this.webVROptions.defaultLightingOnControllers) {
if (!_this._lightOnControllers) {
_this._lightOnControllers = new BABYLON.HemisphericLight("vrControllersLight", new BABYLON.Vector3(0, 1, 0), _this.getScene());
}
var activateLightOnSubMeshes_1 = function (mesh, light) {
var children = mesh.getChildren();
if (children.length !== 0) {
children.forEach(function (mesh) {
light.includedOnlyMeshes.push(mesh);
activateLightOnSubMeshes_1(mesh, light);
});
}
};
_this._lightOnControllers.includedOnlyMeshes.push(loadedMesh);
activateLightOnSubMeshes_1(loadedMesh, _this._lightOnControllers);
}
});
}
}
webVrController_1.attachToPoseControlledCamera(_this);
// since this is async - sanity check. Is the controller already stored?
if (_this.controllers.indexOf(webVrController_1) === -1) {
//add to the controllers array
_this.controllers.push(webVrController_1);
// Forced to add some control code for Vive as it doesn't always fill properly the "hand" property
// Sometimes, both controllers are set correctly (left and right), sometimes none, sometimes only one of them...
// So we're overriding setting left & right manually to be sure
var firstViveWandDetected = false;
for (var i = 0; i < _this.controllers.length; i++) {
if (_this.controllers[i].controllerType === BABYLON.PoseEnabledControllerType.VIVE) {
if (!firstViveWandDetected) {
firstViveWandDetected = true;
_this.controllers[i].hand = "left";
}
else {
_this.controllers[i].hand = "right";
}
}
}
//did we find enough controllers? Great! let the developer know.
if (_this.controllers.length >= 2) {
_this.onControllersAttachedObservable.notifyObservers(_this.controllers);
}
}
}
});
};
return WebVRFreeCamera;
}(BABYLON.FreeCamera));
BABYLON.WebVRFreeCamera = WebVRFreeCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.webVRCamera.js.map
var BABYLON;
(function (BABYLON) {
// We're mainly based on the logic defined into the FreeCamera code
/**
* This is a camera specifically designed to react to device orientation events such as a modern mobile device
* being tilted forward or back and left or right.
*/
var DeviceOrientationCamera = /** @class */ (function (_super) {
__extends(DeviceOrientationCamera, _super);
/**
* Creates a new device orientation camera
* @param name The name of the camera
* @param position The start position camera
* @param scene The scene the camera belongs to
*/
function DeviceOrientationCamera(name, position, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this._quaternionCache = new BABYLON.Quaternion();
_this.inputs.addDeviceOrientation();
return _this;
}
/**
* Gets the current instance class name ("DeviceOrientationCamera").
* This helps avoiding instanceof at run time.
* @returns the class name
*/
DeviceOrientationCamera.prototype.getClassName = function () {
return "DeviceOrientationCamera";
};
/**
* Checks and applies the current values of the inputs to the camera. (Internal use only)
*/
DeviceOrientationCamera.prototype._checkInputs = function () {
_super.prototype._checkInputs.call(this);
this._quaternionCache.copyFrom(this.rotationQuaternion);
if (this._initialQuaternion) {
this._initialQuaternion.multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
}
};
/**
* Reset the camera to its default orientation on the specified axis only.
* @param axis The axis to reset
*/
DeviceOrientationCamera.prototype.resetToCurrentRotation = function (axis) {
var _this = this;
if (axis === void 0) { axis = BABYLON.Axis.Y; }
//can only work if this camera has a rotation quaternion already.
if (!this.rotationQuaternion)
return;
if (!this._initialQuaternion) {
this._initialQuaternion = new BABYLON.Quaternion();
}
this._initialQuaternion.copyFrom(this._quaternionCache || this.rotationQuaternion);
['x', 'y', 'z'].forEach(function (axisName) {
if (!axis[axisName]) {
_this._initialQuaternion[axisName] = 0;
}
else {
_this._initialQuaternion[axisName] *= -1;
}
});
this._initialQuaternion.normalize();
//force rotation update
this._initialQuaternion.multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
};
return DeviceOrientationCamera;
}(BABYLON.FreeCamera));
BABYLON.DeviceOrientationCamera = DeviceOrientationCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.deviceOrientationCamera.js.map
var BABYLON;
(function (BABYLON) {
var VRDeviceOrientationFreeCamera = /** @class */ (function (_super) {
__extends(VRDeviceOrientationFreeCamera, _super);
function VRDeviceOrientationFreeCamera(name, position, scene, compensateDistortion, vrCameraMetrics) {
if (compensateDistortion === void 0) { compensateDistortion = true; }
if (vrCameraMetrics === void 0) { vrCameraMetrics = BABYLON.VRCameraMetrics.GetDefault(); }
var _this = _super.call(this, name, position, scene) || this;
vrCameraMetrics.compensateDistortion = compensateDistortion;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_VR, { vrCameraMetrics: vrCameraMetrics });
return _this;
}
VRDeviceOrientationFreeCamera.prototype.getClassName = function () {
return "VRDeviceOrientationFreeCamera";
};
return VRDeviceOrientationFreeCamera;
}(BABYLON.DeviceOrientationCamera));
BABYLON.VRDeviceOrientationFreeCamera = VRDeviceOrientationFreeCamera;
var VRDeviceOrientationGamepadCamera = /** @class */ (function (_super) {
__extends(VRDeviceOrientationGamepadCamera, _super);
function VRDeviceOrientationGamepadCamera(name, position, scene, compensateDistortion, vrCameraMetrics) {
if (compensateDistortion === void 0) { compensateDistortion = true; }
if (vrCameraMetrics === void 0) { vrCameraMetrics = BABYLON.VRCameraMetrics.GetDefault(); }
var _this = _super.call(this, name, position, scene, compensateDistortion, vrCameraMetrics) || this;
_this.inputs.addGamepad();
return _this;
}
VRDeviceOrientationGamepadCamera.prototype.getClassName = function () {
return "VRDeviceOrientationGamepadCamera";
};
return VRDeviceOrientationGamepadCamera;
}(VRDeviceOrientationFreeCamera));
BABYLON.VRDeviceOrientationGamepadCamera = VRDeviceOrientationGamepadCamera;
var VRDeviceOrientationArcRotateCamera = /** @class */ (function (_super) {
__extends(VRDeviceOrientationArcRotateCamera, _super);
function VRDeviceOrientationArcRotateCamera(name, alpha, beta, radius, target, scene, compensateDistortion, vrCameraMetrics) {
if (compensateDistortion === void 0) { compensateDistortion = true; }
if (vrCameraMetrics === void 0) { vrCameraMetrics = BABYLON.VRCameraMetrics.GetDefault(); }
var _this = _super.call(this, name, alpha, beta, radius, target, scene) || this;
vrCameraMetrics.compensateDistortion = compensateDistortion;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_VR, { vrCameraMetrics: vrCameraMetrics });
_this.inputs.addVRDeviceOrientation();
return _this;
}
VRDeviceOrientationArcRotateCamera.prototype.getClassName = function () {
return "VRDeviceOrientationArcRotateCamera";
};
return VRDeviceOrientationArcRotateCamera;
}(BABYLON.ArcRotateCamera));
BABYLON.VRDeviceOrientationArcRotateCamera = VRDeviceOrientationArcRotateCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.vrDeviceOrientationCamera.js.map
var BABYLON;
(function (BABYLON) {
/**
* Camera used to simulate anaglyphic rendering (based on FreeCamera)
*/
var AnaglyphFreeCamera = /** @class */ (function (_super) {
__extends(AnaglyphFreeCamera, _super);
/**
* Creates a new AnaglyphFreeCamera
* @param name defines camera name
* @param position defines initial position
* @param interaxialDistance defines distance between each color axis
* @param scene defines the hosting scene
*/
function AnaglyphFreeCamera(name, position, interaxialDistance, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
return _this;
}
/**
* Gets camera class name
* @returns AnaglyphFreeCamera
*/
AnaglyphFreeCamera.prototype.getClassName = function () {
return "AnaglyphFreeCamera";
};
return AnaglyphFreeCamera;
}(BABYLON.FreeCamera));
BABYLON.AnaglyphFreeCamera = AnaglyphFreeCamera;
/**
* Camera used to simulate anaglyphic rendering (based on ArcRotateCamera)
*/
var AnaglyphArcRotateCamera = /** @class */ (function (_super) {
__extends(AnaglyphArcRotateCamera, _super);
/**
* Creates a new AnaglyphArcRotateCamera
* @param name defines camera name
* @param alpha defines alpha angle (in radians)
* @param beta defines beta angle (in radians)
* @param radius defines radius
* @param target defines camera target
* @param interaxialDistance defines distance between each color axis
* @param scene defines the hosting scene
*/
function AnaglyphArcRotateCamera(name, alpha, beta, radius, target, interaxialDistance, scene) {
var _this = _super.call(this, name, alpha, beta, radius, target, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
return _this;
}
/**
* Gets camera class name
* @returns AnaglyphArcRotateCamera
*/
AnaglyphArcRotateCamera.prototype.getClassName = function () {
return "AnaglyphArcRotateCamera";
};
return AnaglyphArcRotateCamera;
}(BABYLON.ArcRotateCamera));
BABYLON.AnaglyphArcRotateCamera = AnaglyphArcRotateCamera;
/**
* Camera used to simulate anaglyphic rendering (based on GamepadCamera)
*/
var AnaglyphGamepadCamera = /** @class */ (function (_super) {
__extends(AnaglyphGamepadCamera, _super);
/**
* Creates a new AnaglyphGamepadCamera
* @param name defines camera name
* @param position defines initial position
* @param interaxialDistance defines distance between each color axis
* @param scene defines the hosting scene
*/
function AnaglyphGamepadCamera(name, position, interaxialDistance, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
return _this;
}
/**
* Gets camera class name
* @returns AnaglyphGamepadCamera
*/
AnaglyphGamepadCamera.prototype.getClassName = function () {
return "AnaglyphGamepadCamera";
};
return AnaglyphGamepadCamera;
}(BABYLON.GamepadCamera));
BABYLON.AnaglyphGamepadCamera = AnaglyphGamepadCamera;
/**
* Camera used to simulate anaglyphic rendering (based on UniversalCamera)
*/
var AnaglyphUniversalCamera = /** @class */ (function (_super) {
__extends(AnaglyphUniversalCamera, _super);
/**
* Creates a new AnaglyphUniversalCamera
* @param name defines camera name
* @param position defines initial position
* @param interaxialDistance defines distance between each color axis
* @param scene defines the hosting scene
*/
function AnaglyphUniversalCamera(name, position, interaxialDistance, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
return _this;
}
/**
* Gets camera class name
* @returns AnaglyphUniversalCamera
*/
AnaglyphUniversalCamera.prototype.getClassName = function () {
return "AnaglyphUniversalCamera";
};
return AnaglyphUniversalCamera;
}(BABYLON.UniversalCamera));
BABYLON.AnaglyphUniversalCamera = AnaglyphUniversalCamera;
/**
* Camera used to simulate stereoscopic rendering (based on FreeCamera)
*/
var StereoscopicFreeCamera = /** @class */ (function (_super) {
__extends(StereoscopicFreeCamera, _super);
/**
* Creates a new StereoscopicFreeCamera
* @param name defines camera name
* @param position defines initial position
* @param interaxialDistance defines distance between each color axis
* @param isStereoscopicSideBySide defines is stereoscopic is done side by side or over under
* @param scene defines the hosting scene
*/
function StereoscopicFreeCamera(name, position, interaxialDistance, isStereoscopicSideBySide, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.isStereoscopicSideBySide = isStereoscopicSideBySide;
_this.setCameraRigMode(isStereoscopicSideBySide ? BABYLON.Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : BABYLON.Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
return _this;
}
/**
* Gets camera class name
* @returns StereoscopicFreeCamera
*/
StereoscopicFreeCamera.prototype.getClassName = function () {
return "StereoscopicFreeCamera";
};
return StereoscopicFreeCamera;
}(BABYLON.FreeCamera));
BABYLON.StereoscopicFreeCamera = StereoscopicFreeCamera;
/**
* Camera used to simulate stereoscopic rendering (based on ArcRotateCamera)
*/
var StereoscopicArcRotateCamera = /** @class */ (function (_super) {
__extends(StereoscopicArcRotateCamera, _super);
/**
* Creates a new StereoscopicArcRotateCamera
* @param name defines camera name
* @param alpha defines alpha angle (in radians)
* @param beta defines beta angle (in radians)
* @param radius defines radius
* @param target defines camera target
* @param interaxialDistance defines distance between each color axis
* @param isStereoscopicSideBySide defines is stereoscopic is done side by side or over under
* @param scene defines the hosting scene
*/
function StereoscopicArcRotateCamera(name, alpha, beta, radius, target, interaxialDistance, isStereoscopicSideBySide, scene) {
var _this = _super.call(this, name, alpha, beta, radius, target, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.isStereoscopicSideBySide = isStereoscopicSideBySide;
_this.setCameraRigMode(isStereoscopicSideBySide ? BABYLON.Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : BABYLON.Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
return _this;
}
/**
* Gets camera class name
* @returns StereoscopicArcRotateCamera
*/
StereoscopicArcRotateCamera.prototype.getClassName = function () {
return "StereoscopicArcRotateCamera";
};
return StereoscopicArcRotateCamera;
}(BABYLON.ArcRotateCamera));
BABYLON.StereoscopicArcRotateCamera = StereoscopicArcRotateCamera;
/**
* Camera used to simulate stereoscopic rendering (based on GamepadCamera)
*/
var StereoscopicGamepadCamera = /** @class */ (function (_super) {
__extends(StereoscopicGamepadCamera, _super);
/**
* Creates a new StereoscopicGamepadCamera
* @param name defines camera name
* @param position defines initial position
* @param interaxialDistance defines distance between each color axis
* @param isStereoscopicSideBySide defines is stereoscopic is done side by side or over under
* @param scene defines the hosting scene
*/
function StereoscopicGamepadCamera(name, position, interaxialDistance, isStereoscopicSideBySide, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.isStereoscopicSideBySide = isStereoscopicSideBySide;
_this.setCameraRigMode(isStereoscopicSideBySide ? BABYLON.Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : BABYLON.Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
return _this;
}
/**
* Gets camera class name
* @returns StereoscopicGamepadCamera
*/
StereoscopicGamepadCamera.prototype.getClassName = function () {
return "StereoscopicGamepadCamera";
};
return StereoscopicGamepadCamera;
}(BABYLON.GamepadCamera));
BABYLON.StereoscopicGamepadCamera = StereoscopicGamepadCamera;
/**
* Camera used to simulate stereoscopic rendering (based on UniversalCamera)
*/
var StereoscopicUniversalCamera = /** @class */ (function (_super) {
__extends(StereoscopicUniversalCamera, _super);
/**
* Creates a new StereoscopicUniversalCamera
* @param name defines camera name
* @param position defines initial position
* @param interaxialDistance defines distance between each color axis
* @param isStereoscopicSideBySide defines is stereoscopic is done side by side or over under
* @param scene defines the hosting scene
*/
function StereoscopicUniversalCamera(name, position, interaxialDistance, isStereoscopicSideBySide, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.isStereoscopicSideBySide = isStereoscopicSideBySide;
_this.setCameraRigMode(isStereoscopicSideBySide ? BABYLON.Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : BABYLON.Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
return _this;
}
/**
* Gets camera class name
* @returns StereoscopicUniversalCamera
*/
StereoscopicUniversalCamera.prototype.getClassName = function () {
return "StereoscopicUniversalCamera";
};
return StereoscopicUniversalCamera;
}(BABYLON.UniversalCamera));
BABYLON.StereoscopicUniversalCamera = StereoscopicUniversalCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.stereoscopicCameras.js.map
var BABYLON;
(function (BABYLON) {
var VRExperienceHelperGazer = /** @class */ (function () {
function VRExperienceHelperGazer(scene, gazeTrackerToClone) {
if (gazeTrackerToClone === void 0) { gazeTrackerToClone = null; }
this.scene = scene;
this._pointerDownOnMeshAsked = false;
this._isActionableMesh = false;
this._teleportationRequestInitiated = false;
this._teleportationBackRequestInitiated = false;
this._dpadPressed = true;
this._activePointer = false;
this._id = VRExperienceHelperGazer._idCounter++;
// Gaze tracker
if (!gazeTrackerToClone) {
this._gazeTracker = BABYLON.Mesh.CreateTorus("gazeTracker", 0.0035, 0.0025, 20, scene, false);
this._gazeTracker.bakeCurrentTransformIntoVertices();
this._gazeTracker.isPickable = false;
this._gazeTracker.isVisible = false;
var targetMat = new BABYLON.StandardMaterial("targetMat", scene);
targetMat.specularColor = BABYLON.Color3.Black();
targetMat.emissiveColor = new BABYLON.Color3(0.7, 0.7, 0.7);
targetMat.backFaceCulling = false;
this._gazeTracker.material = targetMat;
}
else {
this._gazeTracker = gazeTrackerToClone.clone("gazeTracker");
}
}
VRExperienceHelperGazer.prototype._getForwardRay = function (length) {
return new BABYLON.Ray(BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, 0, length));
};
VRExperienceHelperGazer.prototype._selectionPointerDown = function () {
this._pointerDownOnMeshAsked = true;
if (this._currentMeshSelected && this._currentHit) {
this.scene.simulatePointerDown(this._currentHit, { pointerId: this._id });
}
};
VRExperienceHelperGazer.prototype._selectionPointerUp = function () {
if (this._currentMeshSelected && this._currentHit) {
this.scene.simulatePointerUp(this._currentHit, { pointerId: this._id });
}
this._pointerDownOnMeshAsked = false;
};
VRExperienceHelperGazer.prototype._activatePointer = function () {
this._activePointer = true;
};
VRExperienceHelperGazer.prototype._deactivatePointer = function () {
this._activePointer = false;
};
VRExperienceHelperGazer.prototype._updatePointerDistance = function (distance) {
};
VRExperienceHelperGazer.prototype.dispose = function () {
this._interactionsEnabled = false;
this._teleportationEnabled = false;
};
VRExperienceHelperGazer._idCounter = 0;
return VRExperienceHelperGazer;
}());
var VRExperienceHelperControllerGazer = /** @class */ (function (_super) {
__extends(VRExperienceHelperControllerGazer, _super);
function VRExperienceHelperControllerGazer(webVRController, scene, gazeTrackerToClone) {
var _this = _super.call(this, scene, gazeTrackerToClone) || this;
_this.webVRController = webVRController;
// Laser pointer
_this._laserPointer = BABYLON.Mesh.CreateCylinder("laserPointer", 1, 0.004, 0.0002, 20, 1, scene, false);
var laserPointerMaterial = new BABYLON.StandardMaterial("laserPointerMat", scene);
laserPointerMaterial.emissiveColor = new BABYLON.Color3(0.7, 0.7, 0.7);
laserPointerMaterial.alpha = 0.6;
_this._laserPointer.material = laserPointerMaterial;
_this._laserPointer.rotation.x = Math.PI / 2;
_this._laserPointer.position.z = -0.5;
_this._laserPointer.isVisible = false;
if (!webVRController.mesh) {
// Create an empty mesh that is used prior to loading the high quality model
var preloadMesh = new BABYLON.Mesh("preloadControllerMesh", scene);
var preloadPointerPose = new BABYLON.Mesh(BABYLON.PoseEnabledController.POINTING_POSE, scene);
preloadPointerPose.rotation.x = -0.7;
preloadMesh.addChild(preloadPointerPose);
webVRController.attachToMesh(preloadMesh);
}
_this._setLaserPointerParent(webVRController.mesh);
_this._meshAttachedObserver = webVRController._meshAttachedObservable.add(function (mesh) {
_this._setLaserPointerParent(mesh);
});
return _this;
}
VRExperienceHelperControllerGazer.prototype._getForwardRay = function (length) {
return this.webVRController.getForwardRay(length);
};
VRExperienceHelperControllerGazer.prototype._activatePointer = function () {
_super.prototype._activatePointer.call(this);
this._laserPointer.isVisible = true;
};
VRExperienceHelperControllerGazer.prototype._deactivatePointer = function () {
_super.prototype._deactivatePointer.call(this);
this._laserPointer.isVisible = false;
};
VRExperienceHelperControllerGazer.prototype._setLaserPointerColor = function (color) {
this._laserPointer.material.emissiveColor = color;
};
VRExperienceHelperControllerGazer.prototype._setLaserPointerParent = function (mesh) {
var makeNotPick = function (root) {
root.name += " laserPointer";
root.getChildMeshes().forEach(function (c) {
makeNotPick(c);
});
};
makeNotPick(mesh);
var childMeshes = mesh.getChildMeshes();
this.webVRController._pointingPoseNode = null;
for (var i = 0; i < childMeshes.length; i++) {
if (childMeshes[i].name && childMeshes[i].name.indexOf(BABYLON.PoseEnabledController.POINTING_POSE) >= 0) {
mesh = childMeshes[i];
this.webVRController._pointingPoseNode = mesh;
break;
}
}
this._laserPointer.parent = mesh;
};
VRExperienceHelperControllerGazer.prototype._updatePointerDistance = function (distance) {
this._laserPointer.scaling.y = distance;
this._laserPointer.position.z = -distance / 2;
};
VRExperienceHelperControllerGazer.prototype.dispose = function () {
_super.prototype.dispose.call(this);
this._laserPointer.dispose();
if (this._meshAttachedObserver) {
this.webVRController._meshAttachedObservable.remove(this._meshAttachedObserver);
}
};
return VRExperienceHelperControllerGazer;
}(VRExperienceHelperGazer));
var VRExperienceHelperCameraGazer = /** @class */ (function (_super) {
__extends(VRExperienceHelperCameraGazer, _super);
function VRExperienceHelperCameraGazer(getCamera, scene) {
var _this = _super.call(this, scene) || this;
_this.getCamera = getCamera;
return _this;
}
VRExperienceHelperCameraGazer.prototype._getForwardRay = function (length) {
var camera = this.getCamera();
if (camera) {
return camera.getForwardRay(length);
}
else {
return new BABYLON.Ray(BABYLON.Vector3.Zero(), BABYLON.Vector3.Forward());
}
};
return VRExperienceHelperCameraGazer;
}(VRExperienceHelperGazer));
/**
* Helps to quickly add VR support to an existing scene.
* See http://doc.babylonjs.com/how_to/webvr_helper
*/
var VRExperienceHelper = /** @class */ (function () {
/**
* Instantiates a VRExperienceHelper.
* Helps to quickly add VR support to an existing scene.
* @param scene The scene the VRExperienceHelper belongs to.
* @param webVROptions Options to modify the vr experience helper's behavior.
*/
function VRExperienceHelper(scene, /** Options to modify the vr experience helper's behavior. */ webVROptions) {
if (webVROptions === void 0) { webVROptions = {}; }
var _this = this;
this.webVROptions = webVROptions;
// Can the system support WebVR, even if a headset isn't plugged in?
this._webVRsupported = false;
// If WebVR is supported, is a headset plugged in and are we ready to present?
this._webVRready = false;
// Are we waiting for the requestPresent callback to complete?
this._webVRrequesting = false;
// Are we presenting to the headset right now?
this._webVRpresenting = false;
// Are we presenting in the fullscreen fallback?
this._fullscreenVRpresenting = false;
/**
* Observable raised when entering VR.
*/
this.onEnteringVRObservable = new BABYLON.Observable();
/**
* Observable raised when exiting VR.
*/
this.onExitingVRObservable = new BABYLON.Observable();
/**
* Observable raised when controller mesh is loaded.
*/
this.onControllerMeshLoadedObservable = new BABYLON.Observable();
this._useCustomVRButton = false;
this._teleportationRequested = false;
this._teleportActive = false;
this._floorMeshesCollection = [];
this._rotationAllowed = true;
this._teleportBackwardsVector = new BABYLON.Vector3(0, -1, -1);
this._rotationRightAsked = false;
this._rotationLeftAsked = false;
this._isDefaultTeleportationTarget = true;
this._teleportationFillColor = "#444444";
this._teleportationBorderColor = "#FFFFFF";
this._rotationAngle = 0;
this._haloCenter = new BABYLON.Vector3(0, 0, 0);
this._padSensibilityUp = 0.65;
this._padSensibilityDown = 0.35;
this.leftController = null;
this.rightController = null;
/**
* Observable raised when a new mesh is selected based on meshSelectionPredicate
*/
this.onNewMeshSelected = new BABYLON.Observable();
/**
* Observable raised when a new mesh is picked based on meshSelectionPredicate
*/
this.onNewMeshPicked = new BABYLON.Observable();
/**
* Observable raised before camera teleportation
*/
this.onBeforeCameraTeleport = new BABYLON.Observable();
/**
* Observable raised after camera teleportation
*/
this.onAfterCameraTeleport = new BABYLON.Observable();
/**
* Observable raised when current selected mesh gets unselected
*/
this.onSelectedMeshUnselected = new BABYLON.Observable();
/**
* Set teleportation enabled. If set to false camera teleportation will be disabled but camera rotation will be kept.
*/
this.teleportationEnabled = true;
this._teleportationInitialized = false;
this._interactionsEnabled = false;
this._interactionsRequested = false;
this._displayGaze = true;
this._displayLaserPointer = true;
this._onResize = function () {
_this.moveButtonToBottomRight();
if (_this._fullscreenVRpresenting && _this._webVRready) {
_this.exitVR();
}
};
this._onFullscreenChange = function () {
if (document.fullscreen !== undefined) {
_this._fullscreenVRpresenting = document.fullscreen;
}
else if (document.mozFullScreen !== undefined) {
_this._fullscreenVRpresenting = document.mozFullScreen;
}
else if (document.webkitIsFullScreen !== undefined) {
_this._fullscreenVRpresenting = document.webkitIsFullScreen;
}
else if (document.msIsFullScreen !== undefined) {
_this._fullscreenVRpresenting = document.msIsFullScreen;
}
if (!_this._fullscreenVRpresenting && _this._canvas) {
_this.exitVR();
if (!_this._useCustomVRButton) {
_this._btnVR.style.top = _this._canvas.offsetTop + _this._canvas.offsetHeight - 70 + "px";
_this._btnVR.style.left = _this._canvas.offsetLeft + _this._canvas.offsetWidth - 100 + "px";
}
}
};
this.beforeRender = function () {
if (_this.leftController && _this.leftController._activePointer) {
_this._castRayAndSelectObject(_this.leftController);
}
if (_this.rightController && _this.rightController._activePointer) {
_this._castRayAndSelectObject(_this.rightController);
}
if (!(_this.leftController && _this.leftController._activePointer) && !(_this.rightController && _this.rightController._activePointer)) {
_this._castRayAndSelectObject(_this._cameraGazer);
}
else {
_this._cameraGazer._gazeTracker.isVisible = false;
}
};
this._onNewGamepadConnected = function (gamepad) {
if (gamepad.type !== BABYLON.Gamepad.POSE_ENABLED) {
if (gamepad.leftStick) {
gamepad.onleftstickchanged(function (stickValues) {
if (_this._teleportationInitialized && _this.teleportationEnabled) {
// Listening to classic/xbox gamepad only if no VR controller is active
if ((!_this.leftController && !_this.rightController) ||
((_this.leftController && !_this.leftController._activePointer) &&
(_this.rightController && !_this.rightController._activePointer))) {
_this._checkTeleportWithRay(stickValues, _this._cameraGazer);
_this._checkTeleportBackwards(stickValues, _this._cameraGazer);
}
}
});
}
if (gamepad.rightStick) {
gamepad.onrightstickchanged(function (stickValues) {
if (_this._teleportationInitialized) {
_this._checkRotate(stickValues, _this._cameraGazer);
}
});
}
if (gamepad.type === BABYLON.Gamepad.XBOX) {
gamepad.onbuttondown(function (buttonPressed) {
if (_this._interactionsEnabled && buttonPressed === BABYLON.Xbox360Button.A) {
_this._cameraGazer._selectionPointerDown();
}
});
gamepad.onbuttonup(function (buttonPressed) {
if (_this._interactionsEnabled && buttonPressed === BABYLON.Xbox360Button.A) {
_this._cameraGazer._selectionPointerUp();
}
});
}
}
else {
var webVRController = gamepad;
var controller = new VRExperienceHelperControllerGazer(webVRController, _this._scene, _this._cameraGazer._gazeTracker);
if (webVRController.hand === "right" || (_this.leftController && _this.leftController.webVRController != webVRController)) {
_this.rightController = controller;
}
else {
_this.leftController = controller;
}
_this._tryEnableInteractionOnController(controller);
}
};
// This only succeeds if the controller's mesh exists for the controller so this must be called whenever new controller is connected or when mesh is loaded
this._tryEnableInteractionOnController = function (controller) {
if (_this._interactionsRequested && !controller._interactionsEnabled) {
_this._enableInteractionOnController(controller);
}
if (_this._teleportationRequested && !controller._teleportationEnabled) {
_this._enableTeleportationOnController(controller);
}
};
this._onNewGamepadDisconnected = function (gamepad) {
if (gamepad instanceof BABYLON.WebVRController) {
if (gamepad.hand === "left" && _this.leftController != null) {
_this.leftController.dispose();
_this.leftController = null;
}
if (gamepad.hand === "right" && _this.rightController != null) {
_this.rightController.dispose();
_this.rightController = null;
}
}
};
this._workingVector = BABYLON.Vector3.Zero();
this._workingQuaternion = BABYLON.Quaternion.Identity();
this._workingMatrix = BABYLON.Matrix.Identity();
this._scene = scene;
this._canvas = scene.getEngine().getRenderingCanvas();
// Parse options
if (webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined) {
webVROptions.createFallbackVRDeviceOrientationFreeCamera = true;
}
if (webVROptions.createDeviceOrientationCamera === undefined) {
webVROptions.createDeviceOrientationCamera = true;
}
if (webVROptions.defaultHeight === undefined) {
webVROptions.defaultHeight = 1.7;
}
if (webVROptions.useCustomVRButton) {
this._useCustomVRButton = true;
if (webVROptions.customVRButton) {
this._btnVR = webVROptions.customVRButton;
}
}
if (webVROptions.rayLength) {
this._rayLength = webVROptions.rayLength;
}
this._defaultHeight = webVROptions.defaultHeight;
if (webVROptions.positionScale) {
this._rayLength *= webVROptions.positionScale;
this._defaultHeight *= webVROptions.positionScale;
}
// Set position
if (this._scene.activeCamera) {
this._position = this._scene.activeCamera.position.clone();
}
else {
this._position = new BABYLON.Vector3(0, this._defaultHeight, 0);
}
// Set non-vr camera
if (webVROptions.createDeviceOrientationCamera || !this._scene.activeCamera) {
this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene);
// Copy data from existing camera
if (this._scene.activeCamera) {
this._deviceOrientationCamera.minZ = this._scene.activeCamera.minZ;
this._deviceOrientationCamera.maxZ = this._scene.activeCamera.maxZ;
// Set rotation from previous camera
if (this._scene.activeCamera instanceof BABYLON.TargetCamera && this._scene.activeCamera.rotation) {
var targetCamera = this._scene.activeCamera;
if (targetCamera.rotationQuaternion) {
this._deviceOrientationCamera.rotationQuaternion.copyFrom(targetCamera.rotationQuaternion);
}
else {
this._deviceOrientationCamera.rotationQuaternion.copyFrom(BABYLON.Quaternion.RotationYawPitchRoll(targetCamera.rotation.y, targetCamera.rotation.x, targetCamera.rotation.z));
}
this._deviceOrientationCamera.rotation = targetCamera.rotation.clone();
}
}
this._scene.activeCamera = this._deviceOrientationCamera;
if (this._canvas) {
this._scene.activeCamera.attachControl(this._canvas);
}
}
else {
this._existingCamera = this._scene.activeCamera;
}
// Create VR cameras
if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene);
}
this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions);
this._webVRCamera.useStandingMatrix();
this._cameraGazer = new VRExperienceHelperCameraGazer(function () { return _this.currentVRCamera; }, scene);
// Create default button
if (!this._useCustomVRButton) {
this._btnVR = document.createElement("BUTTON");
this._btnVR.className = "babylonVRicon";
this._btnVR.id = "babylonVRiconbtn";
this._btnVR.title = "Click to switch to VR";
var css = ".babylonVRicon { position: absolute; right: 20px; height: 50px; width: 80px; background-color: rgba(51,51,51,0.7); background-image: url(data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%222048%22%20height%3D%221152%22%20viewBox%3D%220%200%202048%201152%22%20version%3D%221.1%22%3E%3Cpath%20transform%3D%22rotate%28180%201024%2C576.0000000000001%29%22%20d%3D%22m1109%2C896q17%2C0%2030%2C-12t13%2C-30t-12.5%2C-30.5t-30.5%2C-12.5l-170%2C0q-18%2C0%20-30.5%2C12.5t-12.5%2C30.5t13%2C30t30%2C12l170%2C0zm-85%2C256q59%2C0%20132.5%2C-1.5t154.5%2C-5.5t164.5%2C-11.5t163%2C-20t150%2C-30t124.5%2C-41.5q23%2C-11%2042%2C-24t38%2C-30q27%2C-25%2041%2C-61.5t14%2C-72.5l0%2C-257q0%2C-123%20-47%2C-232t-128%2C-190t-190%2C-128t-232%2C-47l-81%2C0q-37%2C0%20-68.5%2C14t-60.5%2C34.5t-55.5%2C45t-53%2C45t-53%2C34.5t-55.5%2C14t-55.5%2C-14t-53%2C-34.5t-53%2C-45t-55.5%2C-45t-60.5%2C-34.5t-68.5%2C-14l-81%2C0q-123%2C0%20-232%2C47t-190%2C128t-128%2C190t-47%2C232l0%2C257q0%2C68%2038%2C115t97%2C73q54%2C24%20124.5%2C41.5t150%2C30t163%2C20t164.5%2C11.5t154.5%2C5.5t132.5%2C1.5zm939%2C-298q0%2C39%20-24.5%2C67t-58.5%2C42q-54%2C23%20-122%2C39.5t-143.5%2C28t-155.5%2C19t-157%2C11t-148.5%2C5t-129.5%2C1.5q-59%2C0%20-130%2C-1.5t-148%2C-5t-157%2C-11t-155.5%2C-19t-143.5%2C-28t-122%2C-39.5q-34%2C-14%20-58.5%2C-42t-24.5%2C-67l0%2C-257q0%2C-106%2040.5%2C-199t110%2C-162.5t162.5%2C-109.5t199%2C-40l81%2C0q27%2C0%2052%2C14t50%2C34.5t51%2C44.5t55.5%2C44.5t63.5%2C34.5t74%2C14t74%2C-14t63.5%2C-34.5t55.5%2C-44.5t51%2C-44.5t50%2C-34.5t52%2C-14l14%2C0q37%2C0%2070%2C0.5t64.5%2C4.5t63.5%2C12t68%2C23q71%2C30%20128.5%2C78.5t98.5%2C110t63.5%2C133.5t22.5%2C149l0%2C257z%22%20fill%3D%22white%22%20/%3E%3C/svg%3E%0A); background-size: 80%; background-repeat:no-repeat; background-position: center; border: none; outline: none; transition: transform 0.125s ease-out } .babylonVRicon:hover { transform: scale(1.05) } .babylonVRicon:active {background-color: rgba(51,51,51,1) } .babylonVRicon:focus {background-color: rgba(51,51,51,1) }";
css += ".babylonVRicon.vrdisplaypresenting { display: none; }";
// TODO: Add user feedback so that they know what state the VRDisplay is in (disconnected, connected, entering-VR)
// css += ".babylonVRicon.vrdisplaysupported { }";
// css += ".babylonVRicon.vrdisplayready { }";
// css += ".babylonVRicon.vrdisplayrequesting { }";
var style = document.createElement('style');
style.appendChild(document.createTextNode(css));
document.getElementsByTagName('head')[0].appendChild(style);
this.moveButtonToBottomRight();
}
// VR button click event
if (this._btnVR) {
this._btnVR.addEventListener("click", function () {
if (!_this.isInVRMode) {
_this.enterVR();
}
else {
_this.exitVR();
}
});
}
// Window events
window.addEventListener("resize", this._onResize);
document.addEventListener("fullscreenchange", this._onFullscreenChange, false);
document.addEventListener("mozfullscreenchange", this._onFullscreenChange, false);
document.addEventListener("webkitfullscreenchange", this._onFullscreenChange, false);
document.addEventListener("msfullscreenchange", this._onFullscreenChange, false);
// Display vr button when headset is connected
if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
this.displayVRButton();
}
else {
this._scene.getEngine().onVRDisplayChangedObservable.add(function (e) {
if (e.vrDisplay) {
_this.displayVRButton();
}
});
}
// Exiting VR mode using 'ESC' key on desktop
this._onKeyDown = function (event) {
if (event.keyCode === 27 && _this.isInVRMode) {
_this.exitVR();
}
};
document.addEventListener("keydown", this._onKeyDown);
// Exiting VR mode double tapping the touch screen
this._scene.onPrePointerObservable.add(function (pointerInfo, eventState) {
if (_this.isInVRMode) {
_this.exitVR();
if (_this._fullscreenVRpresenting) {
_this._scene.getEngine().switchFullscreen(true);
}
}
}, BABYLON.PointerEventTypes.POINTERDOUBLETAP, false);
// Listen for WebVR display changes
this._onVRDisplayChanged = function (eventArgs) { return _this.onVRDisplayChanged(eventArgs); };
this._onVrDisplayPresentChange = function () { return _this.onVrDisplayPresentChange(); };
this._onVRRequestPresentStart = function () {
_this._webVRrequesting = true;
_this.updateButtonVisibility();
};
this._onVRRequestPresentComplete = function (success) {
_this._webVRrequesting = false;
_this.updateButtonVisibility();
};
scene.getEngine().onVRDisplayChangedObservable.add(this._onVRDisplayChanged);
scene.getEngine().onVRRequestPresentStart.add(this._onVRRequestPresentStart);
scene.getEngine().onVRRequestPresentComplete.add(this._onVRRequestPresentComplete);
window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
scene.onDisposeObservable.add(function () {
_this.dispose();
});
// Gamepad connection events
this._webVRCamera.onControllerMeshLoadedObservable.add(function (webVRController) { return _this._onDefaultMeshLoaded(webVRController); });
this._scene.gamepadManager.onGamepadConnectedObservable.add(this._onNewGamepadConnected);
this._scene.gamepadManager.onGamepadDisconnectedObservable.add(this._onNewGamepadDisconnected);
this.updateButtonVisibility();
//create easing functions
this._circleEase = new BABYLON.CircleEase();
this._circleEase.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
}
Object.defineProperty(VRExperienceHelper.prototype, "onEnteringVR", {
/** Return this.onEnteringVRObservable
* Note: This one is for backward compatibility. Please use onEnteringVRObservable directly
*/
get: function () {
return this.onEnteringVRObservable;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "onExitingVR", {
/** Return this.onExitingVRObservable
* Note: This one is for backward compatibility. Please use onExitingVRObservable directly
*/
get: function () {
return this.onExitingVRObservable;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "onControllerMeshLoaded", {
/** Return this.onControllerMeshLoadedObservable
* Note: This one is for backward compatibility. Please use onControllerMeshLoadedObservable directly
*/
get: function () {
return this.onControllerMeshLoadedObservable;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "teleportationTarget", {
/**
* The mesh used to display where the user is going to teleport.
*/
get: function () {
return this._teleportationTarget;
},
/**
* Sets the mesh to be used to display where the user is going to teleport.
*/
set: function (value) {
if (value) {
value.name = "teleportationTarget";
this._isDefaultTeleportationTarget = false;
this._teleportationTarget = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "gazeTrackerMesh", {
/**
* The mesh used to display where the user is selecting,
* when set bakeCurrentTransformIntoVertices will be called on the mesh.
* See http://doc.babylonjs.com/resources/baking_transformations
*/
get: function () {
return this._cameraGazer._gazeTracker;
},
set: function (value) {
if (value) {
this._cameraGazer._gazeTracker = value;
this._cameraGazer._gazeTracker.bakeCurrentTransformIntoVertices();
this._cameraGazer._gazeTracker.isPickable = false;
this._cameraGazer._gazeTracker.isVisible = false;
this._cameraGazer._gazeTracker.name = "gazeTracker";
if (this.leftController) {
this.leftController._gazeTracker = this._cameraGazer._gazeTracker.clone("gazeTracker");
}
if (this.rightController) {
this.rightController._gazeTracker = this._cameraGazer._gazeTracker.clone("gazeTracker");
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "displayGaze", {
/**
* If the ray of the gaze should be displayed.
*/
get: function () {
return this._displayGaze;
},
/**
* Sets if the ray of the gaze should be displayed.
*/
set: function (value) {
this._displayGaze = value;
if (!value) {
this._cameraGazer._gazeTracker.isVisible = false;
if (this.leftController) {
this.leftController._gazeTracker.isVisible = false;
}
if (this.rightController) {
this.rightController._gazeTracker.isVisible = false;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "displayLaserPointer", {
/**
* If the ray of the LaserPointer should be displayed.
*/
get: function () {
return this._displayLaserPointer;
},
/**
* Sets if the ray of the LaserPointer should be displayed.
*/
set: function (value) {
this._displayLaserPointer = value;
if (!value) {
if (this.rightController) {
this.rightController._deactivatePointer();
this.rightController._gazeTracker.isVisible = false;
}
if (this.leftController) {
this.leftController._deactivatePointer();
this.leftController._gazeTracker.isVisible = false;
}
}
else {
if (this.rightController) {
this.rightController._activatePointer();
}
else if (this.leftController) {
this.leftController._activatePointer();
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "deviceOrientationCamera", {
/**
* The deviceOrientationCamera used as the camera when not in VR.
*/
get: function () {
return this._deviceOrientationCamera;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "currentVRCamera", {
/**
* Based on the current WebVR support, returns the current VR camera used.
*/
get: function () {
if (this._webVRready) {
return this._webVRCamera;
}
else {
return this._scene.activeCamera;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "webVRCamera", {
/**
* The webVRCamera which is used when in VR.
*/
get: function () {
return this._webVRCamera;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "vrDeviceOrientationCamera", {
/**
* The deviceOrientationCamera that is used as a fallback when vr device is not connected.
*/
get: function () {
return this._vrDeviceOrientationCamera;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "_teleportationRequestInitiated", {
get: function () {
var result = this._cameraGazer._teleportationRequestInitiated
|| (this.leftController !== null && this.leftController._teleportationRequestInitiated)
|| (this.rightController !== null && this.rightController._teleportationRequestInitiated);
return result;
},
enumerable: true,
configurable: true
});
// Raised when one of the controller has loaded successfully its associated default mesh
VRExperienceHelper.prototype._onDefaultMeshLoaded = function (webVRController) {
if (this.leftController && this.leftController.webVRController == webVRController) {
if (webVRController.mesh) {
this.leftController._setLaserPointerParent(webVRController.mesh);
}
}
if (this.rightController && this.rightController.webVRController == webVRController) {
if (webVRController.mesh) {
this.rightController._setLaserPointerParent(webVRController.mesh);
}
}
try {
this.onControllerMeshLoadedObservable.notifyObservers(webVRController);
}
catch (err) {
BABYLON.Tools.Warn("Error in your custom logic onControllerMeshLoaded: " + err);
}
};
Object.defineProperty(VRExperienceHelper.prototype, "isInVRMode", {
/**
* Gets a value indicating if we are currently in VR mode.
*/
get: function () {
return this._webVRpresenting || this._fullscreenVRpresenting;
},
enumerable: true,
configurable: true
});
VRExperienceHelper.prototype.onVrDisplayPresentChange = function () {
var vrDisplay = this._scene.getEngine().getVRDevice();
if (vrDisplay) {
var wasPresenting = this._webVRpresenting;
// A VR display is connected
this._webVRpresenting = vrDisplay.isPresenting;
if (wasPresenting && !this._webVRpresenting)
this.exitVR();
}
else {
BABYLON.Tools.Warn('Detected VRDisplayPresentChange on an unknown VRDisplay. Did you can enterVR on the vrExperienceHelper?');
}
this.updateButtonVisibility();
};
VRExperienceHelper.prototype.onVRDisplayChanged = function (eventArgs) {
this._webVRsupported = eventArgs.vrSupported;
this._webVRready = !!eventArgs.vrDisplay;
this._webVRpresenting = eventArgs.vrDisplay && eventArgs.vrDisplay.isPresenting;
this.updateButtonVisibility();
};
VRExperienceHelper.prototype.moveButtonToBottomRight = function () {
if (this._canvas && !this._useCustomVRButton) {
this._btnVR.style.top = this._canvas.offsetTop + this._canvas.offsetHeight - 70 + "px";
this._btnVR.style.left = this._canvas.offsetLeft + this._canvas.offsetWidth - 100 + "px";
}
};
VRExperienceHelper.prototype.displayVRButton = function () {
if (!this._useCustomVRButton && !this._btnVRDisplayed) {
document.body.appendChild(this._btnVR);
this._btnVRDisplayed = true;
}
};
VRExperienceHelper.prototype.updateButtonVisibility = function () {
if (!this._btnVR || this._useCustomVRButton) {
return;
}
this._btnVR.className = "babylonVRicon";
if (this.isInVRMode) {
this._btnVR.className += " vrdisplaypresenting";
}
else {
if (this._webVRready)
this._btnVR.className += " vrdisplayready";
if (this._webVRsupported)
this._btnVR.className += " vrdisplaysupported";
if (this._webVRrequesting)
this._btnVR.className += " vrdisplayrequesting";
}
};
/**
* Attempt to enter VR. If a headset is connected and ready, will request present on that.
* Otherwise, will use the fullscreen API.
*/
VRExperienceHelper.prototype.enterVR = function () {
if (this.onEnteringVRObservable) {
try {
this.onEnteringVRObservable.notifyObservers(this);
}
catch (err) {
BABYLON.Tools.Warn("Error in your custom logic onEnteringVR: " + err);
}
}
if (this._scene.activeCamera) {
this._position = this._scene.activeCamera.position.clone();
// make sure that we return to the last active camera
this._existingCamera = this._scene.activeCamera;
}
if (this._webVRrequesting)
return;
// If WebVR is supported and a headset is connected
if (this._webVRready) {
if (!this._webVRpresenting) {
this._webVRCamera.position = this._position;
this._scene.activeCamera = this._webVRCamera;
}
}
else if (this._vrDeviceOrientationCamera) {
this._vrDeviceOrientationCamera.position = this._position;
if (this._scene.activeCamera) {
this._vrDeviceOrientationCamera.minZ = this._scene.activeCamera.minZ;
}
this._scene.activeCamera = this._vrDeviceOrientationCamera;
this._scene.getEngine().switchFullscreen(true);
this.updateButtonVisibility();
}
if (this._scene.activeCamera && this._canvas) {
this._scene.activeCamera.attachControl(this._canvas);
}
if (this._interactionsEnabled) {
this._scene.registerBeforeRender(this.beforeRender);
}
};
/**
* Attempt to exit VR, or fullscreen.
*/
VRExperienceHelper.prototype.exitVR = function () {
if (this.onExitingVRObservable) {
try {
this.onExitingVRObservable.notifyObservers(this);
}
catch (err) {
BABYLON.Tools.Warn("Error in your custom logic onExitingVR: " + err);
}
}
if (this._webVRpresenting) {
this._scene.getEngine().disableVR();
}
if (this._scene.activeCamera) {
this._position = this._scene.activeCamera.position.clone();
}
if (this._deviceOrientationCamera) {
this._deviceOrientationCamera.position = this._position;
this._scene.activeCamera = this._deviceOrientationCamera;
if (this._canvas) {
this._scene.activeCamera.attachControl(this._canvas);
}
}
else if (this._existingCamera) {
this._existingCamera.position = this._position;
this._scene.activeCamera = this._existingCamera;
}
this.updateButtonVisibility();
if (this._interactionsEnabled) {
this._scene.unregisterBeforeRender(this.beforeRender);
}
// resize to update width and height when exiting vr exits fullscreen
this._scene.getEngine().resize();
};
Object.defineProperty(VRExperienceHelper.prototype, "position", {
/**
* The position of the vr experience helper.
*/
get: function () {
return this._position;
},
/**
* Sets the position of the vr experience helper.
*/
set: function (value) {
this._position = value;
if (this._scene.activeCamera) {
this._scene.activeCamera.position = value;
}
},
enumerable: true,
configurable: true
});
/**
* Enables controllers and user interactions suck as selecting and object or clicking on an object.
*/
VRExperienceHelper.prototype.enableInteractions = function () {
var _this = this;
if (!this._interactionsEnabled) {
this._interactionsRequested = true;
if (this.leftController) {
this._enableInteractionOnController(this.leftController);
}
if (this.rightController) {
this._enableInteractionOnController(this.rightController);
}
this.raySelectionPredicate = function (mesh) {
return mesh.isVisible;
};
this.meshSelectionPredicate = function (mesh) {
return true;
};
this._raySelectionPredicate = function (mesh) {
if (_this._isTeleportationFloor(mesh) || (mesh.name.indexOf("gazeTracker") === -1
&& mesh.name.indexOf("teleportationTarget") === -1
&& mesh.name.indexOf("torusTeleportation") === -1
&& mesh.name.indexOf("laserPointer") === -1)) {
return _this.raySelectionPredicate(mesh);
}
return false;
};
this._interactionsEnabled = true;
}
};
VRExperienceHelper.prototype._isTeleportationFloor = function (mesh) {
for (var i = 0; i < this._floorMeshesCollection.length; i++) {
if (this._floorMeshesCollection[i].id === mesh.id) {
return true;
}
}
if (this._floorMeshName && mesh.name === this._floorMeshName) {
return true;
}
return false;
};
/**
* Adds a floor mesh to be used for teleportation.
* @param floorMesh the mesh to be used for teleportation.
*/
VRExperienceHelper.prototype.addFloorMesh = function (floorMesh) {
if (!this._floorMeshesCollection) {
return;
}
if (this._floorMeshesCollection.indexOf(floorMesh) > -1) {
return;
}
this._floorMeshesCollection.push(floorMesh);
};
/**
* Removes a floor mesh from being used for teleportation.
* @param floorMesh the mesh to be removed.
*/
VRExperienceHelper.prototype.removeFloorMesh = function (floorMesh) {
if (!this._floorMeshesCollection) {
return;
}
var meshIndex = this._floorMeshesCollection.indexOf(floorMesh);
if (meshIndex !== -1) {
this._floorMeshesCollection.splice(meshIndex, 1);
}
};
/**
* Enables interactions and teleportation using the VR controllers and gaze.
* @param vrTeleportationOptions options to modify teleportation behavior.
*/
VRExperienceHelper.prototype.enableTeleportation = function (vrTeleportationOptions) {
if (vrTeleportationOptions === void 0) { vrTeleportationOptions = {}; }
if (!this._teleportationInitialized) {
this._teleportationRequested = true;
this.enableInteractions();
if (vrTeleportationOptions.floorMeshName) {
this._floorMeshName = vrTeleportationOptions.floorMeshName;
}
if (vrTeleportationOptions.floorMeshes) {
this._floorMeshesCollection = vrTeleportationOptions.floorMeshes;
}
if (this.leftController != null) {
this._enableTeleportationOnController(this.leftController);
}
if (this.rightController != null) {
this._enableTeleportationOnController(this.rightController);
}
// Creates an image processing post process for the vignette not relying
// on the main scene configuration for image processing to reduce setup and spaces
// (gamma/linear) conflicts.
var imageProcessingConfiguration = new BABYLON.ImageProcessingConfiguration();
imageProcessingConfiguration.vignetteColor = new BABYLON.Color4(0, 0, 0, 0);
imageProcessingConfiguration.vignetteEnabled = true;
this._postProcessMove = new BABYLON.ImageProcessingPostProcess("postProcessMove", 1.0, this._webVRCamera, undefined, undefined, undefined, undefined, imageProcessingConfiguration);
this._webVRCamera.detachPostProcess(this._postProcessMove);
this._teleportationInitialized = true;
if (this._isDefaultTeleportationTarget) {
this._createTeleportationCircles();
this._teleportationTarget.scaling.scaleInPlace(this._webVRCamera.deviceScaleFactor);
}
}
};
VRExperienceHelper.prototype._enableInteractionOnController = function (controller) {
var _this = this;
var controllerMesh = controller.webVRController.mesh;
if (controllerMesh) {
controller._interactionsEnabled = true;
controller._activatePointer();
controller.webVRController.onMainButtonStateChangedObservable.add(function (stateObject) {
// Enabling / disabling laserPointer
if (_this._displayLaserPointer && stateObject.value === 1) {
if (controller._activePointer) {
controller._deactivatePointer();
}
else {
controller._activatePointer();
}
if (_this.displayGaze) {
controller._gazeTracker.isVisible = controller._activePointer;
}
}
});
controller.webVRController.onTriggerStateChangedObservable.add(function (stateObject) {
if (!controller._pointerDownOnMeshAsked) {
if (stateObject.value > _this._padSensibilityUp) {
controller._selectionPointerDown();
}
}
else if (stateObject.value < _this._padSensibilityDown) {
controller._selectionPointerUp();
}
});
}
};
VRExperienceHelper.prototype._checkTeleportWithRay = function (stateObject, gazer) {
// Dont teleport if another gaze already requested teleportation
if (this._teleportationRequestInitiated && !gazer._teleportationRequestInitiated) {
return;
}
if (!gazer._teleportationRequestInitiated) {
if (stateObject.y < -this._padSensibilityUp && gazer._dpadPressed) {
gazer._activatePointer();
gazer._teleportationRequestInitiated = true;
}
}
else {
// Listening to the proper controller values changes to confirm teleportation
if (Math.sqrt(stateObject.y * stateObject.y + stateObject.x * stateObject.x) < this._padSensibilityDown) {
if (this._teleportActive) {
this._teleportCamera(this._haloCenter);
}
gazer._teleportationRequestInitiated = false;
}
}
};
VRExperienceHelper.prototype._checkRotate = function (stateObject, gazer) {
// Only rotate when user is not currently selecting a teleportation location
if (gazer._teleportationRequestInitiated) {
return;
}
if (!this._rotationLeftAsked) {
if (stateObject.x < -this._padSensibilityUp && gazer._dpadPressed) {
this._rotationLeftAsked = true;
if (this._rotationAllowed) {
this._rotateCamera(false);
}
}
}
else {
if (stateObject.x > -this._padSensibilityDown) {
this._rotationLeftAsked = false;
}
}
if (!this._rotationRightAsked) {
if (stateObject.x > this._padSensibilityUp && gazer._dpadPressed) {
this._rotationRightAsked = true;
if (this._rotationAllowed) {
this._rotateCamera(true);
}
}
}
else {
if (stateObject.x < this._padSensibilityDown) {
this._rotationRightAsked = false;
}
}
};
VRExperienceHelper.prototype._checkTeleportBackwards = function (stateObject, gazer) {
// Only teleport backwards when user is not currently selecting a teleportation location
if (gazer._teleportationRequestInitiated) {
return;
}
// Teleport backwards
if (stateObject.y > this._padSensibilityUp && gazer._dpadPressed) {
if (!gazer._teleportationBackRequestInitiated) {
if (!this.currentVRCamera) {
return;
}
// Get rotation and position of the current camera
var rotation = BABYLON.Quaternion.FromRotationMatrix(this.currentVRCamera.getWorldMatrix().getRotationMatrix());
var position = this.currentVRCamera.position;
// If the camera has device position, use that instead
if (this.currentVRCamera.devicePosition && this.currentVRCamera.deviceRotationQuaternion) {
rotation = this.currentVRCamera.deviceRotationQuaternion;
position = this.currentVRCamera.devicePosition;
}
// Get matrix with only the y rotation of the device rotation
rotation.toEulerAnglesToRef(this._workingVector);
this._workingVector.z = 0;
this._workingVector.x = 0;
BABYLON.Quaternion.RotationYawPitchRollToRef(this._workingVector.y, this._workingVector.x, this._workingVector.z, this._workingQuaternion);
this._workingQuaternion.toRotationMatrix(this._workingMatrix);
// Rotate backwards ray by device rotation to cast at the ground behind the user
BABYLON.Vector3.TransformCoordinatesToRef(this._teleportBackwardsVector, this._workingMatrix, this._workingVector);
// Teleport if ray hit the ground and is not to far away eg. backwards off a cliff
var ray = new BABYLON.Ray(position, this._workingVector);
var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate);
if (hit && hit.pickedPoint && hit.pickedMesh && this._isTeleportationFloor(hit.pickedMesh) && hit.distance < 5) {
this._teleportCamera(hit.pickedPoint);
}
gazer._teleportationBackRequestInitiated = true;
}
}
else {
gazer._teleportationBackRequestInitiated = false;
}
};
VRExperienceHelper.prototype._enableTeleportationOnController = function (controller) {
var _this = this;
var controllerMesh = controller.webVRController.mesh;
if (controllerMesh) {
if (!controller._interactionsEnabled) {
this._enableInteractionOnController(controller);
}
controller._interactionsEnabled = true;
controller._teleportationEnabled = true;
if (controller.webVRController.controllerType === BABYLON.PoseEnabledControllerType.VIVE) {
controller._dpadPressed = false;
controller.webVRController.onPadStateChangedObservable.add(function (stateObject) {
controller._dpadPressed = stateObject.pressed;
if (!controller._dpadPressed) {
_this._rotationLeftAsked = false;
_this._rotationRightAsked = false;
controller._teleportationBackRequestInitiated = false;
}
});
}
controller.webVRController.onPadValuesChangedObservable.add(function (stateObject) {
if (_this.teleportationEnabled) {
_this._checkTeleportBackwards(stateObject, controller);
_this._checkTeleportWithRay(stateObject, controller);
}
_this._checkRotate(stateObject, controller);
});
}
};
VRExperienceHelper.prototype._createTeleportationCircles = function () {
this._teleportationTarget = BABYLON.Mesh.CreateGround("teleportationTarget", 2, 2, 2, this._scene);
this._teleportationTarget.isPickable = false;
var length = 512;
var dynamicTexture = new BABYLON.DynamicTexture("DynamicTexture", length, this._scene, true);
dynamicTexture.hasAlpha = true;
var context = dynamicTexture.getContext();
var centerX = length / 2;
var centerY = length / 2;
var radius = 200;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = this._teleportationFillColor;
context.fill();
context.lineWidth = 10;
context.strokeStyle = this._teleportationBorderColor;
context.stroke();
context.closePath();
dynamicTexture.update();
var teleportationCircleMaterial = new BABYLON.StandardMaterial("TextPlaneMaterial", this._scene);
teleportationCircleMaterial.diffuseTexture = dynamicTexture;
this._teleportationTarget.material = teleportationCircleMaterial;
var torus = BABYLON.Mesh.CreateTorus("torusTeleportation", 0.75, 0.1, 25, this._scene, false);
torus.isPickable = false;
torus.parent = this._teleportationTarget;
var animationInnerCircle = new BABYLON.Animation("animationInnerCircle", "position.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
var keys = [];
keys.push({
frame: 0,
value: 0
});
keys.push({
frame: 30,
value: 0.4
});
keys.push({
frame: 60,
value: 0
});
animationInnerCircle.setKeys(keys);
var easingFunction = new BABYLON.SineEase();
easingFunction.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
animationInnerCircle.setEasingFunction(easingFunction);
torus.animations = [];
torus.animations.push(animationInnerCircle);
this._scene.beginAnimation(torus, 0, 60, true);
this._hideTeleportationTarget();
};
VRExperienceHelper.prototype._displayTeleportationTarget = function () {
this._teleportActive = true;
if (this._teleportationInitialized) {
this._teleportationTarget.isVisible = true;
if (this._isDefaultTeleportationTarget) {
this._teleportationTarget.getChildren()[0].isVisible = true;
}
}
};
VRExperienceHelper.prototype._hideTeleportationTarget = function () {
this._teleportActive = false;
if (this._teleportationInitialized) {
this._teleportationTarget.isVisible = false;
if (this._isDefaultTeleportationTarget) {
this._teleportationTarget.getChildren()[0].isVisible = false;
}
}
};
VRExperienceHelper.prototype._rotateCamera = function (right) {
var _this = this;
if (!(this.currentVRCamera instanceof BABYLON.FreeCamera)) {
return;
}
if (right) {
this._rotationAngle++;
}
else {
this._rotationAngle--;
}
this.currentVRCamera.animations = [];
var target = BABYLON.Quaternion.FromRotationMatrix(BABYLON.Matrix.RotationY(Math.PI / 4 * this._rotationAngle));
var animationRotation = new BABYLON.Animation("animationRotation", "rotationQuaternion", 90, BABYLON.Animation.ANIMATIONTYPE_QUATERNION, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var animationRotationKeys = [];
animationRotationKeys.push({
frame: 0,
value: this.currentVRCamera.rotationQuaternion
});
animationRotationKeys.push({
frame: 6,
value: target
});
animationRotation.setKeys(animationRotationKeys);
animationRotation.setEasingFunction(this._circleEase);
this.currentVRCamera.animations.push(animationRotation);
this._postProcessMove.animations = [];
var animationPP = new BABYLON.Animation("animationPP", "vignetteWeight", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var vignetteWeightKeys = [];
vignetteWeightKeys.push({
frame: 0,
value: 0
});
vignetteWeightKeys.push({
frame: 3,
value: 4
});
vignetteWeightKeys.push({
frame: 6,
value: 0
});
animationPP.setKeys(vignetteWeightKeys);
animationPP.setEasingFunction(this._circleEase);
this._postProcessMove.animations.push(animationPP);
var animationPP2 = new BABYLON.Animation("animationPP2", "vignetteStretch", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var vignetteStretchKeys = [];
vignetteStretchKeys.push({
frame: 0,
value: 0
});
vignetteStretchKeys.push({
frame: 3,
value: 10
});
vignetteStretchKeys.push({
frame: 6,
value: 0
});
animationPP2.setKeys(vignetteStretchKeys);
animationPP2.setEasingFunction(this._circleEase);
this._postProcessMove.animations.push(animationPP2);
this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0;
this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0;
this._postProcessMove.samples = 4;
this._webVRCamera.attachPostProcess(this._postProcessMove);
this._scene.beginAnimation(this._postProcessMove, 0, 6, false, 1, function () {
_this._webVRCamera.detachPostProcess(_this._postProcessMove);
});
this._scene.beginAnimation(this.currentVRCamera, 0, 6, false, 1);
};
VRExperienceHelper.prototype._moveTeleportationSelectorTo = function (hit, gazer, ray) {
if (hit.pickedPoint) {
if (gazer._teleportationRequestInitiated) {
this._displayTeleportationTarget();
this._haloCenter.copyFrom(hit.pickedPoint);
this._teleportationTarget.position.copyFrom(hit.pickedPoint);
}
var pickNormal = this._convertNormalToDirectionOfRay(hit.getNormal(true, false), ray);
if (pickNormal) {
var axis1 = BABYLON.Vector3.Cross(BABYLON.Axis.Y, pickNormal);
var axis2 = BABYLON.Vector3.Cross(pickNormal, axis1);
BABYLON.Vector3.RotationFromAxisToRef(axis2, pickNormal, axis1, this._teleportationTarget.rotation);
}
this._teleportationTarget.position.y += 0.1;
}
};
VRExperienceHelper.prototype._teleportCamera = function (location) {
var _this = this;
if (!(this.currentVRCamera instanceof BABYLON.FreeCamera)) {
return;
}
// Teleport the hmd to where the user is looking by moving the anchor to where they are looking minus the
// offset of the headset from the anchor.
if (this.webVRCamera.leftCamera) {
this._workingVector.copyFrom(this.webVRCamera.leftCamera.globalPosition);
this._workingVector.subtractInPlace(this.webVRCamera.position);
location.subtractToRef(this._workingVector, this._workingVector);
}
else {
this._workingVector.copyFrom(location);
}
// Add height to account for user's height offset
if (this.isInVRMode) {
this._workingVector.y += this.webVRCamera.deviceDistanceToRoomGround() * this._webVRCamera.deviceScaleFactor;
}
else {
this._workingVector.y += this._defaultHeight;
}
this.onBeforeCameraTeleport.notifyObservers(this._workingVector);
// Create animation from the camera's position to the new location
this.currentVRCamera.animations = [];
var animationCameraTeleportation = new BABYLON.Animation("animationCameraTeleportation", "position", 90, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var animationCameraTeleportationKeys = [{
frame: 0,
value: this.currentVRCamera.position
},
{
frame: 11,
value: this._workingVector
}
];
animationCameraTeleportation.setKeys(animationCameraTeleportationKeys);
animationCameraTeleportation.setEasingFunction(this._circleEase);
this.currentVRCamera.animations.push(animationCameraTeleportation);
this._postProcessMove.animations = [];
var animationPP = new BABYLON.Animation("animationPP", "vignetteWeight", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var vignetteWeightKeys = [];
vignetteWeightKeys.push({
frame: 0,
value: 0
});
vignetteWeightKeys.push({
frame: 5,
value: 8
});
vignetteWeightKeys.push({
frame: 11,
value: 0
});
animationPP.setKeys(vignetteWeightKeys);
this._postProcessMove.animations.push(animationPP);
var animationPP2 = new BABYLON.Animation("animationPP2", "vignetteStretch", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var vignetteStretchKeys = [];
vignetteStretchKeys.push({
frame: 0,
value: 0
});
vignetteStretchKeys.push({
frame: 5,
value: 10
});
vignetteStretchKeys.push({
frame: 11,
value: 0
});
animationPP2.setKeys(vignetteStretchKeys);
this._postProcessMove.animations.push(animationPP2);
this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0;
this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0;
this._webVRCamera.attachPostProcess(this._postProcessMove);
this._scene.beginAnimation(this._postProcessMove, 0, 11, false, 1, function () {
_this._webVRCamera.detachPostProcess(_this._postProcessMove);
});
this._scene.beginAnimation(this.currentVRCamera, 0, 11, false, 1, function () {
_this.onAfterCameraTeleport.notifyObservers(_this._workingVector);
});
this._hideTeleportationTarget();
};
VRExperienceHelper.prototype._convertNormalToDirectionOfRay = function (normal, ray) {
if (normal) {
var angle = Math.acos(BABYLON.Vector3.Dot(normal, ray.direction));
if (angle < Math.PI / 2) {
normal.scaleInPlace(-1);
}
}
return normal;
};
VRExperienceHelper.prototype._castRayAndSelectObject = function (gazer) {
if (!(this.currentVRCamera instanceof BABYLON.FreeCamera)) {
return;
}
var ray = gazer._getForwardRay(this._rayLength);
var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate);
// Moving the gazeTracker on the mesh face targetted
if (hit && hit.pickedPoint) {
if (this._displayGaze) {
var multiplier = 1;
gazer._gazeTracker.isVisible = true;
if (gazer._isActionableMesh) {
multiplier = 3;
}
gazer._gazeTracker.scaling.x = hit.distance * multiplier;
gazer._gazeTracker.scaling.y = hit.distance * multiplier;
gazer._gazeTracker.scaling.z = hit.distance * multiplier;
var pickNormal = this._convertNormalToDirectionOfRay(hit.getNormal(), ray);
// To avoid z-fighting
var deltaFighting = 0.002;
if (pickNormal) {
var axis1 = BABYLON.Vector3.Cross(BABYLON.Axis.Y, pickNormal);
var axis2 = BABYLON.Vector3.Cross(pickNormal, axis1);
BABYLON.Vector3.RotationFromAxisToRef(axis2, pickNormal, axis1, gazer._gazeTracker.rotation);
}
gazer._gazeTracker.position.copyFrom(hit.pickedPoint);
if (gazer._gazeTracker.position.x < 0) {
gazer._gazeTracker.position.x += deltaFighting;
}
else {
gazer._gazeTracker.position.x -= deltaFighting;
}
if (gazer._gazeTracker.position.y < 0) {
gazer._gazeTracker.position.y += deltaFighting;
}
else {
gazer._gazeTracker.position.y -= deltaFighting;
}
if (gazer._gazeTracker.position.z < 0) {
gazer._gazeTracker.position.z += deltaFighting;
}
else {
gazer._gazeTracker.position.z -= deltaFighting;
}
}
// Changing the size of the laser pointer based on the distance from the targetted point
gazer._updatePointerDistance(hit.distance);
}
else {
gazer._gazeTracker.isVisible = false;
}
if (hit && hit.pickedMesh) {
gazer._currentHit = hit;
if (gazer._pointerDownOnMeshAsked) {
this._scene.simulatePointerMove(gazer._currentHit, { pointerId: gazer._id });
}
// The object selected is the floor, we're in a teleportation scenario
if (this._teleportationInitialized && this._isTeleportationFloor(hit.pickedMesh) && hit.pickedPoint) {
// Moving the teleportation area to this targetted point
//Raise onSelectedMeshUnselected observable if ray collided floor mesh/meshes and a non floor mesh was previously selected
if (gazer._currentMeshSelected && !this._isTeleportationFloor(gazer._currentMeshSelected)) {
this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
}
gazer._currentMeshSelected = null;
if (gazer._teleportationRequestInitiated) {
this._moveTeleportationSelectorTo(hit, gazer, ray);
}
return;
}
// If not, we're in a selection scenario
//this._teleportationAllowed = false;
if (hit.pickedMesh !== gazer._currentMeshSelected) {
if (this.meshSelectionPredicate(hit.pickedMesh)) {
this.onNewMeshPicked.notifyObservers(hit);
gazer._currentMeshSelected = hit.pickedMesh;
if (hit.pickedMesh.isPickable && hit.pickedMesh.actionManager) {
this.changeGazeColor(new BABYLON.Color3(0, 0, 1));
this.changeLaserColor(new BABYLON.Color3(0.2, 0.2, 1));
gazer._isActionableMesh = true;
}
else {
this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7));
this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7));
gazer._isActionableMesh = false;
}
try {
this.onNewMeshSelected.notifyObservers(hit.pickedMesh);
}
catch (err) {
BABYLON.Tools.Warn("Error in your custom logic onNewMeshSelected: " + err);
}
}
else {
this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
gazer._currentMeshSelected = null;
this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7));
this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7));
}
}
}
else {
gazer._currentHit = null;
this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
gazer._currentMeshSelected = null;
//this._teleportationAllowed = false;
this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7));
this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7));
}
};
VRExperienceHelper.prototype._notifySelectedMeshUnselected = function (mesh) {
if (mesh) {
this.onSelectedMeshUnselected.notifyObservers(mesh);
}
};
/**
* Sets the color of the laser ray from the vr controllers.
* @param color new color for the ray.
*/
VRExperienceHelper.prototype.changeLaserColor = function (color) {
if (this.leftController) {
this.leftController._setLaserPointerColor(color);
}
if (this.rightController) {
this.rightController._setLaserPointerColor(color);
}
};
/**
* Sets the color of the ray from the vr headsets gaze.
* @param color new color for the ray.
*/
VRExperienceHelper.prototype.changeGazeColor = function (color) {
if (!this._cameraGazer._gazeTracker.material) {
return;
}
this._cameraGazer._gazeTracker.material.emissiveColor = color;
if (this.leftController) {
this.leftController._gazeTracker.material.emissiveColor = color;
}
if (this.rightController) {
this.rightController._gazeTracker.material.emissiveColor = color;
}
};
/**
* Exits VR and disposes of the vr experience helper
*/
VRExperienceHelper.prototype.dispose = function () {
if (this.isInVRMode) {
this.exitVR();
}
if (this._postProcessMove) {
this._postProcessMove.dispose();
}
if (this._webVRCamera) {
this._webVRCamera.dispose();
}
if (this._vrDeviceOrientationCamera) {
this._vrDeviceOrientationCamera.dispose();
}
if (!this._useCustomVRButton && this._btnVR.parentNode) {
document.body.removeChild(this._btnVR);
}
if (this._deviceOrientationCamera && (this._scene.activeCamera != this._deviceOrientationCamera)) {
this._deviceOrientationCamera.dispose();
}
if (this._cameraGazer) {
this._cameraGazer.dispose();
}
if (this.leftController) {
this.leftController.dispose();
}
if (this.rightController) {
this.rightController.dispose();
}
if (this._teleportationTarget) {
this._teleportationTarget.dispose();
}
this._floorMeshesCollection = [];
document.removeEventListener("keydown", this._onKeyDown);
window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
window.removeEventListener("resize", this._onResize);
document.removeEventListener("fullscreenchange", this._onFullscreenChange);
document.removeEventListener("mozfullscreenchange", this._onFullscreenChange);
document.removeEventListener("webkitfullscreenchange", this._onFullscreenChange);
document.removeEventListener("msfullscreenchange", this._onFullscreenChange);
this._scene.getEngine().onVRDisplayChangedObservable.removeCallback(this._onVRDisplayChanged);
this._scene.getEngine().onVRRequestPresentStart.removeCallback(this._onVRRequestPresentStart);
this._scene.getEngine().onVRRequestPresentComplete.removeCallback(this._onVRRequestPresentComplete);
window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
this._scene.gamepadManager.onGamepadConnectedObservable.removeCallback(this._onNewGamepadConnected);
this._scene.gamepadManager.onGamepadDisconnectedObservable.removeCallback(this._onNewGamepadDisconnected);
this._scene.unregisterBeforeRender(this.beforeRender);
};
/**
* Gets the name of the VRExperienceHelper class
* @returns "VRExperienceHelper"
*/
VRExperienceHelper.prototype.getClassName = function () {
return "VRExperienceHelper";
};
return VRExperienceHelper;
}());
BABYLON.VRExperienceHelper = VRExperienceHelper;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.vrExperienceHelper.js.map
// Mainly based on these 2 articles :
// Creating an universal virtual touch joystick working for all Touch models thanks to Hand.JS : http://blogs.msdn.com/b/davrous/archive/2013/02/22/creating-an-universal-virtual-touch-joystick-working-for-all-touch-models-thanks-to-hand-js.aspx
// & on Seb Lee-Delisle original work: http://seb.ly/2011/04/multi-touch-game-controller-in-javascripthtml5-for-ipad/
var BABYLON;
(function (BABYLON) {
/**
* Defines the potential axis of a Joystick
*/
var JoystickAxis;
(function (JoystickAxis) {
/** X axis */
JoystickAxis[JoystickAxis["X"] = 0] = "X";
/** Y axis */
JoystickAxis[JoystickAxis["Y"] = 1] = "Y";
/** Z axis */
JoystickAxis[JoystickAxis["Z"] = 2] = "Z";
})(JoystickAxis = BABYLON.JoystickAxis || (BABYLON.JoystickAxis = {}));
/**
* Class used to define virtual joystick (used in touch mode)
*/
var VirtualJoystick = /** @class */ (function () {
/**
* Creates a new virtual joystick
* @param leftJoystick defines that the joystick is for left hand (false by default)
*/
function VirtualJoystick(leftJoystick) {
var _this = this;
if (leftJoystick) {
this._leftJoystick = true;
}
else {
this._leftJoystick = false;
}
VirtualJoystick._globalJoystickIndex++;
// By default left & right arrow keys are moving the X
// and up & down keys are moving the Y
this._axisTargetedByLeftAndRight = JoystickAxis.X;
this._axisTargetedByUpAndDown = JoystickAxis.Y;
this.reverseLeftRight = false;
this.reverseUpDown = false;
// collections of pointers
this._touches = new BABYLON.StringDictionary();
this.deltaPosition = BABYLON.Vector3.Zero();
this._joystickSensibility = 25;
this._inversedSensibility = 1 / (this._joystickSensibility / 1000);
this._onResize = function (evt) {
VirtualJoystick.vjCanvasWidth = window.innerWidth;
VirtualJoystick.vjCanvasHeight = window.innerHeight;
if (VirtualJoystick.vjCanvas) {
VirtualJoystick.vjCanvas.width = VirtualJoystick.vjCanvasWidth;
VirtualJoystick.vjCanvas.height = VirtualJoystick.vjCanvasHeight;
}
VirtualJoystick.halfWidth = VirtualJoystick.vjCanvasWidth / 2;
};
// injecting a canvas element on top of the canvas 3D game
if (!VirtualJoystick.vjCanvas) {
window.addEventListener("resize", this._onResize, false);
VirtualJoystick.vjCanvas = document.createElement("canvas");
VirtualJoystick.vjCanvasWidth = window.innerWidth;
VirtualJoystick.vjCanvasHeight = window.innerHeight;
VirtualJoystick.vjCanvas.width = window.innerWidth;
VirtualJoystick.vjCanvas.height = window.innerHeight;
VirtualJoystick.vjCanvas.style.width = "100%";
VirtualJoystick.vjCanvas.style.height = "100%";
VirtualJoystick.vjCanvas.style.position = "absolute";
VirtualJoystick.vjCanvas.style.backgroundColor = "transparent";
VirtualJoystick.vjCanvas.style.top = "0px";
VirtualJoystick.vjCanvas.style.left = "0px";
VirtualJoystick.vjCanvas.style.zIndex = "5";
VirtualJoystick.vjCanvas.style.msTouchAction = "none";
// Support for jQuery PEP polyfill
VirtualJoystick.vjCanvas.setAttribute("touch-action", "none");
var context = VirtualJoystick.vjCanvas.getContext('2d');
if (!context) {
throw new Error("Unable to create canvas for virtual joystick");
}
VirtualJoystick.vjCanvasContext = context;
VirtualJoystick.vjCanvasContext.strokeStyle = "#ffffff";
VirtualJoystick.vjCanvasContext.lineWidth = 2;
document.body.appendChild(VirtualJoystick.vjCanvas);
}
VirtualJoystick.halfWidth = VirtualJoystick.vjCanvas.width / 2;
this.pressed = false;
// default joystick color
this._joystickColor = "cyan";
this._joystickPointerID = -1;
// current joystick position
this._joystickPointerPos = new BABYLON.Vector2(0, 0);
this._joystickPreviousPointerPos = new BABYLON.Vector2(0, 0);
// origin joystick position
this._joystickPointerStartPos = new BABYLON.Vector2(0, 0);
this._deltaJoystickVector = new BABYLON.Vector2(0, 0);
this._onPointerDownHandlerRef = function (evt) {
_this._onPointerDown(evt);
};
this._onPointerMoveHandlerRef = function (evt) {
_this._onPointerMove(evt);
};
this._onPointerUpHandlerRef = function (evt) {
_this._onPointerUp(evt);
};
VirtualJoystick.vjCanvas.addEventListener('pointerdown', this._onPointerDownHandlerRef, false);
VirtualJoystick.vjCanvas.addEventListener('pointermove', this._onPointerMoveHandlerRef, false);
VirtualJoystick.vjCanvas.addEventListener('pointerup', this._onPointerUpHandlerRef, false);
VirtualJoystick.vjCanvas.addEventListener('pointerout', this._onPointerUpHandlerRef, false);
VirtualJoystick.vjCanvas.addEventListener("contextmenu", function (evt) {
evt.preventDefault(); // Disables system menu
}, false);
requestAnimationFrame(function () { _this._drawVirtualJoystick(); });
}
/**
* Defines joystick sensibility (ie. the ratio beteen a physical move and virtual joystick position change)
* @param newJoystickSensibility defines the new sensibility
*/
VirtualJoystick.prototype.setJoystickSensibility = function (newJoystickSensibility) {
this._joystickSensibility = newJoystickSensibility;
this._inversedSensibility = 1 / (this._joystickSensibility / 1000);
};
VirtualJoystick.prototype._onPointerDown = function (e) {
var positionOnScreenCondition;
e.preventDefault();
if (this._leftJoystick === true) {
positionOnScreenCondition = (e.clientX < VirtualJoystick.halfWidth);
}
else {
positionOnScreenCondition = (e.clientX > VirtualJoystick.halfWidth);
}
if (positionOnScreenCondition && this._joystickPointerID < 0) {
// First contact will be dedicated to the virtual joystick
this._joystickPointerID = e.pointerId;
this._joystickPointerStartPos.x = e.clientX;
this._joystickPointerStartPos.y = e.clientY;
this._joystickPointerPos = this._joystickPointerStartPos.clone();
this._joystickPreviousPointerPos = this._joystickPointerStartPos.clone();
this._deltaJoystickVector.x = 0;
this._deltaJoystickVector.y = 0;
this.pressed = true;
this._touches.add(e.pointerId.toString(), e);
}
else {
// You can only trigger the action buttons with a joystick declared
if (VirtualJoystick._globalJoystickIndex < 2 && this._action) {
this._action();
this._touches.add(e.pointerId.toString(), { x: e.clientX, y: e.clientY, prevX: e.clientX, prevY: e.clientY });
}
}
};
VirtualJoystick.prototype._onPointerMove = function (e) {
// If the current pointer is the one associated to the joystick (first touch contact)
if (this._joystickPointerID == e.pointerId) {
this._joystickPointerPos.x = e.clientX;
this._joystickPointerPos.y = e.clientY;
this._deltaJoystickVector = this._joystickPointerPos.clone();
this._deltaJoystickVector = this._deltaJoystickVector.subtract(this._joystickPointerStartPos);
var directionLeftRight = this.reverseLeftRight ? -1 : 1;
var deltaJoystickX = directionLeftRight * this._deltaJoystickVector.x / this._inversedSensibility;
switch (this._axisTargetedByLeftAndRight) {
case JoystickAxis.X:
this.deltaPosition.x = Math.min(1, Math.max(-1, deltaJoystickX));
break;
case JoystickAxis.Y:
this.deltaPosition.y = Math.min(1, Math.max(-1, deltaJoystickX));
break;
case JoystickAxis.Z:
this.deltaPosition.z = Math.min(1, Math.max(-1, deltaJoystickX));
break;
}
var directionUpDown = this.reverseUpDown ? 1 : -1;
var deltaJoystickY = directionUpDown * this._deltaJoystickVector.y / this._inversedSensibility;
switch (this._axisTargetedByUpAndDown) {
case JoystickAxis.X:
this.deltaPosition.x = Math.min(1, Math.max(-1, deltaJoystickY));
break;
case JoystickAxis.Y:
this.deltaPosition.y = Math.min(1, Math.max(-1, deltaJoystickY));
break;
case JoystickAxis.Z:
this.deltaPosition.z = Math.min(1, Math.max(-1, deltaJoystickY));
break;
}
}
else {
var data = this._touches.get(e.pointerId.toString());
if (data) {
data.x = e.clientX;
data.y = e.clientY;
}
}
};
VirtualJoystick.prototype._onPointerUp = function (e) {
if (this._joystickPointerID == e.pointerId) {
VirtualJoystick.vjCanvasContext.clearRect(this._joystickPointerStartPos.x - 64, this._joystickPointerStartPos.y - 64, 128, 128);
VirtualJoystick.vjCanvasContext.clearRect(this._joystickPreviousPointerPos.x - 42, this._joystickPreviousPointerPos.y - 42, 84, 84);
this._joystickPointerID = -1;
this.pressed = false;
}
else {
var touch = this._touches.get(e.pointerId.toString());
if (touch) {
VirtualJoystick.vjCanvasContext.clearRect(touch.prevX - 44, touch.prevY - 44, 88, 88);
}
}
this._deltaJoystickVector.x = 0;
this._deltaJoystickVector.y = 0;
this._touches.remove(e.pointerId.toString());
};
/**
* Change the color of the virtual joystick
* @param newColor a string that must be a CSS color value (like "red") or the hexa value (like "#FF0000")
*/
VirtualJoystick.prototype.setJoystickColor = function (newColor) {
this._joystickColor = newColor;
};
/**
* Defines a callback to call when the joystick is touched
* @param action defines the callback
*/
VirtualJoystick.prototype.setActionOnTouch = function (action) {
this._action = action;
};
/**
* Defines which axis you'd like to control for left & right
* @param axis defines the axis to use
*/
VirtualJoystick.prototype.setAxisForLeftRight = function (axis) {
switch (axis) {
case JoystickAxis.X:
case JoystickAxis.Y:
case JoystickAxis.Z:
this._axisTargetedByLeftAndRight = axis;
break;
default:
this._axisTargetedByLeftAndRight = JoystickAxis.X;
break;
}
};
/**
* Defines which axis you'd like to control for up & down
* @param axis defines the axis to use
*/
VirtualJoystick.prototype.setAxisForUpDown = function (axis) {
switch (axis) {
case JoystickAxis.X:
case JoystickAxis.Y:
case JoystickAxis.Z:
this._axisTargetedByUpAndDown = axis;
break;
default:
this._axisTargetedByUpAndDown = JoystickAxis.Y;
break;
}
};
VirtualJoystick.prototype._drawVirtualJoystick = function () {
var _this = this;
if (this.pressed) {
this._touches.forEach(function (key, touch) {
if (touch.pointerId === _this._joystickPointerID) {
VirtualJoystick.vjCanvasContext.clearRect(_this._joystickPointerStartPos.x - 64, _this._joystickPointerStartPos.y - 64, 128, 128);
VirtualJoystick.vjCanvasContext.clearRect(_this._joystickPreviousPointerPos.x - 42, _this._joystickPreviousPointerPos.y - 42, 84, 84);
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.lineWidth = 6;
VirtualJoystick.vjCanvasContext.strokeStyle = _this._joystickColor;
VirtualJoystick.vjCanvasContext.arc(_this._joystickPointerStartPos.x, _this._joystickPointerStartPos.y, 40, 0, Math.PI * 2, true);
VirtualJoystick.vjCanvasContext.stroke();
VirtualJoystick.vjCanvasContext.closePath();
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.strokeStyle = _this._joystickColor;
VirtualJoystick.vjCanvasContext.lineWidth = 2;
VirtualJoystick.vjCanvasContext.arc(_this._joystickPointerStartPos.x, _this._joystickPointerStartPos.y, 60, 0, Math.PI * 2, true);
VirtualJoystick.vjCanvasContext.stroke();
VirtualJoystick.vjCanvasContext.closePath();
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.strokeStyle = _this._joystickColor;
VirtualJoystick.vjCanvasContext.arc(_this._joystickPointerPos.x, _this._joystickPointerPos.y, 40, 0, Math.PI * 2, true);
VirtualJoystick.vjCanvasContext.stroke();
VirtualJoystick.vjCanvasContext.closePath();
_this._joystickPreviousPointerPos = _this._joystickPointerPos.clone();
}
else {
VirtualJoystick.vjCanvasContext.clearRect(touch.prevX - 44, touch.prevY - 44, 88, 88);
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.fillStyle = "white";
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.strokeStyle = "red";
VirtualJoystick.vjCanvasContext.lineWidth = 6;
VirtualJoystick.vjCanvasContext.arc(touch.x, touch.y, 40, 0, Math.PI * 2, true);
VirtualJoystick.vjCanvasContext.stroke();
VirtualJoystick.vjCanvasContext.closePath();
touch.prevX = touch.x;
touch.prevY = touch.y;
}
;
});
}
requestAnimationFrame(function () { _this._drawVirtualJoystick(); });
};
/**
* Release internal HTML canvas
*/
VirtualJoystick.prototype.releaseCanvas = function () {
if (VirtualJoystick.vjCanvas) {
VirtualJoystick.vjCanvas.removeEventListener('pointerdown', this._onPointerDownHandlerRef);
VirtualJoystick.vjCanvas.removeEventListener('pointermove', this._onPointerMoveHandlerRef);
VirtualJoystick.vjCanvas.removeEventListener('pointerup', this._onPointerUpHandlerRef);
VirtualJoystick.vjCanvas.removeEventListener('pointerout', this._onPointerUpHandlerRef);
window.removeEventListener("resize", this._onResize);
document.body.removeChild(VirtualJoystick.vjCanvas);
VirtualJoystick.vjCanvas = null;
}
};
// Used to draw the virtual joystick inside a 2D canvas on top of the WebGL rendering canvas
VirtualJoystick._globalJoystickIndex = 0;
return VirtualJoystick;
}());
BABYLON.VirtualJoystick = VirtualJoystick;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.virtualJoystick.js.map
var BABYLON;
(function (BABYLON) {
// We're mainly based on the logic defined into the FreeCamera code
var VirtualJoysticksCamera = /** @class */ (function (_super) {
__extends(VirtualJoysticksCamera, _super);
function VirtualJoysticksCamera(name, position, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.inputs.addVirtualJoystick();
return _this;
}
VirtualJoysticksCamera.prototype.getClassName = function () {
return "VirtualJoysticksCamera";
};
return VirtualJoysticksCamera;
}(BABYLON.FreeCamera));
BABYLON.VirtualJoysticksCamera = VirtualJoysticksCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.virtualJoysticksCamera.js.map
var BABYLON;
(function (BABYLON) {
var FreeCameraVirtualJoystickInput = /** @class */ (function () {
function FreeCameraVirtualJoystickInput() {
}
FreeCameraVirtualJoystickInput.prototype.getLeftJoystick = function () {
return this._leftjoystick;
};
FreeCameraVirtualJoystickInput.prototype.getRightJoystick = function () {
return this._rightjoystick;
};
FreeCameraVirtualJoystickInput.prototype.checkInputs = function () {
if (this._leftjoystick) {
var camera = this.camera;
var speed = camera._computeLocalCameraSpeed() * 50;
var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(camera.rotation.y, camera.rotation.x, 0);
var deltaTransform = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(this._leftjoystick.deltaPosition.x * speed, this._leftjoystick.deltaPosition.y * speed, this._leftjoystick.deltaPosition.z * speed), cameraTransform);
camera.cameraDirection = camera.cameraDirection.add(deltaTransform);
camera.cameraRotation = camera.cameraRotation.addVector3(this._rightjoystick.deltaPosition);
if (!this._leftjoystick.pressed) {
this._leftjoystick.deltaPosition = this._leftjoystick.deltaPosition.scale(0.9);
}
if (!this._rightjoystick.pressed) {
this._rightjoystick.deltaPosition = this._rightjoystick.deltaPosition.scale(0.9);
}
}
};
FreeCameraVirtualJoystickInput.prototype.attachControl = function (element, noPreventDefault) {
this._leftjoystick = new BABYLON.VirtualJoystick(true);
this._leftjoystick.setAxisForUpDown(BABYLON.JoystickAxis.Z);
this._leftjoystick.setAxisForLeftRight(BABYLON.JoystickAxis.X);
this._leftjoystick.setJoystickSensibility(0.15);
this._rightjoystick = new BABYLON.VirtualJoystick(false);
this._rightjoystick.setAxisForUpDown(BABYLON.JoystickAxis.X);
this._rightjoystick.setAxisForLeftRight(BABYLON.JoystickAxis.Y);
this._rightjoystick.reverseUpDown = true;
this._rightjoystick.setJoystickSensibility(0.05);
this._rightjoystick.setJoystickColor("yellow");
};
FreeCameraVirtualJoystickInput.prototype.detachControl = function (element) {
this._leftjoystick.releaseCanvas();
this._rightjoystick.releaseCanvas();
};
FreeCameraVirtualJoystickInput.prototype.getClassName = function () {
return "FreeCameraVirtualJoystickInput";
};
FreeCameraVirtualJoystickInput.prototype.getSimpleName = function () {
return "virtualJoystick";
};
return FreeCameraVirtualJoystickInput;
}());
BABYLON.FreeCameraVirtualJoystickInput = FreeCameraVirtualJoystickInput;
BABYLON.CameraInputTypes["FreeCameraVirtualJoystickInput"] = FreeCameraVirtualJoystickInput;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.freeCameraVirtualJoystickInput.js.map
var BABYLON;
(function (BABYLON) {
var SimplificationSettings = /** @class */ (function () {
function SimplificationSettings(quality, distance, optimizeMesh) {
this.quality = quality;
this.distance = distance;
this.optimizeMesh = optimizeMesh;
}
return SimplificationSettings;
}());
BABYLON.SimplificationSettings = SimplificationSettings;
var SimplificationQueue = /** @class */ (function () {
function SimplificationQueue() {
this.running = false;
this._simplificationArray = [];
}
SimplificationQueue.prototype.addTask = function (task) {
this._simplificationArray.push(task);
};
SimplificationQueue.prototype.executeNext = function () {
var task = this._simplificationArray.pop();
if (task) {
this.running = true;
this.runSimplification(task);
}
else {
this.running = false;
}
};
SimplificationQueue.prototype.runSimplification = function (task) {
var _this = this;
if (task.parallelProcessing) {
//parallel simplifier
task.settings.forEach(function (setting) {
var simplifier = _this.getSimplifier(task);
simplifier.simplify(setting, function (newMesh) {
task.mesh.addLODLevel(setting.distance, newMesh);
newMesh.isVisible = true;
//check if it is the last
if (setting.quality === task.settings[task.settings.length - 1].quality && task.successCallback) {
//all done, run the success callback.
task.successCallback();
}
_this.executeNext();
});
});
}
else {
//single simplifier.
var simplifier = this.getSimplifier(task);
var runDecimation = function (setting, callback) {
simplifier.simplify(setting, function (newMesh) {
task.mesh.addLODLevel(setting.distance, newMesh);
newMesh.isVisible = true;
//run the next quality level
callback();
});
};
BABYLON.AsyncLoop.Run(task.settings.length, function (loop) {
runDecimation(task.settings[loop.index], function () {
loop.executeNext();
});
}, function () {
//execution ended, run the success callback.
if (task.successCallback) {
task.successCallback();
}
_this.executeNext();
});
}
};
SimplificationQueue.prototype.getSimplifier = function (task) {
switch (task.simplificationType) {
case SimplificationType.QUADRATIC:
default:
return new QuadraticErrorSimplification(task.mesh);
}
};
return SimplificationQueue;
}());
BABYLON.SimplificationQueue = SimplificationQueue;
/**
* The implemented types of simplification
* At the moment only Quadratic Error Decimation is implemented
*/
var SimplificationType;
(function (SimplificationType) {
/** Quadratic error decimation */
SimplificationType[SimplificationType["QUADRATIC"] = 0] = "QUADRATIC";
})(SimplificationType = BABYLON.SimplificationType || (BABYLON.SimplificationType = {}));
var DecimationTriangle = /** @class */ (function () {
function DecimationTriangle(vertices) {
this.vertices = vertices;
this.error = new Array(4);
this.deleted = false;
this.isDirty = false;
this.deletePending = false;
this.borderFactor = 0;
}
return DecimationTriangle;
}());
BABYLON.DecimationTriangle = DecimationTriangle;
var DecimationVertex = /** @class */ (function () {
function DecimationVertex(position, id) {
this.position = position;
this.id = id;
this.isBorder = true;
this.q = new QuadraticMatrix();
this.triangleCount = 0;
this.triangleStart = 0;
this.originalOffsets = [];
}
DecimationVertex.prototype.updatePosition = function (newPosition) {
this.position.copyFrom(newPosition);
};
return DecimationVertex;
}());
BABYLON.DecimationVertex = DecimationVertex;
var QuadraticMatrix = /** @class */ (function () {
function QuadraticMatrix(data) {
this.data = new Array(10);
for (var i = 0; i < 10; ++i) {
if (data && data[i]) {
this.data[i] = data[i];
}
else {
this.data[i] = 0;
}
}
}
QuadraticMatrix.prototype.det = function (a11, a12, a13, a21, a22, a23, a31, a32, a33) {
var det = this.data[a11] * this.data[a22] * this.data[a33] + this.data[a13] * this.data[a21] * this.data[a32] +
this.data[a12] * this.data[a23] * this.data[a31] - this.data[a13] * this.data[a22] * this.data[a31] -
this.data[a11] * this.data[a23] * this.data[a32] - this.data[a12] * this.data[a21] * this.data[a33];
return det;
};
QuadraticMatrix.prototype.addInPlace = function (matrix) {
for (var i = 0; i < 10; ++i) {
this.data[i] += matrix.data[i];
}
};
QuadraticMatrix.prototype.addArrayInPlace = function (data) {
for (var i = 0; i < 10; ++i) {
this.data[i] += data[i];
}
};
QuadraticMatrix.prototype.add = function (matrix) {
var m = new QuadraticMatrix();
for (var i = 0; i < 10; ++i) {
m.data[i] = this.data[i] + matrix.data[i];
}
return m;
};
QuadraticMatrix.FromData = function (a, b, c, d) {
return new QuadraticMatrix(QuadraticMatrix.DataFromNumbers(a, b, c, d));
};
//returning an array to avoid garbage collection
QuadraticMatrix.DataFromNumbers = function (a, b, c, d) {
return [a * a, a * b, a * c, a * d, b * b, b * c, b * d, c * c, c * d, d * d];
};
return QuadraticMatrix;
}());
BABYLON.QuadraticMatrix = QuadraticMatrix;
var Reference = /** @class */ (function () {
function Reference(vertexId, triangleId) {
this.vertexId = vertexId;
this.triangleId = triangleId;
}
return Reference;
}());
BABYLON.Reference = Reference;
/**
* An implementation of the Quadratic Error simplification algorithm.
* Original paper : http://www1.cs.columbia.edu/~cs4162/html05s/garland97.pdf
* Ported mostly from QSlim and http://voxels.blogspot.de/2014/05/quadric-mesh-simplification-with-source.html to babylon JS
* @author RaananW
*/
var QuadraticErrorSimplification = /** @class */ (function () {
function QuadraticErrorSimplification(_mesh) {
this._mesh = _mesh;
this.syncIterations = 5000;
this.aggressiveness = 7;
this.decimationIterations = 100;
this.boundingBoxEpsilon = BABYLON.Epsilon;
}
QuadraticErrorSimplification.prototype.simplify = function (settings, successCallback) {
var _this = this;
this.initDecimatedMesh();
//iterating through the submeshes array, one after the other.
BABYLON.AsyncLoop.Run(this._mesh.subMeshes.length, function (loop) {
_this.initWithMesh(loop.index, function () {
_this.runDecimation(settings, loop.index, function () {
loop.executeNext();
});
}, settings.optimizeMesh);
}, function () {
setTimeout(function () {
successCallback(_this._reconstructedMesh);
}, 0);
});
};
QuadraticErrorSimplification.prototype.runDecimation = function (settings, submeshIndex, successCallback) {
var _this = this;
var targetCount = ~~(this.triangles.length * settings.quality);
var deletedTriangles = 0;
var triangleCount = this.triangles.length;
var iterationFunction = function (iteration, callback) {
setTimeout(function () {
if (iteration % 5 === 0) {
_this.updateMesh(iteration === 0);
}
for (var i = 0; i < _this.triangles.length; ++i) {
_this.triangles[i].isDirty = false;
}
var threshold = 0.000000001 * Math.pow((iteration + 3), _this.aggressiveness);
var trianglesIterator = function (i) {
var tIdx = ~~(((_this.triangles.length / 2) + i) % _this.triangles.length);
var t = _this.triangles[tIdx];
if (!t)
return;
if (t.error[3] > threshold || t.deleted || t.isDirty) {
return;
}
for (var j = 0; j < 3; ++j) {
if (t.error[j] < threshold) {
var deleted0 = [];
var deleted1 = [];
var v0 = t.vertices[j];
var v1 = t.vertices[(j + 1) % 3];
if (v0.isBorder || v1.isBorder)
continue;
var p = BABYLON.Vector3.Zero();
var n = BABYLON.Vector3.Zero();
var uv = BABYLON.Vector2.Zero();
var color = new BABYLON.Color4(0, 0, 0, 1);
_this.calculateError(v0, v1, p, n, uv, color);
var delTr = new Array();
if (_this.isFlipped(v0, v1, p, deleted0, t.borderFactor, delTr))
continue;
if (_this.isFlipped(v1, v0, p, deleted1, t.borderFactor, delTr))
continue;
if (deleted0.indexOf(true) < 0 || deleted1.indexOf(true) < 0)
continue;
var uniqueArray = new Array();
delTr.forEach(function (deletedT) {
if (uniqueArray.indexOf(deletedT) === -1) {
deletedT.deletePending = true;
uniqueArray.push(deletedT);
}
});
if (uniqueArray.length % 2 !== 0) {
continue;
}
v0.q = v1.q.add(v0.q);
v0.updatePosition(p);
var tStart = _this.references.length;
deletedTriangles = _this.updateTriangles(v0, v0, deleted0, deletedTriangles);
deletedTriangles = _this.updateTriangles(v0, v1, deleted1, deletedTriangles);
var tCount = _this.references.length - tStart;
if (tCount <= v0.triangleCount) {
if (tCount) {
for (var c = 0; c < tCount; c++) {
_this.references[v0.triangleStart + c] = _this.references[tStart + c];
}
}
}
else {
v0.triangleStart = tStart;
}
v0.triangleCount = tCount;
break;
}
}
};
BABYLON.AsyncLoop.SyncAsyncForLoop(_this.triangles.length, _this.syncIterations, trianglesIterator, callback, function () { return (triangleCount - deletedTriangles <= targetCount); });
}, 0);
};
BABYLON.AsyncLoop.Run(this.decimationIterations, function (loop) {
if (triangleCount - deletedTriangles <= targetCount)
loop.breakLoop();
else {
iterationFunction(loop.index, function () {
loop.executeNext();
});
}
}, function () {
setTimeout(function () {
//reconstruct this part of the mesh
_this.reconstructMesh(submeshIndex);
successCallback();
}, 0);
});
};
QuadraticErrorSimplification.prototype.initWithMesh = function (submeshIndex, callback, optimizeMesh) {
var _this = this;
this.vertices = [];
this.triangles = [];
var positionData = this._mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
var indices = this._mesh.getIndices();
var submesh = this._mesh.subMeshes[submeshIndex];
var findInVertices = function (positionToSearch) {
if (optimizeMesh) {
for (var ii = 0; ii < _this.vertices.length; ++ii) {
if (_this.vertices[ii].position.equals(positionToSearch)) {
return _this.vertices[ii];
}
}
}
return null;
};
var vertexReferences = [];
var vertexInit = function (i) {
if (!positionData) {
return;
}
var offset = i + submesh.verticesStart;
var position = BABYLON.Vector3.FromArray(positionData, offset * 3);
var vertex = findInVertices(position) || new DecimationVertex(position, _this.vertices.length);
vertex.originalOffsets.push(offset);
if (vertex.id === _this.vertices.length) {
_this.vertices.push(vertex);
}
vertexReferences.push(vertex.id);
};
//var totalVertices = mesh.getTotalVertices();
var totalVertices = submesh.verticesCount;
BABYLON.AsyncLoop.SyncAsyncForLoop(totalVertices, (this.syncIterations / 4) >> 0, vertexInit, function () {
var indicesInit = function (i) {
if (!indices) {
return;
}
var offset = (submesh.indexStart / 3) + i;
var pos = (offset * 3);
var i0 = indices[pos + 0];
var i1 = indices[pos + 1];
var i2 = indices[pos + 2];
var v0 = _this.vertices[vertexReferences[i0 - submesh.verticesStart]];
var v1 = _this.vertices[vertexReferences[i1 - submesh.verticesStart]];
var v2 = _this.vertices[vertexReferences[i2 - submesh.verticesStart]];
var triangle = new DecimationTriangle([v0, v1, v2]);
triangle.originalOffset = pos;
_this.triangles.push(triangle);
};
BABYLON.AsyncLoop.SyncAsyncForLoop(submesh.indexCount / 3, _this.syncIterations, indicesInit, function () {
_this.init(callback);
});
});
};
QuadraticErrorSimplification.prototype.init = function (callback) {
var _this = this;
var triangleInit1 = function (i) {
var t = _this.triangles[i];
t.normal = BABYLON.Vector3.Cross(t.vertices[1].position.subtract(t.vertices[0].position), t.vertices[2].position.subtract(t.vertices[0].position)).normalize();
for (var j = 0; j < 3; j++) {
t.vertices[j].q.addArrayInPlace(QuadraticMatrix.DataFromNumbers(t.normal.x, t.normal.y, t.normal.z, -(BABYLON.Vector3.Dot(t.normal, t.vertices[0].position))));
}
};
BABYLON.AsyncLoop.SyncAsyncForLoop(this.triangles.length, this.syncIterations, triangleInit1, function () {
var triangleInit2 = function (i) {
var t = _this.triangles[i];
for (var j = 0; j < 3; ++j) {
t.error[j] = _this.calculateError(t.vertices[j], t.vertices[(j + 1) % 3]);
}
t.error[3] = Math.min(t.error[0], t.error[1], t.error[2]);
};
BABYLON.AsyncLoop.SyncAsyncForLoop(_this.triangles.length, _this.syncIterations, triangleInit2, function () {
callback();
});
});
};
QuadraticErrorSimplification.prototype.reconstructMesh = function (submeshIndex) {
var newTriangles = [];
var i;
for (i = 0; i < this.vertices.length; ++i) {
this.vertices[i].triangleCount = 0;
}
var t;
var j;
for (i = 0; i < this.triangles.length; ++i) {
if (!this.triangles[i].deleted) {
t = this.triangles[i];
for (j = 0; j < 3; ++j) {
t.vertices[j].triangleCount = 1;
}
newTriangles.push(t);
}
}
var newPositionData = (this._reconstructedMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind) || []);
var newNormalData = (this._reconstructedMesh.getVerticesData(BABYLON.VertexBuffer.NormalKind) || []);
var newUVsData = (this._reconstructedMesh.getVerticesData(BABYLON.VertexBuffer.UVKind) || []);
var newColorsData = (this._reconstructedMesh.getVerticesData(BABYLON.VertexBuffer.ColorKind) || []);
var normalData = this._mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind);
var uvs = this._mesh.getVerticesData(BABYLON.VertexBuffer.UVKind);
var colorsData = this._mesh.getVerticesData(BABYLON.VertexBuffer.ColorKind);
var vertexCount = 0;
for (i = 0; i < this.vertices.length; ++i) {
var vertex = this.vertices[i];
vertex.id = vertexCount;
if (vertex.triangleCount) {
vertex.originalOffsets.forEach(function (originalOffset) {
if (!normalData) {
return;
}
newPositionData.push(vertex.position.x);
newPositionData.push(vertex.position.y);
newPositionData.push(vertex.position.z);
newNormalData.push(normalData[originalOffset * 3]);
newNormalData.push(normalData[(originalOffset * 3) + 1]);
newNormalData.push(normalData[(originalOffset * 3) + 2]);
if (uvs && uvs.length) {
newUVsData.push(uvs[(originalOffset * 2)]);
newUVsData.push(uvs[(originalOffset * 2) + 1]);
}
else if (colorsData && colorsData.length) {
newColorsData.push(colorsData[(originalOffset * 4)]);
newColorsData.push(colorsData[(originalOffset * 4) + 1]);
newColorsData.push(colorsData[(originalOffset * 4) + 2]);
newColorsData.push(colorsData[(originalOffset * 4) + 3]);
}
++vertexCount;
});
}
}
var startingIndex = this._reconstructedMesh.getTotalIndices();
var startingVertex = this._reconstructedMesh.getTotalVertices();
var submeshesArray = this._reconstructedMesh.subMeshes;
this._reconstructedMesh.subMeshes = [];
var newIndicesArray = this._reconstructedMesh.getIndices(); //[];
var originalIndices = this._mesh.getIndices();
for (i = 0; i < newTriangles.length; ++i) {
t = newTriangles[i]; //now get the new referencing point for each vertex
[0, 1, 2].forEach(function (idx) {
var id = originalIndices[t.originalOffset + idx];
var offset = t.vertices[idx].originalOffsets.indexOf(id);
if (offset < 0)
offset = 0;
newIndicesArray.push(t.vertices[idx].id + offset + startingVertex);
});
}
//overwriting the old vertex buffers and indices.
this._reconstructedMesh.setIndices(newIndicesArray);
this._reconstructedMesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, newPositionData);
this._reconstructedMesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, newNormalData);
if (newUVsData.length > 0)
this._reconstructedMesh.setVerticesData(BABYLON.VertexBuffer.UVKind, newUVsData);
if (newColorsData.length > 0)
this._reconstructedMesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, newColorsData);
//create submesh
var originalSubmesh = this._mesh.subMeshes[submeshIndex];
if (submeshIndex > 0) {
this._reconstructedMesh.subMeshes = [];
submeshesArray.forEach(function (submesh) {
BABYLON.SubMesh.AddToMesh(submesh.materialIndex, submesh.verticesStart, submesh.verticesCount, /* 0, newPositionData.length/3, */ submesh.indexStart, submesh.indexCount, submesh.getMesh());
});
BABYLON.SubMesh.AddToMesh(originalSubmesh.materialIndex, startingVertex, vertexCount, /* 0, newPositionData.length / 3, */ startingIndex, newTriangles.length * 3, this._reconstructedMesh);
}
};
QuadraticErrorSimplification.prototype.initDecimatedMesh = function () {
this._reconstructedMesh = new BABYLON.Mesh(this._mesh.name + "Decimated", this._mesh.getScene());
this._reconstructedMesh.material = this._mesh.material;
this._reconstructedMesh.parent = this._mesh.parent;
this._reconstructedMesh.isVisible = false;
this._reconstructedMesh.renderingGroupId = this._mesh.renderingGroupId;
};
QuadraticErrorSimplification.prototype.isFlipped = function (vertex1, vertex2, point, deletedArray, borderFactor, delTr) {
for (var i = 0; i < vertex1.triangleCount; ++i) {
var t = this.triangles[this.references[vertex1.triangleStart + i].triangleId];
if (t.deleted)
continue;
var s = this.references[vertex1.triangleStart + i].vertexId;
var v1 = t.vertices[(s + 1) % 3];
var v2 = t.vertices[(s + 2) % 3];
if ((v1 === vertex2 || v2 === vertex2)) {
deletedArray[i] = true;
delTr.push(t);
continue;
}
var d1 = v1.position.subtract(point);
d1 = d1.normalize();
var d2 = v2.position.subtract(point);
d2 = d2.normalize();
if (Math.abs(BABYLON.Vector3.Dot(d1, d2)) > 0.999)
return true;
var normal = BABYLON.Vector3.Cross(d1, d2).normalize();
deletedArray[i] = false;
if (BABYLON.Vector3.Dot(normal, t.normal) < 0.2)
return true;
}
return false;
};
QuadraticErrorSimplification.prototype.updateTriangles = function (origVertex, vertex, deletedArray, deletedTriangles) {
var newDeleted = deletedTriangles;
for (var i = 0; i < vertex.triangleCount; ++i) {
var ref = this.references[vertex.triangleStart + i];
var t = this.triangles[ref.triangleId];
if (t.deleted)
continue;
if (deletedArray[i] && t.deletePending) {
t.deleted = true;
newDeleted++;
continue;
}
t.vertices[ref.vertexId] = origVertex;
t.isDirty = true;
t.error[0] = this.calculateError(t.vertices[0], t.vertices[1]) + (t.borderFactor / 2);
t.error[1] = this.calculateError(t.vertices[1], t.vertices[2]) + (t.borderFactor / 2);
t.error[2] = this.calculateError(t.vertices[2], t.vertices[0]) + (t.borderFactor / 2);
t.error[3] = Math.min(t.error[0], t.error[1], t.error[2]);
this.references.push(ref);
}
return newDeleted;
};
QuadraticErrorSimplification.prototype.identifyBorder = function () {
for (var i = 0; i < this.vertices.length; ++i) {
var vCount = [];
var vId = [];
var v = this.vertices[i];
var j;
for (j = 0; j < v.triangleCount; ++j) {
var triangle = this.triangles[this.references[v.triangleStart + j].triangleId];
for (var ii = 0; ii < 3; ii++) {
var ofs = 0;
var vv = triangle.vertices[ii];
while (ofs < vCount.length) {
if (vId[ofs] === vv.id)
break;
++ofs;
}
if (ofs === vCount.length) {
vCount.push(1);
vId.push(vv.id);
}
else {
vCount[ofs]++;
}
}
}
for (j = 0; j < vCount.length; ++j) {
if (vCount[j] === 1) {
this.vertices[vId[j]].isBorder = true;
}
else {
this.vertices[vId[j]].isBorder = false;
}
}
}
};
QuadraticErrorSimplification.prototype.updateMesh = function (identifyBorders) {
if (identifyBorders === void 0) { identifyBorders = false; }
var i;
if (!identifyBorders) {
var newTrianglesVector = [];
for (i = 0; i < this.triangles.length; ++i) {
if (!this.triangles[i].deleted) {
newTrianglesVector.push(this.triangles[i]);
}
}
this.triangles = newTrianglesVector;
}
for (i = 0; i < this.vertices.length; ++i) {
this.vertices[i].triangleCount = 0;
this.vertices[i].triangleStart = 0;
}
var t;
var j;
var v;
for (i = 0; i < this.triangles.length; ++i) {
t = this.triangles[i];
for (j = 0; j < 3; ++j) {
v = t.vertices[j];
v.triangleCount++;
}
}
var tStart = 0;
for (i = 0; i < this.vertices.length; ++i) {
this.vertices[i].triangleStart = tStart;
tStart += this.vertices[i].triangleCount;
this.vertices[i].triangleCount = 0;
}
var newReferences = new Array(this.triangles.length * 3);
for (i = 0; i < this.triangles.length; ++i) {
t = this.triangles[i];
for (j = 0; j < 3; ++j) {
v = t.vertices[j];
newReferences[v.triangleStart + v.triangleCount] = new Reference(j, i);
v.triangleCount++;
}
}
this.references = newReferences;
if (identifyBorders) {
this.identifyBorder();
}
};
QuadraticErrorSimplification.prototype.vertexError = function (q, point) {
var x = point.x;
var y = point.y;
var z = point.z;
return q.data[0] * x * x + 2 * q.data[1] * x * y + 2 * q.data[2] * x * z + 2 * q.data[3] * x + q.data[4] * y * y
+ 2 * q.data[5] * y * z + 2 * q.data[6] * y + q.data[7] * z * z + 2 * q.data[8] * z + q.data[9];
};
QuadraticErrorSimplification.prototype.calculateError = function (vertex1, vertex2, pointResult, normalResult, uvResult, colorResult) {
var q = vertex1.q.add(vertex2.q);
var border = vertex1.isBorder && vertex2.isBorder;
var error = 0;
var qDet = q.det(0, 1, 2, 1, 4, 5, 2, 5, 7);
if (qDet !== 0 && !border) {
if (!pointResult) {
pointResult = BABYLON.Vector3.Zero();
}
pointResult.x = -1 / qDet * (q.det(1, 2, 3, 4, 5, 6, 5, 7, 8));
pointResult.y = 1 / qDet * (q.det(0, 2, 3, 1, 5, 6, 2, 7, 8));
pointResult.z = -1 / qDet * (q.det(0, 1, 3, 1, 4, 6, 2, 5, 8));
error = this.vertexError(q, pointResult);
}
else {
var p3 = (vertex1.position.add(vertex2.position)).divide(new BABYLON.Vector3(2, 2, 2));
//var norm3 = (vertex1.normal.add(vertex2.normal)).divide(new Vector3(2, 2, 2)).normalize();
var error1 = this.vertexError(q, vertex1.position);
var error2 = this.vertexError(q, vertex2.position);
var error3 = this.vertexError(q, p3);
error = Math.min(error1, error2, error3);
if (error === error1) {
if (pointResult) {
pointResult.copyFrom(vertex1.position);
}
}
else if (error === error2) {
if (pointResult) {
pointResult.copyFrom(vertex2.position);
}
}
else {
if (pointResult) {
pointResult.copyFrom(p3);
}
}
}
return error;
};
return QuadraticErrorSimplification;
}());
BABYLON.QuadraticErrorSimplification = QuadraticErrorSimplification;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.meshSimplification.js.map
var BABYLON;
(function (BABYLON) {
var MeshLODLevel = /** @class */ (function () {
function MeshLODLevel(distance, mesh) {
this.distance = distance;
this.mesh = mesh;
}
return MeshLODLevel;
}());
BABYLON.MeshLODLevel = MeshLODLevel;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.meshLODLevel.js.map
var BABYLON;
(function (BABYLON) {
/**
* Defines the root class used to create scene optimization to use with SceneOptimizer
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var SceneOptimization = /** @class */ (function () {
/**
* Creates the SceneOptimization object
* @param priority defines the priority of this optimization (0 by default which means first in the list)
* @param desc defines the description associated with the optimization
*/
function SceneOptimization(
/**
* Defines the priority of this optimization (0 by default which means first in the list)
*/
priority) {
if (priority === void 0) { priority = 0; }
this.priority = priority;
}
/**
* Gets a string describing the action executed by the current optimization
* @returns description string
*/
SceneOptimization.prototype.getDescription = function () {
return "";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
SceneOptimization.prototype.apply = function (scene, optimizer) {
return true;
};
;
return SceneOptimization;
}());
BABYLON.SceneOptimization = SceneOptimization;
/**
* Defines an optimization used to reduce the size of render target textures
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var TextureOptimization = /** @class */ (function (_super) {
__extends(TextureOptimization, _super);
/**
* Creates the TextureOptimization object
* @param priority defines the priority of this optimization (0 by default which means first in the list)
* @param maximumSize defines the maximum sized allowed for textures (1024 is the default value). If a texture is bigger, it will be scaled down using a factor defined by the step parameter
* @param step defines the factor (0.5 by default) used to scale down textures bigger than maximum sized allowed.
*/
function TextureOptimization(
/**
* Defines the priority of this optimization (0 by default which means first in the list)
*/
priority,
/**
* Defines the maximum sized allowed for textures (1024 is the default value). If a texture is bigger, it will be scaled down using a factor defined by the step parameter
*/
maximumSize,
/**
* Defines the factor (0.5 by default) used to scale down textures bigger than maximum sized allowed.
*/
step) {
if (priority === void 0) { priority = 0; }
if (maximumSize === void 0) { maximumSize = 1024; }
if (step === void 0) { step = 0.5; }
var _this = _super.call(this, priority) || this;
_this.priority = priority;
_this.maximumSize = maximumSize;
_this.step = step;
return _this;
}
/**
* Gets a string describing the action executed by the current optimization
* @returns description string
*/
TextureOptimization.prototype.getDescription = function () {
return "Reducing render target texture size to " + this.maximumSize;
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
TextureOptimization.prototype.apply = function (scene, optimizer) {
var allDone = true;
for (var index = 0; index < scene.textures.length; index++) {
var texture = scene.textures[index];
if (!texture.canRescale || texture.getContext) {
continue;
}
var currentSize = texture.getSize();
var maxDimension = Math.max(currentSize.width, currentSize.height);
if (maxDimension > this.maximumSize) {
texture.scale(this.step);
allDone = false;
}
}
return allDone;
};
return TextureOptimization;
}(SceneOptimization));
BABYLON.TextureOptimization = TextureOptimization;
/**
* Defines an optimization used to increase or decrease the rendering resolution
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var HardwareScalingOptimization = /** @class */ (function (_super) {
__extends(HardwareScalingOptimization, _super);
/**
* Creates the HardwareScalingOptimization object
* @param priority defines the priority of this optimization (0 by default which means first in the list)
* @param maximumScale defines the maximum scale to use (2 by default)
* @param step defines the step to use between two passes (0.5 by default)
*/
function HardwareScalingOptimization(
/**
* Defines the priority of this optimization (0 by default which means first in the list)
*/
priority,
/**
* Defines the maximum scale to use (2 by default)
*/
maximumScale,
/**
* Defines the step to use between two passes (0.5 by default)
*/
step) {
if (priority === void 0) { priority = 0; }
if (maximumScale === void 0) { maximumScale = 2; }
if (step === void 0) { step = 0.25; }
var _this = _super.call(this, priority) || this;
_this.priority = priority;
_this.maximumScale = maximumScale;
_this.step = step;
_this._currentScale = -1;
_this._directionOffset = 1;
return _this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
HardwareScalingOptimization.prototype.getDescription = function () {
return "Setting hardware scaling level to " + this._currentScale;
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
HardwareScalingOptimization.prototype.apply = function (scene, optimizer) {
if (this._currentScale === -1) {
this._currentScale = scene.getEngine().getHardwareScalingLevel();
if (this._currentScale > this.maximumScale) {
this._directionOffset = -1;
}
}
this._currentScale += this._directionOffset * this.step;
scene.getEngine().setHardwareScalingLevel(this._currentScale);
return this._directionOffset === 1 ? this._currentScale >= this.maximumScale : this._currentScale <= this.maximumScale;
};
;
return HardwareScalingOptimization;
}(SceneOptimization));
BABYLON.HardwareScalingOptimization = HardwareScalingOptimization;
/**
* Defines an optimization used to remove shadows
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var ShadowsOptimization = /** @class */ (function (_super) {
__extends(ShadowsOptimization, _super);
function ShadowsOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
ShadowsOptimization.prototype.getDescription = function () {
return "Turning shadows on/off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
ShadowsOptimization.prototype.apply = function (scene, optimizer) {
scene.shadowsEnabled = optimizer.isInImprovementMode;
return true;
};
;
return ShadowsOptimization;
}(SceneOptimization));
BABYLON.ShadowsOptimization = ShadowsOptimization;
/**
* Defines an optimization used to turn post-processes off
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var PostProcessesOptimization = /** @class */ (function (_super) {
__extends(PostProcessesOptimization, _super);
function PostProcessesOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
PostProcessesOptimization.prototype.getDescription = function () {
return "Turning post-processes on/off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
PostProcessesOptimization.prototype.apply = function (scene, optimizer) {
scene.postProcessesEnabled = optimizer.isInImprovementMode;
return true;
};
;
return PostProcessesOptimization;
}(SceneOptimization));
BABYLON.PostProcessesOptimization = PostProcessesOptimization;
/**
* Defines an optimization used to turn lens flares off
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var LensFlaresOptimization = /** @class */ (function (_super) {
__extends(LensFlaresOptimization, _super);
function LensFlaresOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
LensFlaresOptimization.prototype.getDescription = function () {
return "Turning lens flares on/off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
LensFlaresOptimization.prototype.apply = function (scene, optimizer) {
scene.lensFlaresEnabled = optimizer.isInImprovementMode;
return true;
};
;
return LensFlaresOptimization;
}(SceneOptimization));
BABYLON.LensFlaresOptimization = LensFlaresOptimization;
/**
* Defines an optimization based on user defined callback.
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var CustomOptimization = /** @class */ (function (_super) {
__extends(CustomOptimization, _super);
function CustomOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @returns description string
*/
CustomOptimization.prototype.getDescription = function () {
if (this.onGetDescription) {
return this.onGetDescription();
}
return "Running user defined callback";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
CustomOptimization.prototype.apply = function (scene, optimizer) {
if (this.onApply) {
return this.onApply(scene, optimizer);
}
return true;
};
;
return CustomOptimization;
}(SceneOptimization));
BABYLON.CustomOptimization = CustomOptimization;
/**
* Defines an optimization used to turn particles off
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var ParticlesOptimization = /** @class */ (function (_super) {
__extends(ParticlesOptimization, _super);
function ParticlesOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
ParticlesOptimization.prototype.getDescription = function () {
return "Turning particles on/off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
ParticlesOptimization.prototype.apply = function (scene, optimizer) {
scene.particlesEnabled = optimizer.isInImprovementMode;
return true;
};
;
return ParticlesOptimization;
}(SceneOptimization));
BABYLON.ParticlesOptimization = ParticlesOptimization;
/**
* Defines an optimization used to turn render targets off
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var RenderTargetsOptimization = /** @class */ (function (_super) {
__extends(RenderTargetsOptimization, _super);
function RenderTargetsOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
RenderTargetsOptimization.prototype.getDescription = function () {
return "Turning render targets off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
RenderTargetsOptimization.prototype.apply = function (scene, optimizer) {
scene.renderTargetsEnabled = optimizer.isInImprovementMode;
return true;
};
;
return RenderTargetsOptimization;
}(SceneOptimization));
BABYLON.RenderTargetsOptimization = RenderTargetsOptimization;
/**
* Defines an optimization used to merge meshes with compatible materials
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var MergeMeshesOptimization = /** @class */ (function (_super) {
__extends(MergeMeshesOptimization, _super);
function MergeMeshesOptimization() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._canBeMerged = function (abstractMesh) {
if (!(abstractMesh instanceof BABYLON.Mesh)) {
return false;
}
var mesh = abstractMesh;
if (!mesh.isVisible || !mesh.isEnabled()) {
return false;
}
if (mesh.instances.length > 0) {
return false;
}
if (mesh.skeleton || mesh.hasLODLevels) {
return false;
}
if (mesh.parent) {
return false;
}
return true;
};
return _this;
}
Object.defineProperty(MergeMeshesOptimization, "UpdateSelectionTree", {
/**
* Gets or sets a boolean which defines if optimization octree has to be updated
*/
get: function () {
return MergeMeshesOptimization._UpdateSelectionTree;
},
/**
* Gets or sets a boolean which defines if optimization octree has to be updated
*/
set: function (value) {
MergeMeshesOptimization._UpdateSelectionTree = value;
},
enumerable: true,
configurable: true
});
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
MergeMeshesOptimization.prototype.getDescription = function () {
return "Merging similar meshes together";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @param updateSelectionTree defines that the selection octree has to be updated (false by default)
* @returns true if everything that can be done was applied
*/
MergeMeshesOptimization.prototype.apply = function (scene, optimizer, updateSelectionTree) {
var globalPool = scene.meshes.slice(0);
var globalLength = globalPool.length;
for (var index = 0; index < globalLength; index++) {
var currentPool = new Array();
var current = globalPool[index];
// Checks
if (!this._canBeMerged(current)) {
continue;
}
currentPool.push(current);
// Find compatible meshes
for (var subIndex = index + 1; subIndex < globalLength; subIndex++) {
var otherMesh = globalPool[subIndex];
if (!this._canBeMerged(otherMesh)) {
continue;
}
if (otherMesh.material !== current.material) {
continue;
}
if (otherMesh.checkCollisions !== current.checkCollisions) {
continue;
}
currentPool.push(otherMesh);
globalLength--;
globalPool.splice(subIndex, 1);
subIndex--;
}
if (currentPool.length < 2) {
continue;
}
// Merge meshes
BABYLON.Mesh.MergeMeshes(currentPool, undefined, true);
}
if (updateSelectionTree != undefined) {
if (updateSelectionTree) {
scene.createOrUpdateSelectionOctree();
}
}
else if (MergeMeshesOptimization.UpdateSelectionTree) {
scene.createOrUpdateSelectionOctree();
}
return true;
};
;
MergeMeshesOptimization._UpdateSelectionTree = false;
return MergeMeshesOptimization;
}(SceneOptimization));
BABYLON.MergeMeshesOptimization = MergeMeshesOptimization;
/**
* Defines a list of options used by SceneOptimizer
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var SceneOptimizerOptions = /** @class */ (function () {
/**
* Creates a new list of options used by SceneOptimizer
* @param targetFrameRate defines the target frame rate to reach (60 by default)
* @param trackerDuration defines the interval between two checkes (2000ms by default)
*/
function SceneOptimizerOptions(
/**
* Defines the target frame rate to reach (60 by default)
*/
targetFrameRate,
/**
* Defines the interval between two checkes (2000ms by default)
*/
trackerDuration) {
if (targetFrameRate === void 0) { targetFrameRate = 60; }
if (trackerDuration === void 0) { trackerDuration = 2000; }
this.targetFrameRate = targetFrameRate;
this.trackerDuration = trackerDuration;
/**
* Gets the list of optimizations to apply
*/
this.optimizations = new Array();
}
/**
* Add a new optimization
* @param optimization defines the SceneOptimization to add to the list of active optimizations
* @returns the current SceneOptimizerOptions
*/
SceneOptimizerOptions.prototype.addOptimization = function (optimization) {
this.optimizations.push(optimization);
return this;
};
/**
* Add a new custom optimization
* @param onApply defines the callback called to apply the custom optimization (true if everything that can be done was applied)
* @param onGetDescription defines the callback called to get the description attached with the optimization.
* @param priority defines the priority of this optimization (0 by default which means first in the list)
* @returns the current SceneOptimizerOptions
*/
SceneOptimizerOptions.prototype.addCustomOptimization = function (onApply, onGetDescription, priority) {
if (priority === void 0) { priority = 0; }
var optimization = new CustomOptimization(priority);
optimization.onApply = onApply;
optimization.onGetDescription = onGetDescription;
this.optimizations.push(optimization);
return this;
};
/**
* Creates a list of pre-defined optimizations aimed to reduce the visual impact on the scene
* @param targetFrameRate defines the target frame rate (60 by default)
* @returns a SceneOptimizerOptions object
*/
SceneOptimizerOptions.LowDegradationAllowed = function (targetFrameRate) {
var result = new SceneOptimizerOptions(targetFrameRate);
var priority = 0;
result.addOptimization(new MergeMeshesOptimization(priority));
result.addOptimization(new ShadowsOptimization(priority));
result.addOptimization(new LensFlaresOptimization(priority));
// Next priority
priority++;
result.addOptimization(new PostProcessesOptimization(priority));
result.addOptimization(new ParticlesOptimization(priority));
// Next priority
priority++;
result.addOptimization(new TextureOptimization(priority, 1024));
return result;
};
/**
* Creates a list of pre-defined optimizations aimed to have a moderate impact on the scene visual
* @param targetFrameRate defines the target frame rate (60 by default)
* @returns a SceneOptimizerOptions object
*/
SceneOptimizerOptions.ModerateDegradationAllowed = function (targetFrameRate) {
var result = new SceneOptimizerOptions(targetFrameRate);
var priority = 0;
result.addOptimization(new MergeMeshesOptimization(priority));
result.addOptimization(new ShadowsOptimization(priority));
result.addOptimization(new LensFlaresOptimization(priority));
// Next priority
priority++;
result.addOptimization(new PostProcessesOptimization(priority));
result.addOptimization(new ParticlesOptimization(priority));
// Next priority
priority++;
result.addOptimization(new TextureOptimization(priority, 512));
// Next priority
priority++;
result.addOptimization(new RenderTargetsOptimization(priority));
// Next priority
priority++;
result.addOptimization(new HardwareScalingOptimization(priority, 2));
return result;
};
/**
* Creates a list of pre-defined optimizations aimed to have a big impact on the scene visual
* @param targetFrameRate defines the target frame rate (60 by default)
* @returns a SceneOptimizerOptions object
*/
SceneOptimizerOptions.HighDegradationAllowed = function (targetFrameRate) {
var result = new SceneOptimizerOptions(targetFrameRate);
var priority = 0;
result.addOptimization(new MergeMeshesOptimization(priority));
result.addOptimization(new ShadowsOptimization(priority));
result.addOptimization(new LensFlaresOptimization(priority));
// Next priority
priority++;
result.addOptimization(new PostProcessesOptimization(priority));
result.addOptimization(new ParticlesOptimization(priority));
// Next priority
priority++;
result.addOptimization(new TextureOptimization(priority, 256));
// Next priority
priority++;
result.addOptimization(new RenderTargetsOptimization(priority));
// Next priority
priority++;
result.addOptimization(new HardwareScalingOptimization(priority, 4));
return result;
};
return SceneOptimizerOptions;
}());
BABYLON.SceneOptimizerOptions = SceneOptimizerOptions;
/**
* Class used to run optimizations in order to reach a target frame rate
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var SceneOptimizer = /** @class */ (function () {
/**
* Creates a new SceneOptimizer
* @param scene defines the scene to work on
* @param options defines the options to use with the SceneOptimizer
* @param autoGeneratePriorities defines if priorities must be generated and not read from SceneOptimization property (true by default)
* @param improvementMode defines if the scene optimizer must run the maximum optimization while staying over a target frame instead of trying to reach the target framerate (false by default)
*/
function SceneOptimizer(scene, options, autoGeneratePriorities, improvementMode) {
if (autoGeneratePriorities === void 0) { autoGeneratePriorities = true; }
if (improvementMode === void 0) { improvementMode = false; }
var _this = this;
this._isRunning = false;
this._currentPriorityLevel = 0;
this._targetFrameRate = 60;
this._trackerDuration = 2000;
this._currentFrameRate = 0;
this._improvementMode = false;
/**
* Defines an observable called when the optimizer reaches the target frame rate
*/
this.onSuccessObservable = new BABYLON.Observable();
/**
* Defines an observable called when the optimizer enables an optimization
*/
this.onNewOptimizationAppliedObservable = new BABYLON.Observable();
/**
* Defines an observable called when the optimizer is not able to reach the target frame rate
*/
this.onFailureObservable = new BABYLON.Observable();
if (!options) {
this._options = new SceneOptimizerOptions();
}
else {
this._options = options;
}
if (this._options.targetFrameRate) {
this._targetFrameRate = this._options.targetFrameRate;
}
if (this._options.trackerDuration) {
this._trackerDuration = this._options.trackerDuration;
}
if (autoGeneratePriorities) {
var priority = 0;
for (var _i = 0, _a = this._options.optimizations; _i < _a.length; _i++) {
var optim = _a[_i];
optim.priority = priority++;
}
}
this._improvementMode = improvementMode;
this._scene = scene || BABYLON.Engine.LastCreatedScene;
this._sceneDisposeObserver = this._scene.onDisposeObservable.add(function () {
_this._sceneDisposeObserver = null;
_this.dispose();
});
}
Object.defineProperty(SceneOptimizer.prototype, "isInImprovementMode", {
/**
* Gets a boolean indicating if the optimizer is in improvement mode
*/
get: function () {
return this._improvementMode;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "currentPriorityLevel", {
/**
* Gets the current priority level (0 at start)
*/
get: function () {
return this._currentPriorityLevel;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "currentFrameRate", {
/**
* Gets the current frame rate checked by the SceneOptimizer
*/
get: function () {
return this._currentFrameRate;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "targetFrameRate", {
/**
* Gets or sets the current target frame rate (60 by default)
*/
get: function () {
return this._targetFrameRate;
},
/**
* Gets or sets the current target frame rate (60 by default)
*/
set: function (value) {
this._targetFrameRate = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "trackerDuration", {
/**
* Gets or sets the current interval between two checks (every 2000ms by default)
*/
get: function () {
return this._trackerDuration;
},
/**
* Gets or sets the current interval between two checks (every 2000ms by default)
*/
set: function (value) {
this._trackerDuration = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "optimizations", {
/**
* Gets the list of active optimizations
*/
get: function () {
return this._options.optimizations;
},
enumerable: true,
configurable: true
});
/**
* Stops the current optimizer
*/
SceneOptimizer.prototype.stop = function () {
this._isRunning = false;
};
/**
* Reset the optimizer to initial step (current priority level = 0)
*/
SceneOptimizer.prototype.reset = function () {
this._currentPriorityLevel = 0;
};
/**
* Start the optimizer. By default it will try to reach a specific framerate
* but if the optimizer is set with improvementMode === true then it will run all optimiatiation while frame rate is above the target frame rate
*/
SceneOptimizer.prototype.start = function () {
var _this = this;
if (this._isRunning) {
return;
}
this._isRunning = true;
// Let's wait for the scene to be ready before running our check
this._scene.executeWhenReady(function () {
setTimeout(function () {
_this._checkCurrentState();
}, _this._trackerDuration);
});
};
SceneOptimizer.prototype._checkCurrentState = function () {
var _this = this;
if (!this._isRunning) {
return;
}
var scene = this._scene;
var options = this._options;
this._currentFrameRate = Math.round(scene.getEngine().getFps());
if (this._improvementMode && this._currentFrameRate <= this._targetFrameRate ||
!this._improvementMode && this._currentFrameRate >= this._targetFrameRate) {
this._isRunning = false;
this.onSuccessObservable.notifyObservers(this);
return;
}
// Apply current level of optimizations
var allDone = true;
var noOptimizationApplied = true;
for (var index = 0; index < options.optimizations.length; index++) {
var optimization = options.optimizations[index];
if (optimization.priority === this._currentPriorityLevel) {
noOptimizationApplied = false;
allDone = allDone && optimization.apply(scene, this);
this.onNewOptimizationAppliedObservable.notifyObservers(optimization);
}
}
// If no optimization was applied, this is a failure :(
if (noOptimizationApplied) {
this._isRunning = false;
this.onFailureObservable.notifyObservers(this);
return;
}
// If all optimizations were done, move to next level
if (allDone) {
this._currentPriorityLevel++;
}
// Let's the system running for a specific amount of time before checking FPS
scene.executeWhenReady(function () {
setTimeout(function () {
_this._checkCurrentState();
}, _this._trackerDuration);
});
};
/**
* Release all resources
*/
SceneOptimizer.prototype.dispose = function () {
this.stop();
this.onSuccessObservable.clear();
this.onFailureObservable.clear();
this.onNewOptimizationAppliedObservable.clear();
if (this._sceneDisposeObserver) {
this._scene.onDisposeObservable.remove(this._sceneDisposeObserver);
}
};
/**
* Helper function to create a SceneOptimizer with one single line of code
* @param scene defines the scene to work on
* @param options defines the options to use with the SceneOptimizer
* @param onSuccess defines a callback to call on success
* @param onFailure defines a callback to call on failure
* @returns the new SceneOptimizer object
*/
SceneOptimizer.OptimizeAsync = function (scene, options, onSuccess, onFailure) {
var optimizer = new SceneOptimizer(scene, options || SceneOptimizerOptions.ModerateDegradationAllowed(), false);
if (onSuccess) {
optimizer.onSuccessObservable.add(function () {
onSuccess();
});
}
if (onFailure) {
optimizer.onFailureObservable.add(function () {
onFailure();
});
}
optimizer.start();
return optimizer;
};
return SceneOptimizer;
}());
BABYLON.SceneOptimizer = SceneOptimizer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.sceneOptimizer.js.map
var BABYLON;
(function (BABYLON) {
var OutlineRenderer = /** @class */ (function () {
function OutlineRenderer(scene) {
this.zOffset = 1;
this._scene = scene;
}
OutlineRenderer.prototype.render = function (subMesh, batch, useOverlay) {
var _this = this;
if (useOverlay === void 0) { useOverlay = false; }
var scene = this._scene;
var engine = this._scene.getEngine();
var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
if (!this.isReady(subMesh, hardwareInstancedRendering)) {
return;
}
var mesh = subMesh.getRenderingMesh();
var material = subMesh.getMaterial();
if (!material || !scene.activeCamera) {
return;
}
engine.enableEffect(this._effect);
// Logarithmic depth
if (material.useLogarithmicDepth) {
this._effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));
}
this._effect.setFloat("offset", useOverlay ? 0 : mesh.outlineWidth);
this._effect.setColor4("color", useOverlay ? mesh.overlayColor : mesh.outlineColor, useOverlay ? mesh.overlayAlpha : material.alpha);
this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
// Bones
if (mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices(mesh));
}
mesh._bind(subMesh, this._effect, BABYLON.Material.TriangleFillMode);
// Alpha test
if (material && material.needAlphaTesting()) {
var alphaTexture = material.getAlphaTestTexture();
if (alphaTexture) {
this._effect.setTexture("diffuseSampler", alphaTexture);
this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
}
}
engine.setZOffset(-this.zOffset);
mesh._processRendering(subMesh, this._effect, BABYLON.Material.TriangleFillMode, batch, hardwareInstancedRendering, function (isInstance, world) { _this._effect.setMatrix("world", world); });
engine.setZOffset(0);
};
OutlineRenderer.prototype.isReady = function (subMesh, useInstances) {
var defines = [];
var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
var mesh = subMesh.getMesh();
var material = subMesh.getMaterial();
if (material) {
// Alpha test
if (material.needAlphaTesting()) {
defines.push("#define ALPHATEST");
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
attribs.push(BABYLON.VertexBuffer.UVKind);
defines.push("#define UV1");
}
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
attribs.push(BABYLON.VertexBuffer.UV2Kind);
defines.push("#define UV2");
}
}
//Logarithmic depth
if (material.useLogarithmicDepth) {
defines.push("#define LOGARITHMICDEPTH");
}
}
// Bones
if (mesh.useBones && mesh.computeBonesUsingShaders) {
attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
if (mesh.numBoneInfluencers > 4) {
attribs.push(BABYLON.VertexBuffer.MatricesIndicesExtraKind);
attribs.push(BABYLON.VertexBuffer.MatricesWeightsExtraKind);
}
defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
defines.push("#define BonesPerMesh " + (mesh.skeleton ? mesh.skeleton.bones.length + 1 : 0));
}
else {
defines.push("#define NUM_BONE_INFLUENCERS 0");
}
// Instances
if (useInstances) {
defines.push("#define INSTANCES");
attribs.push("world0");
attribs.push("world1");
attribs.push("world2");
attribs.push("world3");
}
// Get correct effect
var join = defines.join("\n");
if (this._cachedDefines !== join) {
this._cachedDefines = join;
this._effect = this._scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"], ["diffuseSampler"], join);
}
return this._effect.isReady();
};
return OutlineRenderer;
}());
BABYLON.OutlineRenderer = OutlineRenderer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.outlineRenderer.js.map
var BABYLON;
(function (BABYLON) {
var FaceAdjacencies = /** @class */ (function () {
function FaceAdjacencies() {
this.edges = new Array();
this.edgesConnectedCount = 0;
}
return FaceAdjacencies;
}());
var EdgesRenderer = /** @class */ (function () {
// Beware when you use this class with complex objects as the adjacencies computation can be really long
function EdgesRenderer(source, epsilon, checkVerticesInsteadOfIndices) {
if (epsilon === void 0) { epsilon = 0.95; }
if (checkVerticesInsteadOfIndices === void 0) { checkVerticesInsteadOfIndices = false; }
this.edgesWidthScalerForOrthographic = 1000.0;
this.edgesWidthScalerForPerspective = 50.0;
this._linesPositions = new Array();
this._linesNormals = new Array();
this._linesIndices = new Array();
this._buffers = {};
this._checkVerticesInsteadOfIndices = false;
this._source = source;
this._checkVerticesInsteadOfIndices = checkVerticesInsteadOfIndices;
this._epsilon = epsilon;
this._prepareRessources();
this._generateEdgesLines();
}
EdgesRenderer.prototype._prepareRessources = function () {
if (this._lineShader) {
return;
}
this._lineShader = new BABYLON.ShaderMaterial("lineShader", this._source.getScene(), "line", {
attributes: ["position", "normal"],
uniforms: ["worldViewProjection", "color", "width", "aspectRatio"]
});
this._lineShader.disableDepthWrite = true;
this._lineShader.backFaceCulling = false;
};
EdgesRenderer.prototype._rebuild = function () {
var buffer = this._buffers[BABYLON.VertexBuffer.PositionKind];
if (buffer) {
buffer._rebuild();
}
buffer = this._buffers[BABYLON.VertexBuffer.NormalKind];
if (buffer) {
buffer._rebuild();
}
var scene = this._source.getScene();
var engine = scene.getEngine();
this._ib = engine.createIndexBuffer(this._linesIndices);
};
EdgesRenderer.prototype.dispose = function () {
var buffer = this._buffers[BABYLON.VertexBuffer.PositionKind];
if (buffer) {
buffer.dispose();
this._buffers[BABYLON.VertexBuffer.PositionKind] = null;
}
buffer = this._buffers[BABYLON.VertexBuffer.NormalKind];
if (buffer) {
buffer.dispose();
this._buffers[BABYLON.VertexBuffer.NormalKind] = null;
}
this._source.getScene().getEngine()._releaseBuffer(this._ib);
this._lineShader.dispose();
};
EdgesRenderer.prototype._processEdgeForAdjacencies = function (pa, pb, p0, p1, p2) {
if (pa === p0 && pb === p1 || pa === p1 && pb === p0) {
return 0;
}
if (pa === p1 && pb === p2 || pa === p2 && pb === p1) {
return 1;
}
if (pa === p2 && pb === p0 || pa === p0 && pb === p2) {
return 2;
}
return -1;
};
EdgesRenderer.prototype._processEdgeForAdjacenciesWithVertices = function (pa, pb, p0, p1, p2) {
if (pa.equalsWithEpsilon(p0) && pb.equalsWithEpsilon(p1) || pa.equalsWithEpsilon(p1) && pb.equalsWithEpsilon(p0)) {
return 0;
}
if (pa.equalsWithEpsilon(p1) && pb.equalsWithEpsilon(p2) || pa.equalsWithEpsilon(p2) && pb.equalsWithEpsilon(p1)) {
return 1;
}
if (pa.equalsWithEpsilon(p2) && pb.equalsWithEpsilon(p0) || pa.equalsWithEpsilon(p0) && pb.equalsWithEpsilon(p2)) {
return 2;
}
return -1;
};
EdgesRenderer.prototype._checkEdge = function (faceIndex, edge, faceNormals, p0, p1) {
var needToCreateLine;
if (edge === undefined) {
needToCreateLine = true;
}
else {
var dotProduct = BABYLON.Vector3.Dot(faceNormals[faceIndex], faceNormals[edge]);
needToCreateLine = dotProduct < this._epsilon;
}
if (needToCreateLine) {
var offset = this._linesPositions.length / 3;
var normal = p0.subtract(p1);
normal.normalize();
// Positions
this._linesPositions.push(p0.x);
this._linesPositions.push(p0.y);
this._linesPositions.push(p0.z);
this._linesPositions.push(p0.x);
this._linesPositions.push(p0.y);
this._linesPositions.push(p0.z);
this._linesPositions.push(p1.x);
this._linesPositions.push(p1.y);
this._linesPositions.push(p1.z);
this._linesPositions.push(p1.x);
this._linesPositions.push(p1.y);
this._linesPositions.push(p1.z);
// Normals
this._linesNormals.push(p1.x);
this._linesNormals.push(p1.y);
this._linesNormals.push(p1.z);
this._linesNormals.push(-1);
this._linesNormals.push(p1.x);
this._linesNormals.push(p1.y);
this._linesNormals.push(p1.z);
this._linesNormals.push(1);
this._linesNormals.push(p0.x);
this._linesNormals.push(p0.y);
this._linesNormals.push(p0.z);
this._linesNormals.push(-1);
this._linesNormals.push(p0.x);
this._linesNormals.push(p0.y);
this._linesNormals.push(p0.z);
this._linesNormals.push(1);
// Indices
this._linesIndices.push(offset);
this._linesIndices.push(offset + 1);
this._linesIndices.push(offset + 2);
this._linesIndices.push(offset);
this._linesIndices.push(offset + 2);
this._linesIndices.push(offset + 3);
}
};
EdgesRenderer.prototype._generateEdgesLines = function () {
var positions = this._source.getVerticesData(BABYLON.VertexBuffer.PositionKind);
var indices = this._source.getIndices();
if (!indices || !positions) {
return;
}
// First let's find adjacencies
var adjacencies = new Array();
var faceNormals = new Array();
var index;
var faceAdjacencies;
// Prepare faces
for (index = 0; index < indices.length; index += 3) {
faceAdjacencies = new FaceAdjacencies();
var p0Index = indices[index];
var p1Index = indices[index + 1];
var p2Index = indices[index + 2];
faceAdjacencies.p0 = new BABYLON.Vector3(positions[p0Index * 3], positions[p0Index * 3 + 1], positions[p0Index * 3 + 2]);
faceAdjacencies.p1 = new BABYLON.Vector3(positions[p1Index * 3], positions[p1Index * 3 + 1], positions[p1Index * 3 + 2]);
faceAdjacencies.p2 = new BABYLON.Vector3(positions[p2Index * 3], positions[p2Index * 3 + 1], positions[p2Index * 3 + 2]);
var faceNormal = BABYLON.Vector3.Cross(faceAdjacencies.p1.subtract(faceAdjacencies.p0), faceAdjacencies.p2.subtract(faceAdjacencies.p1));
faceNormal.normalize();
faceNormals.push(faceNormal);
adjacencies.push(faceAdjacencies);
}
// Scan
for (index = 0; index < adjacencies.length; index++) {
faceAdjacencies = adjacencies[index];
for (var otherIndex = index + 1; otherIndex < adjacencies.length; otherIndex++) {
var otherFaceAdjacencies = adjacencies[otherIndex];
if (faceAdjacencies.edgesConnectedCount === 3) { // Full
break;
}
if (otherFaceAdjacencies.edgesConnectedCount === 3) { // Full
continue;
}
var otherP0 = indices[otherIndex * 3];
var otherP1 = indices[otherIndex * 3 + 1];
var otherP2 = indices[otherIndex * 3 + 2];
for (var edgeIndex = 0; edgeIndex < 3; edgeIndex++) {
var otherEdgeIndex = 0;
if (faceAdjacencies.edges[edgeIndex] !== undefined) {
continue;
}
switch (edgeIndex) {
case 0:
if (this._checkVerticesInsteadOfIndices) {
otherEdgeIndex = this._processEdgeForAdjacenciesWithVertices(faceAdjacencies.p0, faceAdjacencies.p1, otherFaceAdjacencies.p0, otherFaceAdjacencies.p1, otherFaceAdjacencies.p2);
}
else {
otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3], indices[index * 3 + 1], otherP0, otherP1, otherP2);
}
break;
case 1:
if (this._checkVerticesInsteadOfIndices) {
otherEdgeIndex = this._processEdgeForAdjacenciesWithVertices(faceAdjacencies.p1, faceAdjacencies.p2, otherFaceAdjacencies.p0, otherFaceAdjacencies.p1, otherFaceAdjacencies.p2);
}
else {
otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 1], indices[index * 3 + 2], otherP0, otherP1, otherP2);
}
break;
case 2:
if (this._checkVerticesInsteadOfIndices) {
otherEdgeIndex = this._processEdgeForAdjacenciesWithVertices(faceAdjacencies.p2, faceAdjacencies.p0, otherFaceAdjacencies.p0, otherFaceAdjacencies.p1, otherFaceAdjacencies.p2);
}
else {
otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 2], indices[index * 3], otherP0, otherP1, otherP2);
}
break;
}
if (otherEdgeIndex === -1) {
continue;
}
faceAdjacencies.edges[edgeIndex] = otherIndex;
otherFaceAdjacencies.edges[otherEdgeIndex] = index;
faceAdjacencies.edgesConnectedCount++;
otherFaceAdjacencies.edgesConnectedCount++;
if (faceAdjacencies.edgesConnectedCount === 3) {
break;
}
}
}
}
// Create lines
for (index = 0; index < adjacencies.length; index++) {
// We need a line when a face has no adjacency on a specific edge or if all the adjacencies has an angle greater than epsilon
var current = adjacencies[index];
this._checkEdge(index, current.edges[0], faceNormals, current.p0, current.p1);
this._checkEdge(index, current.edges[1], faceNormals, current.p1, current.p2);
this._checkEdge(index, current.edges[2], faceNormals, current.p2, current.p0);
}
// Merge into a single mesh
var engine = this._source.getScene().getEngine();
this._buffers[BABYLON.VertexBuffer.PositionKind] = new BABYLON.VertexBuffer(engine, this._linesPositions, BABYLON.VertexBuffer.PositionKind, false);
this._buffers[BABYLON.VertexBuffer.NormalKind] = new BABYLON.VertexBuffer(engine, this._linesNormals, BABYLON.VertexBuffer.NormalKind, false, false, 4);
this._ib = engine.createIndexBuffer(this._linesIndices);
this._indicesCount = this._linesIndices.length;
};
EdgesRenderer.prototype.render = function () {
var scene = this._source.getScene();
if (!this._lineShader.isReady() || !scene.activeCamera) {
return;
}
var engine = scene.getEngine();
this._lineShader._preBind();
// VBOs
engine.bindBuffers(this._buffers, this._ib, this._lineShader.getEffect());
scene.resetCachedMaterial();
this._lineShader.setColor4("color", this._source.edgesColor);
if (scene.activeCamera.mode === BABYLON.Camera.ORTHOGRAPHIC_CAMERA) {
this._lineShader.setFloat("width", this._source.edgesWidth / this.edgesWidthScalerForOrthographic);
}
else {
this._lineShader.setFloat("width", this._source.edgesWidth / this.edgesWidthScalerForPerspective);
}
this._lineShader.setFloat("aspectRatio", engine.getAspectRatio(scene.activeCamera));
this._lineShader.bind(this._source.getWorldMatrix());
// Draw order
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, this._indicesCount);
this._lineShader.unbind();
engine.setDepthWrite(true);
};
return EdgesRenderer;
}());
BABYLON.EdgesRenderer = EdgesRenderer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.edgesRenderer.js.map
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var BABYLON;
(function (BABYLON) {
/**
* The effect layer Helps adding post process effect blended with the main pass.
*
* This can be for instance use to generate glow or higlight effects on the scene.
*
* The effect layer class can not be used directly and is intented to inherited from to be
* customized per effects.
*/
var EffectLayer = /** @class */ (function () {
/**
* Instantiates a new effect Layer and references it in the scene.
* @param name The name of the layer
* @param scene The scene to use the layer in
*/
function EffectLayer(
/** The Friendly of the effect in the scene */
name, scene) {
this._vertexBuffers = {};
this._maxSize = 0;
this._mainTextureDesiredSize = { width: 0, height: 0 };
this._shouldRender = true;
this._postProcesses = [];
this._textures = [];
this._emissiveTextureAndColor = { texture: null, color: new BABYLON.Color4() };
/**
* The clear color of the texture used to generate the glow map.
*/
this.neutralColor = new BABYLON.Color4();
/**
* Specifies wether the highlight layer is enabled or not.
*/
this.isEnabled = true;
/**
* An event triggered when the effect layer has been disposed.
*/
this.onDisposeObservable = new BABYLON.Observable();
/**
* An event triggered when the effect layer is about rendering the main texture with the glowy parts.
*/
this.onBeforeRenderMainTextureObservable = new BABYLON.Observable();
/**
* An event triggered when the generated texture is being merged in the scene.
*/
this.onBeforeComposeObservable = new BABYLON.Observable();
/**
* An event triggered when the generated texture has been merged in the scene.
*/
this.onAfterComposeObservable = new BABYLON.Observable();
/**
* An event triggered when the efffect layer changes its size.
*/
this.onSizeChangedObservable = new BABYLON.Observable();
this.name = name;
this._scene = scene || BABYLON.Engine.LastCreatedScene;
this._engine = scene.getEngine();
this._maxSize = this._engine.getCaps().maxTextureSize;
this._scene.effectLayers.push(this);
// Generate Buffers
this._generateIndexBuffer();
this._genrateVertexBuffer();
}
Object.defineProperty(EffectLayer.prototype, "camera", {
/**
* Gets the camera attached to the layer.
*/
get: function () {
return this._effectLayerOptions.camera;
},
enumerable: true,
configurable: true
});
/**
* Initializes the effect layer with the required options.
* @param options Sets of none mandatory options to use with the layer (see IEffectLayerOptions for more information)
*/
EffectLayer.prototype._init = function (options) {
// Adapt options
this._effectLayerOptions = __assign({ mainTextureRatio: 0.5, alphaBlendingMode: BABYLON.Engine.ALPHA_COMBINE, camera: null }, options);
this._setMainTextureSize();
this._createMainTexture();
this._createTextureAndPostProcesses();
this._mergeEffect = this._createMergeEffect();
};
/**
* Generates the index buffer of the full screen quad blending to the main canvas.
*/
EffectLayer.prototype._generateIndexBuffer = function () {
// Indices
var indices = [];
indices.push(0);
indices.push(1);
indices.push(2);
indices.push(0);
indices.push(2);
indices.push(3);
this._indexBuffer = this._engine.createIndexBuffer(indices);
};
/**
* Generates the vertex buffer of the full screen quad blending to the main canvas.
*/
EffectLayer.prototype._genrateVertexBuffer = function () {
// VBO
var vertices = [];
vertices.push(1, 1);
vertices.push(-1, 1);
vertices.push(-1, -1);
vertices.push(1, -1);
var vertexBuffer = new BABYLON.VertexBuffer(this._engine, vertices, BABYLON.VertexBuffer.PositionKind, false, false, 2);
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = vertexBuffer;
};
/**
* Sets the main texture desired size which is the closest power of two
* of the engine canvas size.
*/
EffectLayer.prototype._setMainTextureSize = function () {
if (this._effectLayerOptions.mainTextureFixedSize) {
this._mainTextureDesiredSize.width = this._effectLayerOptions.mainTextureFixedSize;
this._mainTextureDesiredSize.height = this._effectLayerOptions.mainTextureFixedSize;
}
else {
this._mainTextureDesiredSize.width = this._engine.getRenderWidth() * this._effectLayerOptions.mainTextureRatio;
this._mainTextureDesiredSize.height = this._engine.getRenderHeight() * this._effectLayerOptions.mainTextureRatio;
this._mainTextureDesiredSize.width = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(this._mainTextureDesiredSize.width, this._maxSize) : this._mainTextureDesiredSize.width;
this._mainTextureDesiredSize.height = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(this._mainTextureDesiredSize.height, this._maxSize) : this._mainTextureDesiredSize.height;
}
this._mainTextureDesiredSize.width = Math.floor(this._mainTextureDesiredSize.width);
this._mainTextureDesiredSize.height = Math.floor(this._mainTextureDesiredSize.height);
};
/**
* Creates the main texture for the effect layer.
*/
EffectLayer.prototype._createMainTexture = function () {
var _this = this;
this._mainTexture = new BABYLON.RenderTargetTexture("HighlightLayerMainRTT", {
width: this._mainTextureDesiredSize.width,
height: this._mainTextureDesiredSize.height
}, this._scene, false, true, BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
this._mainTexture.activeCamera = this._effectLayerOptions.camera;
this._mainTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._mainTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._mainTexture.anisotropicFilteringLevel = 1;
this._mainTexture.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE);
this._mainTexture.renderParticles = false;
this._mainTexture.renderList = null;
this._mainTexture.ignoreCameraViewport = true;
// Custom render function
this._mainTexture.customRenderFunction = function (opaqueSubMeshes, alphaTestSubMeshes, transparentSubMeshes, depthOnlySubMeshes) {
_this.onBeforeRenderMainTextureObservable.notifyObservers(_this);
var index;
var engine = _this._scene.getEngine();
if (depthOnlySubMeshes.length) {
engine.setColorWrite(false);
for (index = 0; index < depthOnlySubMeshes.length; index++) {
_this._renderSubMesh(depthOnlySubMeshes.data[index]);
}
engine.setColorWrite(true);
}
for (index = 0; index < opaqueSubMeshes.length; index++) {
_this._renderSubMesh(opaqueSubMeshes.data[index]);
}
for (index = 0; index < alphaTestSubMeshes.length; index++) {
_this._renderSubMesh(alphaTestSubMeshes.data[index]);
}
for (index = 0; index < transparentSubMeshes.length; index++) {
_this._renderSubMesh(transparentSubMeshes.data[index]);
}
};
this._mainTexture.onClearObservable.add(function (engine) {
engine.clear(_this.neutralColor, true, true, true);
});
};
/**
* Checks for the readiness of the element composing the layer.
* @param subMesh the mesh to check for
* @param useInstances specify wether or not to use instances to render the mesh
* @param emissiveTexture the associated emissive texture used to generate the glow
* @return true if ready otherwise, false
*/
EffectLayer.prototype._isReady = function (subMesh, useInstances, emissiveTexture) {
var material = subMesh.getMaterial();
if (!material) {
return false;
}
if (!material.isReady(subMesh.getMesh(), useInstances)) {
return false;
}
var defines = [];
var attribs = [BABYLON.VertexBuffer.PositionKind];
var mesh = subMesh.getMesh();
var uv1 = false;
var uv2 = false;
// Alpha test
if (material && material.needAlphaTesting()) {
var alphaTexture = material.getAlphaTestTexture();
if (alphaTexture) {
defines.push("#define ALPHATEST");
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind) &&
alphaTexture.coordinatesIndex === 1) {
defines.push("#define DIFFUSEUV2");
uv2 = true;
}
else if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
defines.push("#define DIFFUSEUV1");
uv1 = true;
}
}
}
// Emissive
if (emissiveTexture) {
defines.push("#define EMISSIVE");
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind) &&
emissiveTexture.coordinatesIndex === 1) {
defines.push("#define EMISSIVEUV2");
uv2 = true;
}
else if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
defines.push("#define EMISSIVEUV1");
uv1 = true;
}
}
if (uv1) {
attribs.push(BABYLON.VertexBuffer.UVKind);
defines.push("#define UV1");
}
if (uv2) {
attribs.push(BABYLON.VertexBuffer.UV2Kind);
defines.push("#define UV2");
}
// Bones
if (mesh.useBones && mesh.computeBonesUsingShaders) {
attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
if (mesh.numBoneInfluencers > 4) {
attribs.push(BABYLON.VertexBuffer.MatricesIndicesExtraKind);
attribs.push(BABYLON.VertexBuffer.MatricesWeightsExtraKind);
}
defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
defines.push("#define BonesPerMesh " + (mesh.skeleton ? (mesh.skeleton.bones.length + 1) : 0));
}
else {
defines.push("#define NUM_BONE_INFLUENCERS 0");
}
// Morph targets
var manager = mesh.morphTargetManager;
var morphInfluencers = 0;
if (manager) {
if (manager.numInfluencers > 0) {
defines.push("#define MORPHTARGETS");
morphInfluencers = manager.numInfluencers;
defines.push("#define NUM_MORPH_INFLUENCERS " + morphInfluencers);
BABYLON.MaterialHelper.PrepareAttributesForMorphTargets(attribs, mesh, { "NUM_MORPH_INFLUENCERS": morphInfluencers });
}
}
// Instances
if (useInstances) {
defines.push("#define INSTANCES");
attribs.push("world0");
attribs.push("world1");
attribs.push("world2");
attribs.push("world3");
}
// Get correct effect
var join = defines.join("\n");
if (this._cachedDefines !== join) {
this._cachedDefines = join;
this._effectLayerMapGenerationEffect = this._scene.getEngine().createEffect("glowMapGeneration", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "color", "emissiveMatrix", "morphTargetInfluences"], ["diffuseSampler", "emissiveSampler"], join, undefined, undefined, undefined, { maxSimultaneousMorphTargets: morphInfluencers });
}
return this._effectLayerMapGenerationEffect.isReady();
};
/**
* Renders the glowing part of the scene by blending the blurred glowing meshes on top of the rendered scene.
*/
EffectLayer.prototype.render = function () {
var currentEffect = this._mergeEffect;
// Check
if (!currentEffect.isReady())
return;
for (var i = 0; i < this._postProcesses.length; i++) {
if (!this._postProcesses[i].isReady()) {
return;
}
}
var engine = this._scene.getEngine();
this.onBeforeComposeObservable.notifyObservers(this);
// Render
engine.enableEffect(currentEffect);
engine.setState(false);
// VBOs
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, currentEffect);
// Cache
var previousAlphaMode = engine.getAlphaMode();
// Go Blend.
engine.setAlphaMode(this._effectLayerOptions.alphaBlendingMode);
// Blends the map on the main canvas.
this._internalRender(currentEffect);
// Restore Alpha
engine.setAlphaMode(previousAlphaMode);
this.onAfterComposeObservable.notifyObservers(this);
// Handle size changes.
var size = this._mainTexture.getSize();
this._setMainTextureSize();
if (size.width !== this._mainTextureDesiredSize.width || size.height !== this._mainTextureDesiredSize.height) {
// Recreate RTT and post processes on size change.
this.onSizeChangedObservable.notifyObservers(this);
this._disposeTextureAndPostProcesses();
this._createMainTexture();
this._createTextureAndPostProcesses();
}
};
/**
* Determine if a given mesh will be used in the current effect.
* @param mesh mesh to test
* @returns true if the mesh will be used
*/
EffectLayer.prototype.hasMesh = function (mesh) {
return true;
};
/**
* Returns true if the layer contains information to display, otherwise false.
* @returns true if the glow layer should be rendered
*/
EffectLayer.prototype.shouldRender = function () {
return this.isEnabled && this._shouldRender;
};
/**
* Returns true if the mesh should render, otherwise false.
* @param mesh The mesh to render
* @returns true if it should render otherwise false
*/
EffectLayer.prototype._shouldRenderMesh = function (mesh) {
return true;
};
/**
* Returns true if the mesh should render, otherwise false.
* @param mesh The mesh to render
* @returns true if it should render otherwise false
*/
EffectLayer.prototype._shouldRenderEmissiveTextureForMesh = function (mesh) {
return true;
};
/**
* Renders the submesh passed in parameter to the generation map.
*/
EffectLayer.prototype._renderSubMesh = function (subMesh) {
var _this = this;
if (!this.shouldRender()) {
return;
}
var material = subMesh.getMaterial();
var mesh = subMesh.getRenderingMesh();
var scene = this._scene;
var engine = scene.getEngine();
if (!material) {
return;
}
// Do not block in blend mode.
if (material.needAlphaBlendingForMesh(mesh)) {
return;
}
// Culling
engine.setState(material.backFaceCulling);
// Managing instances
var batch = mesh._getInstancesRenderList(subMesh._id);
if (batch.mustReturn) {
return;
}
// Early Exit per mesh
if (!this._shouldRenderMesh(mesh)) {
return;
}
var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
this._setEmissiveTextureAndColor(mesh, subMesh, material);
if (this._isReady(subMesh, hardwareInstancedRendering, this._emissiveTextureAndColor.texture)) {
engine.enableEffect(this._effectLayerMapGenerationEffect);
mesh._bind(subMesh, this._effectLayerMapGenerationEffect, BABYLON.Material.TriangleFillMode);
this._effectLayerMapGenerationEffect.setMatrix("viewProjection", scene.getTransformMatrix());
this._effectLayerMapGenerationEffect.setFloat4("color", this._emissiveTextureAndColor.color.r, this._emissiveTextureAndColor.color.g, this._emissiveTextureAndColor.color.b, this._emissiveTextureAndColor.color.a);
// Alpha test
if (material && material.needAlphaTesting()) {
var alphaTexture = material.getAlphaTestTexture();
if (alphaTexture) {
this._effectLayerMapGenerationEffect.setTexture("diffuseSampler", alphaTexture);
var textureMatrix = alphaTexture.getTextureMatrix();
if (textureMatrix) {
this._effectLayerMapGenerationEffect.setMatrix("diffuseMatrix", textureMatrix);
}
}
}
// Glow emissive only
if (this._emissiveTextureAndColor.texture) {
this._effectLayerMapGenerationEffect.setTexture("emissiveSampler", this._emissiveTextureAndColor.texture);
this._effectLayerMapGenerationEffect.setMatrix("emissiveMatrix", this._emissiveTextureAndColor.texture.getTextureMatrix());
}
// Bones
if (mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
this._effectLayerMapGenerationEffect.setMatrices("mBones", mesh.skeleton.getTransformMatrices(mesh));
}
// Morph targets
BABYLON.MaterialHelper.BindMorphTargetParameters(mesh, this._effectLayerMapGenerationEffect);
// Draw
mesh._processRendering(subMesh, this._effectLayerMapGenerationEffect, BABYLON.Material.TriangleFillMode, batch, hardwareInstancedRendering, function (isInstance, world) { return _this._effectLayerMapGenerationEffect.setMatrix("world", world); });
}
else {
// Need to reset refresh rate of the shadowMap
this._mainTexture.resetRefreshCounter();
}
};
/**
* Rebuild the required buffers.
* @hidden Internal use only.
*/
EffectLayer.prototype._rebuild = function () {
var vb = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vb) {
vb._rebuild();
}
this._generateIndexBuffer();
};
/**
* Dispose only the render target textures and post process.
*/
EffectLayer.prototype._disposeTextureAndPostProcesses = function () {
this._mainTexture.dispose();
for (var i = 0; i < this._postProcesses.length; i++) {
if (this._postProcesses[i]) {
this._postProcesses[i].dispose();
}
}
this._postProcesses = [];
for (var i = 0; i < this._textures.length; i++) {
if (this._textures[i]) {
this._textures[i].dispose();
}
}
this._textures = [];
};
/**
* Dispose the highlight layer and free resources.
*/
EffectLayer.prototype.dispose = function () {
var vertexBuffer = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vertexBuffer) {
vertexBuffer.dispose();
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = null;
}
if (this._indexBuffer) {
this._scene.getEngine()._releaseBuffer(this._indexBuffer);
this._indexBuffer = null;
}
// Clean textures and post processes
this._disposeTextureAndPostProcesses();
// Remove from scene
var index = this._scene.effectLayers.indexOf(this, 0);
if (index > -1) {
this._scene.effectLayers.splice(index, 1);
}
// Callback
this.onDisposeObservable.notifyObservers(this);
this.onDisposeObservable.clear();
this.onBeforeRenderMainTextureObservable.clear();
this.onBeforeComposeObservable.clear();
this.onAfterComposeObservable.clear();
this.onSizeChangedObservable.clear();
};
/**
* Gets the class name of the effect layer
* @returns the string with the class name of the effect layer
*/
EffectLayer.prototype.getClassName = function () {
return "EffectLayer";
};
/**
* Creates an effect layer from parsed effect layer data
* @param parsedEffectLayer defines effect layer data
* @param scene defines the current scene
* @param rootUrl defines the root URL containing the effect layer information
* @returns a parsed effect Layer
*/
EffectLayer.Parse = function (parsedEffectLayer, scene, rootUrl) {
var effectLayerType = BABYLON.Tools.Instantiate(parsedEffectLayer.customType);
return effectLayerType.Parse(parsedEffectLayer, scene, rootUrl);
};
__decorate([
BABYLON.serialize()
], EffectLayer.prototype, "name", void 0);
__decorate([
BABYLON.serializeAsColor4()
], EffectLayer.prototype, "neutralColor", void 0);
__decorate([
BABYLON.serialize()
], EffectLayer.prototype, "isEnabled", void 0);
__decorate([
BABYLON.serializeAsCameraReference()
], EffectLayer.prototype, "camera", null);
return EffectLayer;
}());
BABYLON.EffectLayer = EffectLayer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.effectLayer.js.map
var BABYLON;
(function (BABYLON) {
/**
* Special Glow Blur post process only blurring the alpha channel
* It enforces keeping the most luminous color in the color channel.
*/
var GlowBlurPostProcess = /** @class */ (function (_super) {
__extends(GlowBlurPostProcess, _super);
function GlowBlurPostProcess(name, direction, kernel, options, camera, samplingMode, engine, reusable) {
if (samplingMode === void 0) { samplingMode = BABYLON.Texture.BILINEAR_SAMPLINGMODE; }
var _this = _super.call(this, name, "glowBlurPostProcess", ["screenSize", "direction", "blurWidth"], null, options, camera, samplingMode, engine, reusable) || this;
_this.direction = direction;
_this.kernel = kernel;
_this.onApplyObservable.add(function (effect) {
effect.setFloat2("screenSize", _this.width, _this.height);
effect.setVector2("direction", _this.direction);
effect.setFloat("blurWidth", _this.kernel);
});
return _this;
}
return GlowBlurPostProcess;
}(BABYLON.PostProcess));
/**
* The highlight layer Helps adding a glow effect around a mesh.
*
* Once instantiated in a scene, simply use the pushMesh or removeMesh method to add or remove
* glowy meshes to your scene.
*
* !!! THIS REQUIRES AN ACTIVE STENCIL BUFFER ON THE CANVAS !!!
*/
var HighlightLayer = /** @class */ (function (_super) {
__extends(HighlightLayer, _super);
/**
* Instantiates a new highlight Layer and references it to the scene..
* @param name The name of the layer
* @param scene The scene to use the layer in
* @param options Sets of none mandatory options to use with the layer (see IHighlightLayerOptions for more information)
*/
function HighlightLayer(name, scene, options) {
var _this = _super.call(this, name, scene) || this;
_this.name = name;
/**
* Specifies whether or not the inner glow is ACTIVE in the layer.
*/
_this.innerGlow = true;
/**
* Specifies whether or not the outer glow is ACTIVE in the layer.
*/
_this.outerGlow = true;
/**
* An event triggered when the highlight layer is being blurred.
*/
_this.onBeforeBlurObservable = new BABYLON.Observable();
/**
* An event triggered when the highlight layer has been blurred.
*/
_this.onAfterBlurObservable = new BABYLON.Observable();
_this._instanceGlowingMeshStencilReference = HighlightLayer.GlowingMeshStencilReference++;
_this._meshes = {};
_this._excludedMeshes = {};
_this.neutralColor = HighlightLayer.NeutralColor;
// Warn on stencil
if (!_this._engine.isStencilEnable) {
BABYLON.Tools.Warn("Rendering the Highlight Layer requires the stencil to be active on the canvas. var engine = new BABYLON.Engine(canvas, antialias, { stencil: true }");
}
// Adapt options
_this._options = __assign({ mainTextureRatio: 0.5, blurTextureSizeRatio: 0.5, blurHorizontalSize: 1.0, blurVerticalSize: 1.0, alphaBlendingMode: BABYLON.Engine.ALPHA_COMBINE, camera: null }, options);
// Initialize the layer
_this._init({
alphaBlendingMode: _this._options.alphaBlendingMode,
camera: _this._options.camera,
mainTextureFixedSize: _this._options.mainTextureFixedSize,
mainTextureRatio: _this._options.mainTextureRatio
});
// Do not render as long as no meshes have been added
_this._shouldRender = false;
return _this;
}
Object.defineProperty(HighlightLayer.prototype, "blurHorizontalSize", {
/**
* Gets the horizontal size of the blur.
*/
get: function () {
return this._horizontalBlurPostprocess.kernel;
},
/**
* Specifies the horizontal size of the blur.
*/
set: function (value) {
this._horizontalBlurPostprocess.kernel = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(HighlightLayer.prototype, "blurVerticalSize", {
/**
* Gets the vertical size of the blur.
*/
get: function () {
return this._verticalBlurPostprocess.kernel;
},
/**
* Specifies the vertical size of the blur.
*/
set: function (value) {
this._verticalBlurPostprocess.kernel = value;
},
enumerable: true,
configurable: true
});
/**
* Get the effect name of the layer.
* @return The effect name
*/
HighlightLayer.prototype.getEffectName = function () {
return HighlightLayer.EffectName;
};
/**
* Create the merge effect. This is the shader use to blit the information back
* to the main canvas at the end of the scene rendering.
*/
HighlightLayer.prototype._createMergeEffect = function () {
// Effect
return this._engine.createEffect("glowMapMerge", [BABYLON.VertexBuffer.PositionKind], ["offset"], ["textureSampler"], this._options.isStroke ? "#define STROKE \n" : undefined);
};
/**
* Creates the render target textures and post processes used in the highlight layer.
*/
HighlightLayer.prototype._createTextureAndPostProcesses = function () {
var _this = this;
var blurTextureWidth = this._mainTextureDesiredSize.width * this._options.blurTextureSizeRatio;
var blurTextureHeight = this._mainTextureDesiredSize.height * this._options.blurTextureSizeRatio;
blurTextureWidth = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(blurTextureWidth, this._maxSize) : blurTextureWidth;
blurTextureHeight = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(blurTextureHeight, this._maxSize) : blurTextureHeight;
this._blurTexture = new BABYLON.RenderTargetTexture("HighlightLayerBlurRTT", {
width: blurTextureWidth,
height: blurTextureHeight
}, this._scene, false, true, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._blurTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture.anisotropicFilteringLevel = 16;
this._blurTexture.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
this._blurTexture.renderParticles = false;
this._blurTexture.ignoreCameraViewport = true;
this._textures = [this._blurTexture];
if (this._options.alphaBlendingMode === BABYLON.Engine.ALPHA_COMBINE) {
this._downSamplePostprocess = new BABYLON.PassPostProcess("HighlightLayerPPP", this._options.blurTextureSizeRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
this._downSamplePostprocess.onApplyObservable.add(function (effect) {
effect.setTexture("textureSampler", _this._mainTexture);
});
this._horizontalBlurPostprocess = new GlowBlurPostProcess("HighlightLayerHBP", new BABYLON.Vector2(1.0, 0), this._options.blurHorizontalSize, 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
this._horizontalBlurPostprocess.onApplyObservable.add(function (effect) {
effect.setFloat2("screenSize", blurTextureWidth, blurTextureHeight);
});
this._verticalBlurPostprocess = new GlowBlurPostProcess("HighlightLayerVBP", new BABYLON.Vector2(0, 1.0), this._options.blurVerticalSize, 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
this._verticalBlurPostprocess.onApplyObservable.add(function (effect) {
effect.setFloat2("screenSize", blurTextureWidth, blurTextureHeight);
});
this._postProcesses = [this._downSamplePostprocess, this._horizontalBlurPostprocess, this._verticalBlurPostprocess];
}
else {
this._horizontalBlurPostprocess = new BABYLON.BlurPostProcess("HighlightLayerHBP", new BABYLON.Vector2(1.0, 0), this._options.blurHorizontalSize / 2, {
width: blurTextureWidth,
height: blurTextureHeight
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._horizontalBlurPostprocess.width = blurTextureWidth;
this._horizontalBlurPostprocess.height = blurTextureHeight;
this._horizontalBlurPostprocess.onApplyObservable.add(function (effect) {
effect.setTexture("textureSampler", _this._mainTexture);
});
this._verticalBlurPostprocess = new BABYLON.BlurPostProcess("HighlightLayerVBP", new BABYLON.Vector2(0, 1.0), this._options.blurVerticalSize / 2, {
width: blurTextureWidth,
height: blurTextureHeight
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._postProcesses = [this._horizontalBlurPostprocess, this._verticalBlurPostprocess];
}
this._mainTexture.onAfterUnbindObservable.add(function () {
_this.onBeforeBlurObservable.notifyObservers(_this);
var internalTexture = _this._blurTexture.getInternalTexture();
if (internalTexture) {
_this._scene.postProcessManager.directRender(_this._postProcesses, internalTexture, true);
}
_this.onAfterBlurObservable.notifyObservers(_this);
});
// Prevent autoClear.
this._postProcesses.map(function (pp) { pp.autoClear = false; });
};
/**
* Returns wether or nood the layer needs stencil enabled during the mesh rendering.
*/
HighlightLayer.prototype.needStencil = function () {
return true;
};
/**
* Checks for the readiness of the element composing the layer.
* @param subMesh the mesh to check for
* @param useInstances specify wether or not to use instances to render the mesh
* @param emissiveTexture the associated emissive texture used to generate the glow
* @return true if ready otherwise, false
*/
HighlightLayer.prototype.isReady = function (subMesh, useInstances) {
var material = subMesh.getMaterial();
var mesh = subMesh.getRenderingMesh();
if (!material || !mesh || !this._meshes) {
return false;
}
var emissiveTexture = null;
var highlightLayerMesh = this._meshes[mesh.uniqueId];
if (highlightLayerMesh && highlightLayerMesh.glowEmissiveOnly && material) {
emissiveTexture = material.emissiveTexture;
}
return _super.prototype._isReady.call(this, subMesh, useInstances, emissiveTexture);
};
/**
* Implementation specific of rendering the generating effect on the main canvas.
* @param effect The effect used to render through
*/
HighlightLayer.prototype._internalRender = function (effect) {
// Texture
effect.setTexture("textureSampler", this._blurTexture);
// Cache
var engine = this._engine;
var previousStencilBuffer = engine.getStencilBuffer();
var previousStencilFunction = engine.getStencilFunction();
var previousStencilMask = engine.getStencilMask();
var previousStencilOperationPass = engine.getStencilOperationPass();
var previousStencilOperationFail = engine.getStencilOperationFail();
var previousStencilOperationDepthFail = engine.getStencilOperationDepthFail();
var previousStencilReference = engine.getStencilFunctionReference();
// Stencil operations
engine.setStencilOperationPass(BABYLON.Engine.REPLACE);
engine.setStencilOperationFail(BABYLON.Engine.KEEP);
engine.setStencilOperationDepthFail(BABYLON.Engine.KEEP);
// Draw order
engine.setStencilMask(0x00);
engine.setStencilBuffer(true);
engine.setStencilFunctionReference(this._instanceGlowingMeshStencilReference);
// 2 passes inner outer
if (this.outerGlow) {
effect.setFloat("offset", 0);
engine.setStencilFunction(BABYLON.Engine.NOTEQUAL);
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
}
if (this.innerGlow) {
effect.setFloat("offset", 1);
engine.setStencilFunction(BABYLON.Engine.EQUAL);
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
}
// Restore Cache
engine.setStencilFunction(previousStencilFunction);
engine.setStencilMask(previousStencilMask);
engine.setStencilBuffer(previousStencilBuffer);
engine.setStencilOperationPass(previousStencilOperationPass);
engine.setStencilOperationFail(previousStencilOperationFail);
engine.setStencilOperationDepthFail(previousStencilOperationDepthFail);
engine.setStencilFunctionReference(previousStencilReference);
};
/**
* Returns true if the layer contains information to display, otherwise false.
*/
HighlightLayer.prototype.shouldRender = function () {
if (_super.prototype.shouldRender.call(this)) {
return this._meshes ? true : false;
}
return false;
};
/**
* Returns true if the mesh should render, otherwise false.
* @param mesh The mesh to render
* @returns true if it should render otherwise false
*/
HighlightLayer.prototype._shouldRenderMesh = function (mesh) {
// Excluded Mesh
if (this._excludedMeshes && this._excludedMeshes[mesh.uniqueId]) {
return false;
}
;
return true;
};
/**
* Sets the required values for both the emissive texture and and the main color.
*/
HighlightLayer.prototype._setEmissiveTextureAndColor = function (mesh, subMesh, material) {
var highlightLayerMesh = this._meshes[mesh.uniqueId];
if (highlightLayerMesh) {
this._emissiveTextureAndColor.color.set(highlightLayerMesh.color.r, highlightLayerMesh.color.g, highlightLayerMesh.color.b, 1.0);
}
else {
this._emissiveTextureAndColor.color.set(this.neutralColor.r, this.neutralColor.g, this.neutralColor.b, this.neutralColor.a);
}
if (highlightLayerMesh && highlightLayerMesh.glowEmissiveOnly && material) {
this._emissiveTextureAndColor.texture = material.emissiveTexture;
this._emissiveTextureAndColor.color.set(1.0, 1.0, 1.0, 1.0);
}
else {
this._emissiveTextureAndColor.texture = null;
}
};
/**
* Add a mesh in the exclusion list to prevent it to impact or being impacted by the highlight layer.
* @param mesh The mesh to exclude from the highlight layer
*/
HighlightLayer.prototype.addExcludedMesh = function (mesh) {
if (!this._excludedMeshes) {
return;
}
var meshExcluded = this._excludedMeshes[mesh.uniqueId];
if (!meshExcluded) {
this._excludedMeshes[mesh.uniqueId] = {
mesh: mesh,
beforeRender: mesh.onBeforeRenderObservable.add(function (mesh) {
mesh.getEngine().setStencilBuffer(false);
}),
afterRender: mesh.onAfterRenderObservable.add(function (mesh) {
mesh.getEngine().setStencilBuffer(true);
}),
};
}
};
/**
* Remove a mesh from the exclusion list to let it impact or being impacted by the highlight layer.
* @param mesh The mesh to highlight
*/
HighlightLayer.prototype.removeExcludedMesh = function (mesh) {
if (!this._excludedMeshes) {
return;
}
var meshExcluded = this._excludedMeshes[mesh.uniqueId];
if (meshExcluded) {
if (meshExcluded.beforeRender) {
mesh.onBeforeRenderObservable.remove(meshExcluded.beforeRender);
}
if (meshExcluded.afterRender) {
mesh.onAfterRenderObservable.remove(meshExcluded.afterRender);
}
}
this._excludedMeshes[mesh.uniqueId] = null;
};
/**
* Determine if a given mesh will be highlighted by the current HighlightLayer
* @param mesh mesh to test
* @returns true if the mesh will be highlighted by the current HighlightLayer
*/
HighlightLayer.prototype.hasMesh = function (mesh) {
if (!this._meshes) {
return false;
}
return this._meshes[mesh.uniqueId] !== undefined && this._meshes[mesh.uniqueId] !== null;
};
/**
* Add a mesh in the highlight layer in order to make it glow with the chosen color.
* @param mesh The mesh to highlight
* @param color The color of the highlight
* @param glowEmissiveOnly Extract the glow from the emissive texture
*/
HighlightLayer.prototype.addMesh = function (mesh, color, glowEmissiveOnly) {
var _this = this;
if (glowEmissiveOnly === void 0) { glowEmissiveOnly = false; }
if (!this._meshes) {
return;
}
var meshHighlight = this._meshes[mesh.uniqueId];
if (meshHighlight) {
meshHighlight.color = color;
}
else {
this._meshes[mesh.uniqueId] = {
mesh: mesh,
color: color,
// Lambda required for capture due to Observable this context
observerHighlight: mesh.onBeforeRenderObservable.add(function (mesh) {
if (_this._excludedMeshes && _this._excludedMeshes[mesh.uniqueId]) {
_this._defaultStencilReference(mesh);
}
else {
mesh.getScene().getEngine().setStencilFunctionReference(_this._instanceGlowingMeshStencilReference);
}
}),
observerDefault: mesh.onAfterRenderObservable.add(this._defaultStencilReference),
glowEmissiveOnly: glowEmissiveOnly
};
}
this._shouldRender = true;
};
/**
* Remove a mesh from the highlight layer in order to make it stop glowing.
* @param mesh The mesh to highlight
*/
HighlightLayer.prototype.removeMesh = function (mesh) {
if (!this._meshes) {
return;
}
var meshHighlight = this._meshes[mesh.uniqueId];
if (meshHighlight) {
if (meshHighlight.observerHighlight) {
mesh.onBeforeRenderObservable.remove(meshHighlight.observerHighlight);
}
if (meshHighlight.observerDefault) {
mesh.onAfterRenderObservable.remove(meshHighlight.observerDefault);
}
delete this._meshes[mesh.uniqueId];
}
this._shouldRender = false;
for (var meshHighlightToCheck in this._meshes) {
if (this._meshes[meshHighlightToCheck]) {
this._shouldRender = true;
break;
}
}
};
/**
* Force the stencil to the normal expected value for none glowing parts
*/
HighlightLayer.prototype._defaultStencilReference = function (mesh) {
mesh.getScene().getEngine().setStencilFunctionReference(HighlightLayer.NormalMeshStencilReference);
};
/**
* Free any resources and references associated to a mesh.
* Internal use
* @param mesh The mesh to free.
*/
HighlightLayer.prototype._disposeMesh = function (mesh) {
this.removeMesh(mesh);
this.removeExcludedMesh(mesh);
};
/**
* Dispose the highlight layer and free resources.
*/
HighlightLayer.prototype.dispose = function () {
if (this._meshes) {
// Clean mesh references
for (var id in this._meshes) {
var meshHighlight = this._meshes[id];
if (meshHighlight && meshHighlight.mesh) {
if (meshHighlight.observerHighlight) {
meshHighlight.mesh.onBeforeRenderObservable.remove(meshHighlight.observerHighlight);
}
if (meshHighlight.observerDefault) {
meshHighlight.mesh.onAfterRenderObservable.remove(meshHighlight.observerDefault);
}
}
}
this._meshes = null;
}
if (this._excludedMeshes) {
for (var id in this._excludedMeshes) {
var meshHighlight = this._excludedMeshes[id];
if (meshHighlight) {
if (meshHighlight.beforeRender) {
meshHighlight.mesh.onBeforeRenderObservable.remove(meshHighlight.beforeRender);
}
if (meshHighlight.afterRender) {
meshHighlight.mesh.onAfterRenderObservable.remove(meshHighlight.afterRender);
}
}
}
this._excludedMeshes = null;
}
_super.prototype.dispose.call(this);
};
/**
* Gets the class name of the effect layer
* @returns the string with the class name of the effect layer
*/
HighlightLayer.prototype.getClassName = function () {
return "HighlightLayer";
};
/**
* Serializes this Highlight layer
* @returns a serialized Highlight layer object
*/
HighlightLayer.prototype.serialize = function () {
var serializationObject = BABYLON.SerializationHelper.Serialize(this);
serializationObject.customType = "BABYLON.HighlightLayer";
// Highlighted meshes
serializationObject.meshes = [];
if (this._meshes) {
for (var m in this._meshes) {
var mesh = this._meshes[m];
if (mesh) {
serializationObject.meshes.push({
glowEmissiveOnly: mesh.glowEmissiveOnly,
color: mesh.color.asArray(),
meshId: mesh.mesh.id
});
}
}
}
// Excluded meshes
serializationObject.excludedMeshes = [];
if (this._excludedMeshes) {
for (var e in this._excludedMeshes) {
var excludedMesh = this._excludedMeshes[e];
if (excludedMesh) {
serializationObject.excludedMeshes.push(excludedMesh.mesh.id);
}
}
}
return serializationObject;
};
/**
* Creates a Highlight layer from parsed Highlight layer data
* @param parsedHightlightLayer defines the Highlight layer data
* @param scene defines the current scene
* @param rootUrl defines the root URL containing the Highlight layer information
* @returns a parsed Highlight layer
*/
HighlightLayer.Parse = function (parsedHightlightLayer, scene, rootUrl) {
var hl = BABYLON.SerializationHelper.Parse(function () { return new HighlightLayer(parsedHightlightLayer.name, scene, parsedHightlightLayer.options); }, parsedHightlightLayer, scene, rootUrl);
var index;
// Excluded meshes
for (index = 0; index < parsedHightlightLayer.excludedMeshes.length; index++) {
var mesh = scene.getMeshByID(parsedHightlightLayer.excludedMeshes[index]);
if (mesh) {
hl.addExcludedMesh(mesh);
}
}
// Included meshes
for (index = 0; index < parsedHightlightLayer.meshes.length; index++) {
var highlightedMesh = parsedHightlightLayer.meshes[index];
var mesh = scene.getMeshByID(highlightedMesh.meshId);
if (mesh) {
hl.addMesh(mesh, BABYLON.Color3.FromArray(highlightedMesh.color), highlightedMesh.glowEmissiveOnly);
}
}
return hl;
};
/**
* Effect Name of the highlight layer.
*/
HighlightLayer.EffectName = "HighlightLayer";
/**
* The neutral color used during the preparation of the glow effect.
* This is black by default as the blend operation is a blend operation.
*/
HighlightLayer.NeutralColor = new BABYLON.Color4(0, 0, 0, 0);
/**
* Stencil value used for glowing meshes.
*/
HighlightLayer.GlowingMeshStencilReference = 0x02;
/**
* Stencil value used for the other meshes in the scene.
*/
HighlightLayer.NormalMeshStencilReference = 0x01;
__decorate([
BABYLON.serialize()
], HighlightLayer.prototype, "innerGlow", void 0);
__decorate([
BABYLON.serialize()
], HighlightLayer.prototype, "outerGlow", void 0);
__decorate([
BABYLON.serialize()
], HighlightLayer.prototype, "blurHorizontalSize", null);
__decorate([
BABYLON.serialize()
], HighlightLayer.prototype, "blurVerticalSize", null);
__decorate([
BABYLON.serialize("options")
], HighlightLayer.prototype, "_options", void 0);
return HighlightLayer;
}(BABYLON.EffectLayer));
BABYLON.HighlightLayer = HighlightLayer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.highlightLayer.js.map
var BABYLON;
(function (BABYLON) {
/**
* The glow layer Helps adding a glow effect around the emissive parts of a mesh.
*
* Once instantiated in a scene, simply use the pushMesh or removeMesh method to add or remove
* glowy meshes to your scene.
*
* Documentation: https://doc.babylonjs.com/how_to/glow_layer
*/
var GlowLayer = /** @class */ (function (_super) {
__extends(GlowLayer, _super);
/**
* Instantiates a new glow Layer and references it to the scene.
* @param name The name of the layer
* @param scene The scene to use the layer in
* @param options Sets of none mandatory options to use with the layer (see IGlowLayerOptions for more information)
*/
function GlowLayer(name, scene, options) {
var _this = _super.call(this, name, scene) || this;
_this._intensity = 1.0;
_this._includedOnlyMeshes = [];
_this._excludedMeshes = [];
_this.neutralColor = new BABYLON.Color4(0, 0, 0, 1);
// Adapt options
_this._options = __assign({ mainTextureRatio: GlowLayer.DefaultTextureRatio, blurKernelSize: 32, mainTextureFixedSize: undefined, camera: null, mainTextureSamples: 1 }, options);
// Initialize the layer
_this._init({
alphaBlendingMode: BABYLON.Engine.ALPHA_ADD,
camera: _this._options.camera,
mainTextureFixedSize: _this._options.mainTextureFixedSize,
mainTextureRatio: _this._options.mainTextureRatio
});
return _this;
}
Object.defineProperty(GlowLayer.prototype, "blurKernelSize", {
/**
* Gets the kernel size of the blur.
*/
get: function () {
return this._horizontalBlurPostprocess1.kernel;
},
/**
* Sets the kernel size of the blur.
*/
set: function (value) {
this._horizontalBlurPostprocess1.kernel = value;
this._verticalBlurPostprocess1.kernel = value;
this._horizontalBlurPostprocess2.kernel = value;
this._verticalBlurPostprocess2.kernel = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GlowLayer.prototype, "intensity", {
/**
* Gets the glow intensity.
*/
get: function () {
return this._intensity;
},
/**
* Sets the glow intensity.
*/
set: function (value) {
this._intensity = value;
},
enumerable: true,
configurable: true
});
/**
* Get the effect name of the layer.
* @return The effect name
*/
GlowLayer.prototype.getEffectName = function () {
return GlowLayer.EffectName;
};
/**
* Create the merge effect. This is the shader use to blit the information back
* to the main canvas at the end of the scene rendering.
*/
GlowLayer.prototype._createMergeEffect = function () {
// Effect
return this._engine.createEffect("glowMapMerge", [BABYLON.VertexBuffer.PositionKind], ["offset"], ["textureSampler", "textureSampler2"], "#define EMISSIVE \n");
};
/**
* Creates the render target textures and post processes used in the glow layer.
*/
GlowLayer.prototype._createTextureAndPostProcesses = function () {
var _this = this;
var blurTextureWidth = this._mainTextureDesiredSize.width;
var blurTextureHeight = this._mainTextureDesiredSize.height;
blurTextureWidth = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(blurTextureWidth, this._maxSize) : blurTextureWidth;
blurTextureHeight = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(blurTextureHeight, this._maxSize) : blurTextureHeight;
var textureType = 0;
if (this._engine.getCaps().textureHalfFloatRender) {
textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
}
else {
textureType = BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
}
this._blurTexture1 = new BABYLON.RenderTargetTexture("GlowLayerBlurRTT", {
width: blurTextureWidth,
height: blurTextureHeight
}, this._scene, false, true, textureType);
this._blurTexture1.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture1.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture1.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE);
this._blurTexture1.renderParticles = false;
this._blurTexture1.ignoreCameraViewport = true;
var blurTextureWidth2 = Math.floor(blurTextureWidth / 2);
var blurTextureHeight2 = Math.floor(blurTextureHeight / 2);
this._blurTexture2 = new BABYLON.RenderTargetTexture("GlowLayerBlurRTT2", {
width: blurTextureWidth2,
height: blurTextureHeight2
}, this._scene, false, true, textureType);
this._blurTexture2.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture2.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture2.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE);
this._blurTexture2.renderParticles = false;
this._blurTexture2.ignoreCameraViewport = true;
this._textures = [this._blurTexture1, this._blurTexture2];
this._horizontalBlurPostprocess1 = new BABYLON.BlurPostProcess("GlowLayerHBP1", new BABYLON.Vector2(1.0, 0), this._options.blurKernelSize / 2, {
width: blurTextureWidth,
height: blurTextureHeight
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
this._horizontalBlurPostprocess1.width = blurTextureWidth;
this._horizontalBlurPostprocess1.height = blurTextureHeight;
this._horizontalBlurPostprocess1.onApplyObservable.add(function (effect) {
effect.setTexture("textureSampler", _this._mainTexture);
});
this._verticalBlurPostprocess1 = new BABYLON.BlurPostProcess("GlowLayerVBP1", new BABYLON.Vector2(0, 1.0), this._options.blurKernelSize / 2, {
width: blurTextureWidth,
height: blurTextureHeight
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
this._horizontalBlurPostprocess2 = new BABYLON.BlurPostProcess("GlowLayerHBP2", new BABYLON.Vector2(1.0, 0), this._options.blurKernelSize / 2, {
width: blurTextureWidth2,
height: blurTextureHeight2
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
this._horizontalBlurPostprocess2.width = blurTextureWidth2;
this._horizontalBlurPostprocess2.height = blurTextureHeight2;
this._horizontalBlurPostprocess2.onApplyObservable.add(function (effect) {
effect.setTexture("textureSampler", _this._blurTexture1);
});
this._verticalBlurPostprocess2 = new BABYLON.BlurPostProcess("GlowLayerVBP2", new BABYLON.Vector2(0, 1.0), this._options.blurKernelSize / 2, {
width: blurTextureWidth2,
height: blurTextureHeight2
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
this._postProcesses = [this._horizontalBlurPostprocess1, this._verticalBlurPostprocess1, this._horizontalBlurPostprocess2, this._verticalBlurPostprocess2];
this._postProcesses1 = [this._horizontalBlurPostprocess1, this._verticalBlurPostprocess1];
this._postProcesses2 = [this._horizontalBlurPostprocess2, this._verticalBlurPostprocess2];
this._mainTexture.samples = this._options.mainTextureSamples;
this._mainTexture.onAfterUnbindObservable.add(function () {
var internalTexture = _this._blurTexture1.getInternalTexture();
if (internalTexture) {
_this._scene.postProcessManager.directRender(_this._postProcesses1, internalTexture, true);
internalTexture = _this._blurTexture2.getInternalTexture();
if (internalTexture) {
_this._scene.postProcessManager.directRender(_this._postProcesses2, internalTexture, true);
}
}
});
// Prevent autoClear.
this._postProcesses.map(function (pp) { pp.autoClear = false; });
};
/**
* Checks for the readiness of the element composing the layer.
* @param subMesh the mesh to check for
* @param useInstances specify wether or not to use instances to render the mesh
* @param emissiveTexture the associated emissive texture used to generate the glow
* @return true if ready otherwise, false
*/
GlowLayer.prototype.isReady = function (subMesh, useInstances) {
var material = subMesh.getMaterial();
var mesh = subMesh.getRenderingMesh();
if (!material || !mesh) {
return false;
}
var emissiveTexture = material.emissiveTexture;
return _super.prototype._isReady.call(this, subMesh, useInstances, emissiveTexture);
};
/**
* Returns wether or nood the layer needs stencil enabled during the mesh rendering.
*/
GlowLayer.prototype.needStencil = function () {
return false;
};
/**
* Implementation specific of rendering the generating effect on the main canvas.
* @param effect The effect used to render through
*/
GlowLayer.prototype._internalRender = function (effect) {
// Texture
effect.setTexture("textureSampler", this._blurTexture1);
effect.setTexture("textureSampler2", this._blurTexture2);
effect.setFloat("offset", this._intensity);
// Cache
var engine = this._engine;
var previousStencilBuffer = engine.getStencilBuffer();
// Draw order
engine.setStencilBuffer(false);
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
// Draw order
engine.setStencilBuffer(previousStencilBuffer);
};
/**
* Sets the required values for both the emissive texture and and the main color.
*/
GlowLayer.prototype._setEmissiveTextureAndColor = function (mesh, subMesh, material) {
var textureLevel = 1.0;
if (this.customEmissiveTextureSelector) {
this._emissiveTextureAndColor.texture = this.customEmissiveTextureSelector(mesh, subMesh, material);
}
else {
if (material) {
this._emissiveTextureAndColor.texture = material.emissiveTexture;
if (this._emissiveTextureAndColor.texture) {
textureLevel = this._emissiveTextureAndColor.texture.level;
}
}
else {
this._emissiveTextureAndColor.texture = null;
}
}
if (this.customEmissiveColorSelector) {
this.customEmissiveColorSelector(mesh, subMesh, material, this._emissiveTextureAndColor.color);
}
else {
if (material.emissiveColor) {
this._emissiveTextureAndColor.color.set(material.emissiveColor.r * textureLevel, material.emissiveColor.g * textureLevel, material.emissiveColor.b * textureLevel, 1.0);
}
else {
this._emissiveTextureAndColor.color.set(this.neutralColor.r, this.neutralColor.g, this.neutralColor.b, this.neutralColor.a);
}
}
};
/**
* Returns true if the mesh should render, otherwise false.
* @param mesh The mesh to render
* @returns true if it should render otherwise false
*/
GlowLayer.prototype._shouldRenderMesh = function (mesh) {
return this.hasMesh(mesh);
};
/**
* Add a mesh in the exclusion list to prevent it to impact or being impacted by the glow layer.
* @param mesh The mesh to exclude from the glow layer
*/
GlowLayer.prototype.addExcludedMesh = function (mesh) {
if (this._excludedMeshes.indexOf(mesh.uniqueId) === -1) {
this._excludedMeshes.push(mesh.uniqueId);
}
};
/**
* Remove a mesh from the exclusion list to let it impact or being impacted by the glow layer.
* @param mesh The mesh to remove
*/
GlowLayer.prototype.removeExcludedMesh = function (mesh) {
var index = this._excludedMeshes.indexOf(mesh.uniqueId);
if (index !== -1) {
this._excludedMeshes.splice(index, 1);
}
};
/**
* Add a mesh in the inclusion list to impact or being impacted by the glow layer.
* @param mesh The mesh to include in the glow layer
*/
GlowLayer.prototype.addIncludedOnlyMesh = function (mesh) {
if (this._includedOnlyMeshes.indexOf(mesh.uniqueId) === -1) {
this._includedOnlyMeshes.push(mesh.uniqueId);
}
};
/**
* Remove a mesh from the Inclusion list to prevent it to impact or being impacted by the glow layer.
* @param mesh The mesh to remove
*/
GlowLayer.prototype.removeIncludedOnlyMesh = function (mesh) {
var index = this._includedOnlyMeshes.indexOf(mesh.uniqueId);
if (index !== -1) {
this._includedOnlyMeshes.splice(index, 1);
}
};
/**
* Determine if a given mesh will be used in the glow layer
* @param mesh The mesh to test
* @returns true if the mesh will be highlighted by the current glow layer
*/
GlowLayer.prototype.hasMesh = function (mesh) {
// Included Mesh
if (this._includedOnlyMeshes.length) {
return this._includedOnlyMeshes.indexOf(mesh.uniqueId) !== -1;
}
;
// Excluded Mesh
if (this._excludedMeshes.length) {
return this._excludedMeshes.indexOf(mesh.uniqueId) === -1;
}
;
return true;
};
/**
* Free any resources and references associated to a mesh.
* Internal use
* @param mesh The mesh to free.
*/
GlowLayer.prototype._disposeMesh = function (mesh) {
this.removeIncludedOnlyMesh(mesh);
this.removeExcludedMesh(mesh);
};
/**
* Gets the class name of the effect layer
* @returns the string with the class name of the effect layer
*/
GlowLayer.prototype.getClassName = function () {
return "GlowLayer";
};
/**
* Serializes this glow layer
* @returns a serialized glow layer object
*/
GlowLayer.prototype.serialize = function () {
var serializationObject = BABYLON.SerializationHelper.Serialize(this);
serializationObject.customType = "BABYLON.GlowLayer";
var index;
// Included meshes
serializationObject.includedMeshes = [];
if (this._includedOnlyMeshes.length) {
for (index = 0; index < this._includedOnlyMeshes.length; index++) {
var mesh = this._scene.getMeshByUniqueID(this._includedOnlyMeshes[index]);
if (mesh) {
serializationObject.includedMeshes.push(mesh.id);
}
}
}
// Excluded meshes
serializationObject.excludedMeshes = [];
if (this._excludedMeshes.length) {
for (index = 0; index < this._excludedMeshes.length; index++) {
var mesh = this._scene.getMeshByUniqueID(this._excludedMeshes[index]);
if (mesh) {
serializationObject.excludedMeshes.push(mesh.id);
}
}
}
return serializationObject;
};
/**
* Creates a Glow Layer from parsed glow layer data
* @param parsedGlowLayer defines glow layer data
* @param scene defines the current scene
* @param rootUrl defines the root URL containing the glow layer information
* @returns a parsed Glow Layer
*/
GlowLayer.Parse = function (parsedGlowLayer, scene, rootUrl) {
var gl = BABYLON.SerializationHelper.Parse(function () { return new GlowLayer(parsedGlowLayer.name, scene, parsedGlowLayer.options); }, parsedGlowLayer, scene, rootUrl);
var index;
// Excluded meshes
for (index = 0; index < parsedGlowLayer.excludedMeshes.length; index++) {
var mesh = scene.getMeshByID(parsedGlowLayer.excludedMeshes[index]);
if (mesh) {
gl.addExcludedMesh(mesh);
}
}
// Included meshes
for (index = 0; index < parsedGlowLayer.includedMeshes.length; index++) {
var mesh = scene.getMeshByID(parsedGlowLayer.includedMeshes[index]);
if (mesh) {
gl.addIncludedOnlyMesh(mesh);
}
}
return gl;
};
/**
* Effect Name of the layer.
*/
GlowLayer.EffectName = "GlowLayer";
/**
* The default blur kernel size used for the glow.
*/
GlowLayer.DefaultBlurKernelSize = 32;
/**
* The default texture size ratio used for the glow.
*/
GlowLayer.DefaultTextureRatio = 0.5;
__decorate([
BABYLON.serialize()
], GlowLayer.prototype, "blurKernelSize", null);
__decorate([
BABYLON.serialize()
], GlowLayer.prototype, "intensity", null);
__decorate([
BABYLON.serialize("options")
], GlowLayer.prototype, "_options", void 0);
return GlowLayer;
}(BABYLON.EffectLayer));
BABYLON.GlowLayer = GlowLayer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glowLayer.js.map
var BABYLON;
(function (BABYLON) {
/**
* Defines the list of states available for a task inside a {BABYLON.AssetsManager}
*/
var AssetTaskState;
(function (AssetTaskState) {
/**
* Initialization
*/
AssetTaskState[AssetTaskState["INIT"] = 0] = "INIT";
/**
* Running
*/
AssetTaskState[AssetTaskState["RUNNING"] = 1] = "RUNNING";
/**
* Done
*/
AssetTaskState[AssetTaskState["DONE"] = 2] = "DONE";
/**
* Error
*/
AssetTaskState[AssetTaskState["ERROR"] = 3] = "ERROR";
})(AssetTaskState = BABYLON.AssetTaskState || (BABYLON.AssetTaskState = {}));
/**
* Define an abstract asset task used with a {BABYLON.AssetsManager} class to load assets into a scene
*/
var AbstractAssetTask = /** @class */ (function () {
/**
* Creates a new {BABYLON.AssetsManager}
* @param name defines the name of the task
*/
function AbstractAssetTask(
/**
* Task name
*/ name) {
this.name = name;
this._isCompleted = false;
this._taskState = AssetTaskState.INIT;
}
Object.defineProperty(AbstractAssetTask.prototype, "isCompleted", {
/**
* Get if the task is completed
*/
get: function () {
return this._isCompleted;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractAssetTask.prototype, "taskState", {
/**
* Gets the current state of the task
*/
get: function () {
return this._taskState;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractAssetTask.prototype, "errorObject", {
/**
* Gets the current error object (if task is in error)
*/
get: function () {
return this._errorObject;
},
enumerable: true,
configurable: true
});
/**
* Internal only
* @hidden
*/
AbstractAssetTask.prototype._setErrorObject = function (message, exception) {
if (this._errorObject) {
return;
}
this._errorObject = {
message: message,
exception: exception
};
};
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
AbstractAssetTask.prototype.run = function (scene, onSuccess, onError) {
var _this = this;
this._taskState = AssetTaskState.RUNNING;
this.runTask(scene, function () {
_this.onDoneCallback(onSuccess, onError);
}, function (msg, exception) {
_this.onErrorCallback(onError, msg, exception);
});
};
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
AbstractAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
throw new Error("runTask is not implemented");
};
AbstractAssetTask.prototype.onErrorCallback = function (onError, message, exception) {
this._taskState = AssetTaskState.ERROR;
this._errorObject = {
message: message,
exception: exception
};
if (this.onError) {
this.onError(this, message, exception);
}
onError();
};
AbstractAssetTask.prototype.onDoneCallback = function (onSuccess, onError) {
try {
this._taskState = AssetTaskState.DONE;
this._isCompleted = true;
if (this.onSuccess) {
this.onSuccess(this);
}
onSuccess();
}
catch (e) {
this.onErrorCallback(onError, "Task is done, error executing success callback(s)", e);
}
};
return AbstractAssetTask;
}());
BABYLON.AbstractAssetTask = AbstractAssetTask;
/**
* Class used to share progress information about assets loading
*/
var AssetsProgressEvent = /** @class */ (function () {
/**
* Creates a {BABYLON.AssetsProgressEvent}
* @param remainingCount defines the number of remaining tasks to process
* @param totalCount defines the total number of tasks
* @param task defines the task that was just processed
*/
function AssetsProgressEvent(remainingCount, totalCount, task) {
this.remainingCount = remainingCount;
this.totalCount = totalCount;
this.task = task;
}
return AssetsProgressEvent;
}());
BABYLON.AssetsProgressEvent = AssetsProgressEvent;
/**
* Define a task used by {BABYLON.AssetsManager} to load meshes
*/
var MeshAssetTask = /** @class */ (function (_super) {
__extends(MeshAssetTask, _super);
/**
* Creates a new {BABYLON.MeshAssetTask}
* @param name defines the name of the task
* @param meshesNames defines the list of mesh's names you want to load
* @param rootUrl defines the root url to use as a base to load your meshes and associated resources
* @param sceneFilename defines the filename of the scene to load from
*/
function MeshAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the list of mesh's names you want to load
*/
meshesNames,
/**
* Defines the root url to use as a base to load your meshes and associated resources
*/
rootUrl,
/**
* Defines the filename of the scene to load from
*/
sceneFilename) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.meshesNames = meshesNames;
_this.rootUrl = rootUrl;
_this.sceneFilename = sceneFilename;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
MeshAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var _this = this;
BABYLON.SceneLoader.ImportMesh(this.meshesNames, this.rootUrl, this.sceneFilename, scene, function (meshes, particleSystems, skeletons) {
_this.loadedMeshes = meshes;
_this.loadedParticleSystems = particleSystems;
_this.loadedSkeletons = skeletons;
onSuccess();
}, null, function (scene, message, exception) {
onError(message, exception);
});
};
return MeshAssetTask;
}(AbstractAssetTask));
BABYLON.MeshAssetTask = MeshAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load text content
*/
var TextFileAssetTask = /** @class */ (function (_super) {
__extends(TextFileAssetTask, _super);
/**
* Creates a new TextFileAssetTask object
* @param name defines the name of the task
* @param url defines the location of the file to load
*/
function TextFileAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the file to load
*/
url) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
TextFileAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var _this = this;
scene._loadFile(this.url, function (data) {
_this.text = data;
onSuccess();
}, undefined, false, false, function (request, exception) {
if (request) {
onError(request.status + " " + request.statusText, exception);
}
});
};
return TextFileAssetTask;
}(AbstractAssetTask));
BABYLON.TextFileAssetTask = TextFileAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load binary data
*/
var BinaryFileAssetTask = /** @class */ (function (_super) {
__extends(BinaryFileAssetTask, _super);
/**
* Creates a new BinaryFileAssetTask object
* @param name defines the name of the new task
* @param url defines the location of the file to load
*/
function BinaryFileAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the file to load
*/
url) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
BinaryFileAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var _this = this;
scene._loadFile(this.url, function (data) {
_this.data = data;
onSuccess();
}, undefined, true, true, function (request, exception) {
if (request) {
onError(request.status + " " + request.statusText, exception);
}
});
};
return BinaryFileAssetTask;
}(AbstractAssetTask));
BABYLON.BinaryFileAssetTask = BinaryFileAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load images
*/
var ImageAssetTask = /** @class */ (function (_super) {
__extends(ImageAssetTask, _super);
/**
* Creates a new ImageAssetTask
* @param name defines the name of the task
* @param url defines the location of the image to load
*/
function ImageAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the image to load
*/
url) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
ImageAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var _this = this;
var img = new Image();
BABYLON.Tools.SetCorsBehavior(this.url, img);
img.onload = function () {
_this.image = img;
onSuccess();
};
img.onerror = function (err) {
onError("Error loading image", err);
};
img.src = this.url;
};
return ImageAssetTask;
}(AbstractAssetTask));
BABYLON.ImageAssetTask = ImageAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load 2D textures
*/
var TextureAssetTask = /** @class */ (function (_super) {
__extends(TextureAssetTask, _super);
/**
* Creates a new TextureAssetTask object
* @param name defines the name of the task
* @param url defines the location of the file to load
* @param noMipmap defines if mipmap should not be generated (default is false)
* @param invertY defines if texture must be inverted on Y axis (default is false)
* @param samplingMode defines the sampling mode to use (default is BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
*/
function TextureAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the file to load
*/
url,
/**
* Defines if mipmap should not be generated (default is false)
*/
noMipmap,
/**
* Defines if texture must be inverted on Y axis (default is false)
*/
invertY,
/**
* Defines the sampling mode to use (default is BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
*/
samplingMode) {
if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
_this.noMipmap = noMipmap;
_this.invertY = invertY;
_this.samplingMode = samplingMode;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
TextureAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var onload = function () {
onSuccess();
};
var onerror = function (message, exception) {
onError(message, exception);
};
this.texture = new BABYLON.Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onerror);
};
return TextureAssetTask;
}(AbstractAssetTask));
BABYLON.TextureAssetTask = TextureAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load cube textures
*/
var CubeTextureAssetTask = /** @class */ (function (_super) {
__extends(CubeTextureAssetTask, _super);
/**
* Creates a new CubeTextureAssetTask
* @param name defines the name of the task
* @param url defines the location of the files to load (You have to specify the folder where the files are + filename with no extension)
* @param extensions defines the extensions to use to load files (["_px", "_py", "_pz", "_nx", "_ny", "_nz"] by default)
* @param noMipmap defines if mipmaps should not be generated (default is false)
* @param files defines the explicit list of files (undefined by default)
*/
function CubeTextureAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the files to load (You have to specify the folder where the files are + filename with no extension)
*/
url,
/**
* Defines the extensions to use to load files (["_px", "_py", "_pz", "_nx", "_ny", "_nz"] by default)
*/
extensions,
/**
* Defines if mipmaps should not be generated (default is false)
*/
noMipmap,
/**
* Defines the explicit list of files (undefined by default)
*/
files) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
_this.extensions = extensions;
_this.noMipmap = noMipmap;
_this.files = files;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
CubeTextureAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var onload = function () {
onSuccess();
};
var onerror = function (message, exception) {
onError(message, exception);
};
this.texture = new BABYLON.CubeTexture(this.url, scene, this.extensions, this.noMipmap, this.files, onload, onerror);
};
return CubeTextureAssetTask;
}(AbstractAssetTask));
BABYLON.CubeTextureAssetTask = CubeTextureAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load HDR cube textures
*/
var HDRCubeTextureAssetTask = /** @class */ (function (_super) {
__extends(HDRCubeTextureAssetTask, _super);
/**
* Creates a new HDRCubeTextureAssetTask object
* @param name defines the name of the task
* @param url defines the location of the file to load
* @param size defines the desired size (the more it increases the longer the generation will be) If the size is omitted this implies you are using a preprocessed cubemap.
* @param noMipmap defines if mipmaps should not be generated (default is false)
* @param generateHarmonics specifies whether you want to extract the polynomial harmonics during the generation process (default is true)
* @param gammaSpace specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
* @param reserved Internal use only
*/
function HDRCubeTextureAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the file to load
*/
url,
/**
* Defines the desired size (the more it increases the longer the generation will be)
*/
size,
/**
* Defines if mipmaps should not be generated (default is false)
*/
noMipmap,
/**
* Specifies whether you want to extract the polynomial harmonics during the generation process (default is true)
*/
generateHarmonics,
/**
* Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
*/
gammaSpace,
/**
* Internal Use Only
*/
reserved) {
if (noMipmap === void 0) { noMipmap = false; }
if (generateHarmonics === void 0) { generateHarmonics = true; }
if (gammaSpace === void 0) { gammaSpace = false; }
if (reserved === void 0) { reserved = false; }
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
_this.size = size;
_this.noMipmap = noMipmap;
_this.generateHarmonics = generateHarmonics;
_this.gammaSpace = gammaSpace;
_this.reserved = reserved;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
HDRCubeTextureAssetTask.prototype.run = function (scene, onSuccess, onError) {
var onload = function () {
onSuccess();
};
var onerror = function (message, exception) {
onError(message, exception);
};
this.texture = new BABYLON.HDRCubeTexture(this.url, scene, this.size, this.noMipmap, this.generateHarmonics, this.gammaSpace, this.reserved, onload, onerror);
};
return HDRCubeTextureAssetTask;
}(AbstractAssetTask));
BABYLON.HDRCubeTextureAssetTask = HDRCubeTextureAssetTask;
/**
* This class can be used to easily import assets into a scene
* @see http://doc.babylonjs.com/how_to/how_to_use_assetsmanager
*/
var AssetsManager = /** @class */ (function () {
/**
* Creates a new AssetsManager
* @param scene defines the scene to work on
*/
function AssetsManager(scene) {
this._isLoading = false;
this._tasks = new Array();
this._waitingTasksCount = 0;
this._totalTasksCount = 0;
/**
* Observable called when all tasks are processed
*/
this.onTaskSuccessObservable = new BABYLON.Observable();
/**
* Observable called when a task had an error
*/
this.onTaskErrorObservable = new BABYLON.Observable();
/**
* Observable called when a task is successful
*/
this.onTasksDoneObservable = new BABYLON.Observable();
/**
* Observable called when a task is done (whatever the result is)
*/
this.onProgressObservable = new BABYLON.Observable();
/**
* Gets or sets a boolean defining if the {BABYLON.AssetsManager} should use the default loading screen
* @see http://doc.babylonjs.com/how_to/creating_a_custom_loading_screen
*/
this.useDefaultLoadingScreen = true;
this._scene = scene;
}
/**
* Add a {BABYLON.MeshAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param meshesNames defines the name of meshes to load
* @param rootUrl defines the root url to use to locate files
* @param sceneFilename defines the filename of the scene file
* @returns a new {BABYLON.MeshAssetTask} object
*/
AssetsManager.prototype.addMeshTask = function (taskName, meshesNames, rootUrl, sceneFilename) {
var task = new MeshAssetTask(taskName, meshesNames, rootUrl, sceneFilename);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.TextFileAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @returns a new {BABYLON.TextFileAssetTask} object
*/
AssetsManager.prototype.addTextFileTask = function (taskName, url) {
var task = new TextFileAssetTask(taskName, url);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.BinaryFileAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @returns a new {BABYLON.BinaryFileAssetTask} object
*/
AssetsManager.prototype.addBinaryFileTask = function (taskName, url) {
var task = new BinaryFileAssetTask(taskName, url);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.ImageAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @returns a new {BABYLON.ImageAssetTask} object
*/
AssetsManager.prototype.addImageTask = function (taskName, url) {
var task = new ImageAssetTask(taskName, url);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.TextureAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @param noMipmap defines if the texture must not receive mipmaps (false by default)
* @param invertY defines if you want to invert Y axis of the loaded texture (false by default)
* @param samplingMode defines the sampling mode to use (BABYLON.Texture.TRILINEAR_SAMPLINGMODE by default)
* @returns a new {BABYLON.TextureAssetTask} object
*/
AssetsManager.prototype.addTextureTask = function (taskName, url, noMipmap, invertY, samplingMode) {
if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
var task = new TextureAssetTask(taskName, url, noMipmap, invertY, samplingMode);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.CubeTextureAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @param extensions defines the extension to use to load the cube map (can be null)
* @param noMipmap defines if the texture must not receive mipmaps (false by default)
* @param files defines the list of files to load (can be null)
* @returns a new {BABYLON.CubeTextureAssetTask} object
*/
AssetsManager.prototype.addCubeTextureTask = function (taskName, url, extensions, noMipmap, files) {
var task = new CubeTextureAssetTask(taskName, url, extensions, noMipmap, files);
this._tasks.push(task);
return task;
};
/**
*
* Add a {BABYLON.HDRCubeTextureAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @param size defines the size you want for the cubemap (can be null)
* @param noMipmap defines if the texture must not receive mipmaps (false by default)
* @param generateHarmonics defines if you want to automatically generate (true by default)
* @param gammaSpace specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
* @param reserved Internal use only
* @returns a new {BABYLON.HDRCubeTextureAssetTask} object
*/
AssetsManager.prototype.addHDRCubeTextureTask = function (taskName, url, size, noMipmap, generateHarmonics, gammaSpace, reserved) {
if (noMipmap === void 0) { noMipmap = false; }
if (generateHarmonics === void 0) { generateHarmonics = true; }
if (gammaSpace === void 0) { gammaSpace = false; }
if (reserved === void 0) { reserved = false; }
var task = new HDRCubeTextureAssetTask(taskName, url, size, noMipmap, generateHarmonics, gammaSpace, reserved);
this._tasks.push(task);
return task;
};
AssetsManager.prototype._decreaseWaitingTasksCount = function (task) {
var _this = this;
this._waitingTasksCount--;
try {
if (task.taskState === AssetTaskState.DONE) {
// Let's remove successfull tasks
BABYLON.Tools.SetImmediate(function () {
var index = _this._tasks.indexOf(task);
if (index > -1) {
_this._tasks.splice(index, 1);
}
});
}
if (this.onProgress) {
this.onProgress(this._waitingTasksCount, this._totalTasksCount, task);
}
this.onProgressObservable.notifyObservers(new AssetsProgressEvent(this._waitingTasksCount, this._totalTasksCount, task));
}
catch (e) {
BABYLON.Tools.Error("Error running progress callbacks.");
console.log(e);
}
if (this._waitingTasksCount === 0) {
try {
if (this.onFinish) {
this.onFinish(this._tasks);
}
this.onTasksDoneObservable.notifyObservers(this._tasks);
}
catch (e) {
BABYLON.Tools.Error("Error running tasks-done callbacks.");
console.log(e);
}
this._isLoading = false;
this._scene.getEngine().hideLoadingUI();
}
};
AssetsManager.prototype._runTask = function (task) {
var _this = this;
var done = function () {
try {
if (_this.onTaskSuccess) {
_this.onTaskSuccess(task);
}
_this.onTaskSuccessObservable.notifyObservers(task);
_this._decreaseWaitingTasksCount(task);
}
catch (e) {
error("Error executing task success callbacks", e);
}
};
var error = function (message, exception) {
task._setErrorObject(message, exception);
if (_this.onTaskError) {
_this.onTaskError(task);
}
_this.onTaskErrorObservable.notifyObservers(task);
_this._decreaseWaitingTasksCount(task);
};
task.run(this._scene, done, error);
};
/**
* Reset the {BABYLON.AssetsManager} and remove all tasks
* @return the current instance of the {BABYLON.AssetsManager}
*/
AssetsManager.prototype.reset = function () {
this._isLoading = false;
this._tasks = new Array();
return this;
};
/**
* Start the loading process
* @return the current instance of the {BABYLON.AssetsManager}
*/
AssetsManager.prototype.load = function () {
if (this._isLoading) {
return this;
}
this._isLoading = true;
this._waitingTasksCount = this._tasks.length;
this._totalTasksCount = this._tasks.length;
if (this._waitingTasksCount === 0) {
this._isLoading = false;
if (this.onFinish) {
this.onFinish(this._tasks);
}
this.onTasksDoneObservable.notifyObservers(this._tasks);
return this;
}
if (this.useDefaultLoadingScreen) {
this._scene.getEngine().displayLoadingUI();
}
for (var index = 0; index < this._tasks.length; index++) {
var task = this._tasks[index];
this._runTask(task);
}
return this;
};
return AssetsManager;
}());
BABYLON.AssetsManager = AssetsManager;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.assetsManager.js.map
var BABYLON;
(function (BABYLON) {
var serializedGeometries = [];
var serializeGeometry = function (geometry, serializationGeometries) {
if (serializedGeometries[geometry.id]) {
return;
}
if (geometry.doNotSerialize) {
return;
}
if (geometry instanceof BABYLON.BoxGeometry) {
serializationGeometries.boxes.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.SphereGeometry) {
serializationGeometries.spheres.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.CylinderGeometry) {
serializationGeometries.cylinders.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.TorusGeometry) {
serializationGeometries.toruses.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.GroundGeometry) {
serializationGeometries.grounds.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.Plane) {
serializationGeometries.planes.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.TorusKnotGeometry) {
serializationGeometries.torusKnots.push(geometry.serialize());
}
else if (geometry instanceof BABYLON._PrimitiveGeometry) {
throw new Error("Unknown primitive type");
}
else {
serializationGeometries.vertexData.push(geometry.serializeVerticeData());
}
serializedGeometries[geometry.id] = true;
};
var serializeMesh = function (mesh, serializationScene) {
var serializationObject = {};
// Geometry
var geometry = mesh._geometry;
if (geometry) {
if (!mesh.getScene().getGeometryByID(geometry.id)) {
// Geometry was in the memory but not added to the scene, nevertheless it's better to serialize to be able to reload the mesh with its geometry
serializeGeometry(geometry, serializationScene.geometries);
}
}
// Custom
if (mesh.serialize) {
mesh.serialize(serializationObject);
}
return serializationObject;
};
var finalizeSingleMesh = function (mesh, serializationObject) {
//only works if the mesh is already loaded
if (mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE) {
//serialize material
if (mesh.material) {
if (mesh.material instanceof BABYLON.StandardMaterial) {
serializationObject.materials = serializationObject.materials || [];
if (!serializationObject.materials.some(function (mat) { return (mat.id === mesh.material.id); })) {
serializationObject.materials.push(mesh.material.serialize());
}
}
else if (mesh.material instanceof BABYLON.MultiMaterial) {
serializationObject.multiMaterials = serializationObject.multiMaterials || [];
if (!serializationObject.multiMaterials.some(function (mat) { return (mat.id === mesh.material.id); })) {
serializationObject.multiMaterials.push(mesh.material.serialize());
}
}
}
//serialize geometry
var geometry = mesh._geometry;
if (geometry) {
if (!serializationObject.geometries) {
serializationObject.geometries = {};
serializationObject.geometries.boxes = [];
serializationObject.geometries.spheres = [];
serializationObject.geometries.cylinders = [];
serializationObject.geometries.toruses = [];
serializationObject.geometries.grounds = [];
serializationObject.geometries.planes = [];
serializationObject.geometries.torusKnots = [];
serializationObject.geometries.vertexData = [];
}
serializeGeometry(geometry, serializationObject.geometries);
}
// Skeletons
if (mesh.skeleton) {
serializationObject.skeletons = serializationObject.skeletons || [];
serializationObject.skeletons.push(mesh.skeleton.serialize());
}
//serialize the actual mesh
serializationObject.meshes = serializationObject.meshes || [];
serializationObject.meshes.push(serializeMesh(mesh, serializationObject));
}
};
var SceneSerializer = /** @class */ (function () {
function SceneSerializer() {
}
SceneSerializer.ClearCache = function () {
serializedGeometries = [];
};
SceneSerializer.Serialize = function (scene) {
var serializationObject = {};
SceneSerializer.ClearCache();
// Scene
serializationObject.useDelayedTextureLoading = scene.useDelayedTextureLoading;
serializationObject.autoClear = scene.autoClear;
serializationObject.clearColor = scene.clearColor.asArray();
serializationObject.ambientColor = scene.ambientColor.asArray();
serializationObject.gravity = scene.gravity.asArray();
serializationObject.collisionsEnabled = scene.collisionsEnabled;
serializationObject.workerCollisions = scene.workerCollisions;
// Fog
if (scene.fogMode && scene.fogMode !== 0) {
serializationObject.fogMode = scene.fogMode;
serializationObject.fogColor = scene.fogColor.asArray();
serializationObject.fogStart = scene.fogStart;
serializationObject.fogEnd = scene.fogEnd;
serializationObject.fogDensity = scene.fogDensity;
}
//Physics
if (scene.isPhysicsEnabled()) {
var physicEngine = scene.getPhysicsEngine();
if (physicEngine) {
serializationObject.physicsEnabled = true;
serializationObject.physicsGravity = physicEngine.gravity.asArray();
serializationObject.physicsEngine = physicEngine.getPhysicsPluginName();
}
}
// Metadata
if (scene.metadata) {
serializationObject.metadata = scene.metadata;
}
// Morph targets
serializationObject.morphTargetManagers = [];
for (var _i = 0, _a = scene.meshes; _i < _a.length; _i++) {
var abstractMesh = _a[_i];
var manager = abstractMesh.morphTargetManager;
if (manager) {
serializationObject.morphTargetManagers.push(manager.serialize());
}
}
// Lights
serializationObject.lights = [];
var index;
var light;
for (index = 0; index < scene.lights.length; index++) {
light = scene.lights[index];
if (!light.doNotSerialize) {
serializationObject.lights.push(light.serialize());
}
}
// Cameras
serializationObject.cameras = [];
for (index = 0; index < scene.cameras.length; index++) {
var camera = scene.cameras[index];
if (!camera.doNotSerialize) {
serializationObject.cameras.push(camera.serialize());
}
}
if (scene.activeCamera) {
serializationObject.activeCameraID = scene.activeCamera.id;
}
// Animations
BABYLON.Animation.AppendSerializedAnimations(scene, serializationObject);
// Materials
serializationObject.materials = [];
serializationObject.multiMaterials = [];
var material;
for (index = 0; index < scene.materials.length; index++) {
material = scene.materials[index];
if (!material.doNotSerialize) {
serializationObject.materials.push(material.serialize());
}
}
// MultiMaterials
serializationObject.multiMaterials = [];
for (index = 0; index < scene.multiMaterials.length; index++) {
var multiMaterial = scene.multiMaterials[index];
serializationObject.multiMaterials.push(multiMaterial.serialize());
}
// Environment texture
if (scene.environmentTexture) {
serializationObject.environmentTexture = scene.environmentTexture.name;
}
// Skeletons
serializationObject.skeletons = [];
for (index = 0; index < scene.skeletons.length; index++) {
var skeleton = scene.skeletons[index];
if (!skeleton.doNotSerialize) {
serializationObject.skeletons.push(skeleton.serialize());
}
}
// Transform nodes
serializationObject.transformNodes = [];
for (index = 0; index < scene.transformNodes.length; index++) {
serializationObject.transformNodes.push(scene.transformNodes[index].serialize());
}
// Geometries
serializationObject.geometries = {};
serializationObject.geometries.boxes = [];
serializationObject.geometries.spheres = [];
serializationObject.geometries.cylinders = [];
serializationObject.geometries.toruses = [];
serializationObject.geometries.grounds = [];
serializationObject.geometries.planes = [];
serializationObject.geometries.torusKnots = [];
serializationObject.geometries.vertexData = [];
serializedGeometries = [];
var geometries = scene.getGeometries();
for (index = 0; index < geometries.length; index++) {
var geometry = geometries[index];
if (geometry.isReady()) {
serializeGeometry(geometry, serializationObject.geometries);
}
}
// Meshes
serializationObject.meshes = [];
for (index = 0; index < scene.meshes.length; index++) {
var abstractMesh = scene.meshes[index];
if (abstractMesh instanceof BABYLON.Mesh) {
var mesh = abstractMesh;
if (!mesh.doNotSerialize) {
if (mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE) {
serializationObject.meshes.push(serializeMesh(mesh, serializationObject));
}
}
}
}
// Particles Systems
serializationObject.particleSystems = [];
for (index = 0; index < scene.particleSystems.length; index++) {
serializationObject.particleSystems.push(scene.particleSystems[index].serialize());
}
// Lens flares
serializationObject.lensFlareSystems = [];
for (index = 0; index < scene.lensFlareSystems.length; index++) {
serializationObject.lensFlareSystems.push(scene.lensFlareSystems[index].serialize());
}
// Shadows
serializationObject.shadowGenerators = [];
for (index = 0; index < scene.lights.length; index++) {
light = scene.lights[index];
var shadowGenerator = light.getShadowGenerator();
if (shadowGenerator) {
serializationObject.shadowGenerators.push(shadowGenerator.serialize());
}
}
// Action Manager
if (scene.actionManager) {
serializationObject.actions = scene.actionManager.serialize("scene");
}
// Audio
serializationObject.sounds = [];
for (index = 0; index < scene.soundTracks.length; index++) {
var soundtrack = scene.soundTracks[index];
for (var soundId = 0; soundId < soundtrack.soundCollection.length; soundId++) {
serializationObject.sounds.push(soundtrack.soundCollection[soundId].serialize());
}
}
// Effect layers
serializationObject.effectLayers = [];
for (index = 0; index < scene.effectLayers.length; index++) {
var layer = scene.effectLayers[index];
if (layer.serialize) {
serializationObject.effectLayers.push(layer.serialize());
}
}
return serializationObject;
};
SceneSerializer.SerializeMesh = function (toSerialize /* Mesh || Mesh[] */, withParents, withChildren) {
if (withParents === void 0) { withParents = false; }
if (withChildren === void 0) { withChildren = false; }
var serializationObject = {};
SceneSerializer.ClearCache();
toSerialize = (toSerialize instanceof Array) ? toSerialize : [toSerialize];
if (withParents || withChildren) {
//deliberate for loop! not for each, appended should be processed as well.
for (var i = 0; i < toSerialize.length; ++i) {
if (withChildren) {
toSerialize[i].getDescendants().forEach(function (node) {
if (node instanceof BABYLON.Mesh && (toSerialize.indexOf(node) < 0)) {
toSerialize.push(node);
}
});
}
//make sure the array doesn't contain the object already
if (withParents && toSerialize[i].parent && (toSerialize.indexOf(toSerialize[i].parent) < 0)) {
toSerialize.push(toSerialize[i].parent);
}
}
}
toSerialize.forEach(function (mesh) {
finalizeSingleMesh(mesh, serializationObject);
});
return serializationObject;
};
return SceneSerializer;
}());
BABYLON.SceneSerializer = SceneSerializer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.sceneSerializer.js.map
var BABYLON;
(function (BABYLON) {
var ReflectionProbe = /** @class */ (function () {
function ReflectionProbe(name, size, scene, generateMipMaps) {
if (generateMipMaps === void 0) { generateMipMaps = true; }
var _this = this;
this.name = name;
this._viewMatrix = BABYLON.Matrix.Identity();
this._target = BABYLON.Vector3.Zero();
this._add = BABYLON.Vector3.Zero();
this._invertYAxis = false;
this.position = BABYLON.Vector3.Zero();
this._scene = scene;
this._scene.reflectionProbes.push(this);
this._renderTargetTexture = new BABYLON.RenderTargetTexture(name, size, scene, generateMipMaps, true, BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT, true);
this._renderTargetTexture.onBeforeRenderObservable.add(function (faceIndex) {
switch (faceIndex) {
case 0:
_this._add.copyFromFloats(1, 0, 0);
break;
case 1:
_this._add.copyFromFloats(-1, 0, 0);
break;
case 2:
_this._add.copyFromFloats(0, _this._invertYAxis ? 1 : -1, 0);
break;
case 3:
_this._add.copyFromFloats(0, _this._invertYAxis ? -1 : 1, 0);
break;
case 4:
_this._add.copyFromFloats(0, 0, 1);
break;
case 5:
_this._add.copyFromFloats(0, 0, -1);
break;
}
if (_this._attachedMesh) {
_this.position.copyFrom(_this._attachedMesh.getAbsolutePosition());
}
_this.position.addToRef(_this._add, _this._target);
BABYLON.Matrix.LookAtLHToRef(_this.position, _this._target, BABYLON.Vector3.Up(), _this._viewMatrix);
scene.setTransformMatrix(_this._viewMatrix, _this._projectionMatrix);
scene._forcedViewPosition = _this.position;
});
this._renderTargetTexture.onAfterUnbindObservable.add(function () {
scene._forcedViewPosition = null;
scene.updateTransformMatrix(true);
});
if (scene.activeCamera) {
this._projectionMatrix = BABYLON.Matrix.PerspectiveFovLH(Math.PI / 2, 1, scene.activeCamera.minZ, scene.activeCamera.maxZ);
}
}
Object.defineProperty(ReflectionProbe.prototype, "samples", {
get: function () {
return this._renderTargetTexture.samples;
},
set: function (value) {
this._renderTargetTexture.samples = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ReflectionProbe.prototype, "refreshRate", {
get: function () {
return this._renderTargetTexture.refreshRate;
},
set: function (value) {
this._renderTargetTexture.refreshRate = value;
},
enumerable: true,
configurable: true
});
ReflectionProbe.prototype.getScene = function () {
return this._scene;
};
Object.defineProperty(ReflectionProbe.prototype, "cubeTexture", {
get: function () {
return this._renderTargetTexture;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ReflectionProbe.prototype, "renderList", {
get: function () {
return this._renderTargetTexture.renderList;
},
enumerable: true,
configurable: true
});
ReflectionProbe.prototype.attachToMesh = function (mesh) {
this._attachedMesh = mesh;
};
/**
* Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
*
* @param renderingGroupId The rendering group id corresponding to its index
* @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
*/
ReflectionProbe.prototype.setRenderingAutoClearDepthStencil = function (renderingGroupId, autoClearDepthStencil) {
this._renderTargetTexture.setRenderingAutoClearDepthStencil(renderingGroupId, autoClearDepthStencil);
};
ReflectionProbe.prototype.dispose = function () {
var index = this._scene.reflectionProbes.indexOf(this);
if (index !== -1) {
// Remove from the scene if found
this._scene.reflectionProbes.splice(index, 1);
}
if (this._renderTargetTexture) {
this._renderTargetTexture.dispose();
this._renderTargetTexture = null;
}
};
return ReflectionProbe;
}());
BABYLON.ReflectionProbe = ReflectionProbe;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.reflectionProbe.js.map
var BABYLON;
(function (BABYLON) {
var Layer = /** @class */ (function () {
function Layer(name, imgUrl, scene, isBackground, color) {
this.name = name;
this.scale = new BABYLON.Vector2(1, 1);
this.offset = new BABYLON.Vector2(0, 0);
this.alphaBlendingMode = BABYLON.Engine.ALPHA_COMBINE;
this.layerMask = 0x0FFFFFFF;
this._vertexBuffers = {};
// Events
/**
* An event triggered when the layer is disposed.
*/
this.onDisposeObservable = new BABYLON.Observable();
/**
* An event triggered before rendering the scene
*/
this.onBeforeRenderObservable = new BABYLON.Observable();
/**
* An event triggered after rendering the scene
*/
this.onAfterRenderObservable = new BABYLON.Observable();
this.texture = imgUrl ? new BABYLON.Texture(imgUrl, scene, true) : null;
this.isBackground = isBackground === undefined ? true : isBackground;
this.color = color === undefined ? new BABYLON.Color4(1, 1, 1, 1) : color;
this._scene = (scene || BABYLON.Engine.LastCreatedScene);
this._scene.layers.push(this);
var engine = this._scene.getEngine();
// VBO
var vertices = [];
vertices.push(1, 1);
vertices.push(-1, 1);
vertices.push(-1, -1);
vertices.push(1, -1);
var vertexBuffer = new BABYLON.VertexBuffer(engine, vertices, BABYLON.VertexBuffer.PositionKind, false, false, 2);
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = vertexBuffer;
this._createIndexBuffer();
// Effects
this._effect = engine.createEffect("layer", [BABYLON.VertexBuffer.PositionKind], ["textureMatrix", "color", "scale", "offset"], ["textureSampler"], "");
this._alphaTestEffect = engine.createEffect("layer", [BABYLON.VertexBuffer.PositionKind], ["textureMatrix", "color", "scale", "offset"], ["textureSampler"], "#define ALPHATEST");
}
Object.defineProperty(Layer.prototype, "onDispose", {
set: function (callback) {
if (this._onDisposeObserver) {
this.onDisposeObservable.remove(this._onDisposeObserver);
}
this._onDisposeObserver = this.onDisposeObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Layer.prototype, "onBeforeRender", {
set: function (callback) {
if (this._onBeforeRenderObserver) {
this.onBeforeRenderObservable.remove(this._onBeforeRenderObserver);
}
this._onBeforeRenderObserver = this.onBeforeRenderObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Layer.prototype, "onAfterRender", {
set: function (callback) {
if (this._onAfterRenderObserver) {
this.onAfterRenderObservable.remove(this._onAfterRenderObserver);
}
this._onAfterRenderObserver = this.onAfterRenderObservable.add(callback);
},
enumerable: true,
configurable: true
});
Layer.prototype._createIndexBuffer = function () {
var engine = this._scene.getEngine();
// Indices
var indices = [];
indices.push(0);
indices.push(1);
indices.push(2);
indices.push(0);
indices.push(2);
indices.push(3);
this._indexBuffer = engine.createIndexBuffer(indices);
};
Layer.prototype._rebuild = function () {
var vb = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vb) {
vb._rebuild();
}
this._createIndexBuffer();
};
Layer.prototype.render = function () {
var currentEffect = this.alphaTest ? this._alphaTestEffect : this._effect;
// Check
if (!currentEffect.isReady() || !this.texture || !this.texture.isReady())
return;
var engine = this._scene.getEngine();
this.onBeforeRenderObservable.notifyObservers(this);
// Render
engine.enableEffect(currentEffect);
engine.setState(false);
// Texture
currentEffect.setTexture("textureSampler", this.texture);
currentEffect.setMatrix("textureMatrix", this.texture.getTextureMatrix());
// Color
currentEffect.setFloat4("color", this.color.r, this.color.g, this.color.b, this.color.a);
// Scale / offset
currentEffect.setVector2("offset", this.offset);
currentEffect.setVector2("scale", this.scale);
// VBOs
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, currentEffect);
// Draw order
if (!this.alphaTest) {
engine.setAlphaMode(this.alphaBlendingMode);
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
}
else {
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
}
this.onAfterRenderObservable.notifyObservers(this);
};
Layer.prototype.dispose = function () {
var vertexBuffer = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vertexBuffer) {
vertexBuffer.dispose();
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = null;
}
if (this._indexBuffer) {
this._scene.getEngine()._releaseBuffer(this._indexBuffer);
this._indexBuffer = null;
}
if (this.texture) {
this.texture.dispose();
this.texture = null;
}
// Remove from scene
var index = this._scene.layers.indexOf(this);
this._scene.layers.splice(index, 1);
// Callback
this.onDisposeObservable.notifyObservers(this);
this.onDisposeObservable.clear();
this.onAfterRenderObservable.clear();
this.onBeforeRenderObservable.clear();
};
return Layer;
}());
BABYLON.Layer = Layer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.layer.js.map
var BABYLON;
(function (BABYLON) {
var TextureTools = /** @class */ (function () {
function TextureTools() {
}
/**
* Uses the GPU to create a copy texture rescaled at a given size
* @param texture Texture to copy from
* @param width Desired width
* @param height Desired height
* @return Generated texture
*/
TextureTools.CreateResizedCopy = function (texture, width, height, useBilinearMode) {
if (useBilinearMode === void 0) { useBilinearMode = true; }
var scene = texture.getScene();
var engine = scene.getEngine();
var rtt = new BABYLON.RenderTargetTexture('resized' + texture.name, { width: width, height: height }, scene, !texture.noMipmap, true, texture._texture.type, false, texture._samplingMode, false);
rtt.wrapU = texture.wrapU;
rtt.wrapV = texture.wrapV;
rtt.uOffset = texture.uOffset;
rtt.vOffset = texture.vOffset;
rtt.uScale = texture.uScale;
rtt.vScale = texture.vScale;
rtt.uAng = texture.uAng;
rtt.vAng = texture.vAng;
rtt.wAng = texture.wAng;
rtt.coordinatesIndex = texture.coordinatesIndex;
rtt.level = texture.level;
rtt.anisotropicFilteringLevel = texture.anisotropicFilteringLevel;
rtt._texture.isReady = false;
texture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
texture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
var passPostProcess = new BABYLON.PassPostProcess("pass", 1, null, useBilinearMode ? BABYLON.Texture.BILINEAR_SAMPLINGMODE : BABYLON.Texture.NEAREST_SAMPLINGMODE, engine, false, BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
passPostProcess.getEffect().executeWhenCompiled(function () {
passPostProcess.onApply = function (effect) {
effect.setTexture("textureSampler", texture);
};
var internalTexture = rtt.getInternalTexture();
if (internalTexture) {
scene.postProcessManager.directRender([passPostProcess], internalTexture);
engine.unBindFramebuffer(internalTexture);
rtt.disposeFramebufferObjects();
passPostProcess.dispose();
internalTexture.isReady = true;
}
});
return rtt;
};
TextureTools.GetEnvironmentBRDFTexture = function (scene) {
if (!scene._environmentBRDFTexture) {
var texture = BABYLON.Texture.CreateFromBase64String(this._environmentBRDFBase64Texture, "EnvironmentBRDFTexture", scene, true, false, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
texture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
texture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
scene._environmentBRDFTexture = texture;
}
return scene._environmentBRDFTexture;
};
TextureTools._environmentBRDFBase64Texture = "data:image/png;base64,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";
return TextureTools;
}());
BABYLON.TextureTools = TextureTools;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.textureTools.js.map
var BABYLON;
(function (BABYLON) {
var FramingBehavior = /** @class */ (function () {
function FramingBehavior() {
this._mode = FramingBehavior.FitFrustumSidesMode;
this._radiusScale = 1.0;
this._positionScale = 0.5;
this._defaultElevation = 0.3;
this._elevationReturnTime = 1500;
this._elevationReturnWaitTime = 1000;
this._zoomStopsAnimation = false;
this._framingTime = 1500;
this._isPointerDown = false;
this._lastInteractionTime = -Infinity;
// Framing control
this._animatables = new Array();
this._betaIsAnimating = false;
}
Object.defineProperty(FramingBehavior.prototype, "name", {
get: function () {
return "Framing";
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "mode", {
/**
* Gets current mode used by the behavior.
*/
get: function () {
return this._mode;
},
/**
* Sets the current mode used by the behavior
*/
set: function (mode) {
this._mode = mode;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "radiusScale", {
/**
* Gets the scale applied to the radius
*/
get: function () {
return this._radiusScale;
},
/**
* Sets the scale applied to the radius (1 by default)
*/
set: function (radius) {
this._radiusScale = radius;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "positionScale", {
/**
* Gets the scale to apply on Y axis to position camera focus. 0.5 by default which means the center of the bounding box.
*/
get: function () {
return this._positionScale;
},
/**
* Sets the scale to apply on Y axis to position camera focus. 0.5 by default which means the center of the bounding box.
*/
set: function (scale) {
this._positionScale = scale;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "defaultElevation", {
/**
* Gets the angle above/below the horizontal plane to return to when the return to default elevation idle
* behaviour is triggered, in radians.
*/
get: function () {
return this._defaultElevation;
},
/**
* Sets the angle above/below the horizontal plane to return to when the return to default elevation idle
* behaviour is triggered, in radians.
*/
set: function (elevation) {
this._defaultElevation = elevation;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "elevationReturnTime", {
/**
* Gets the time (in milliseconds) taken to return to the default beta position.
* Negative value indicates camera should not return to default.
*/
get: function () {
return this._elevationReturnTime;
},
/**
* Sets the time (in milliseconds) taken to return to the default beta position.
* Negative value indicates camera should not return to default.
*/
set: function (speed) {
this._elevationReturnTime = speed;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "elevationReturnWaitTime", {
/**
* Gets the delay (in milliseconds) taken before the camera returns to the default beta position.
*/
get: function () {
return this._elevationReturnWaitTime;
},
/**
* Sets the delay (in milliseconds) taken before the camera returns to the default beta position.
*/
set: function (time) {
this._elevationReturnWaitTime = time;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "zoomStopsAnimation", {
/**
* Gets the flag that indicates if user zooming should stop animation.
*/
get: function () {
return this._zoomStopsAnimation;
},
/**
* Sets the flag that indicates if user zooming should stop animation.
*/
set: function (flag) {
this._zoomStopsAnimation = flag;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "framingTime", {
/**
* Gets the transition time when framing the mesh, in milliseconds
*/
get: function () {
return this._framingTime;
},
/**
* Sets the transition time when framing the mesh, in milliseconds
*/
set: function (time) {
this._framingTime = time;
},
enumerable: true,
configurable: true
});
FramingBehavior.prototype.init = function () {
// Do notihng
};
FramingBehavior.prototype.attach = function (camera) {
var _this = this;
this._attachedCamera = camera;
var scene = this._attachedCamera.getScene();
FramingBehavior.EasingFunction.setEasingMode(FramingBehavior.EasingMode);
this._onPrePointerObservableObserver = scene.onPrePointerObservable.add(function (pointerInfoPre) {
if (pointerInfoPre.type === BABYLON.PointerEventTypes.POINTERDOWN) {
_this._isPointerDown = true;
return;
}
if (pointerInfoPre.type === BABYLON.PointerEventTypes.POINTERUP) {
_this._isPointerDown = false;
}
});
this._onMeshTargetChangedObserver = camera.onMeshTargetChangedObservable.add(function (mesh) {
if (mesh) {
_this.zoomOnMesh(mesh);
}
});
this._onAfterCheckInputsObserver = camera.onAfterCheckInputsObservable.add(function () {
// Stop the animation if there is user interaction and the animation should stop for this interaction
_this._applyUserInteraction();
// Maintain the camera above the ground. If the user pulls the camera beneath the ground plane, lift it
// back to the default position after a given timeout
_this._maintainCameraAboveGround();
});
};
FramingBehavior.prototype.detach = function () {
if (!this._attachedCamera) {
return;
}
var scene = this._attachedCamera.getScene();
if (this._onPrePointerObservableObserver) {
scene.onPrePointerObservable.remove(this._onPrePointerObservableObserver);
}
if (this._onAfterCheckInputsObserver) {
this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
}
if (this._onMeshTargetChangedObserver) {
this._attachedCamera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
}
this._attachedCamera = null;
};
/**
* Targets the given mesh and updates zoom level accordingly.
* @param mesh The mesh to target.
* @param radius Optional. If a cached radius position already exists, overrides default.
* @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
* @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
* @param onAnimationEnd Callback triggered at the end of the framing animation
*/
FramingBehavior.prototype.zoomOnMesh = function (mesh, focusOnOriginXZ, onAnimationEnd) {
if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
if (onAnimationEnd === void 0) { onAnimationEnd = null; }
mesh.computeWorldMatrix(true);
var boundingBox = mesh.getBoundingInfo().boundingBox;
this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ, onAnimationEnd);
};
/**
* Targets the given mesh with its children and updates zoom level accordingly.
* @param mesh The mesh to target.
* @param radius Optional. If a cached radius position already exists, overrides default.
* @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
* @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
* @param onAnimationEnd Callback triggered at the end of the framing animation
*/
FramingBehavior.prototype.zoomOnMeshHierarchy = function (mesh, focusOnOriginXZ, onAnimationEnd) {
if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
if (onAnimationEnd === void 0) { onAnimationEnd = null; }
mesh.computeWorldMatrix(true);
var boundingBox = mesh.getHierarchyBoundingVectors(true);
this.zoomOnBoundingInfo(boundingBox.min, boundingBox.max, focusOnOriginXZ, onAnimationEnd);
};
/**
* Targets the given meshes with their children and updates zoom level accordingly.
* @param meshes The mesh to target.
* @param radius Optional. If a cached radius position already exists, overrides default.
* @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
* @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
* @param onAnimationEnd Callback triggered at the end of the framing animation
*/
FramingBehavior.prototype.zoomOnMeshesHierarchy = function (meshes, focusOnOriginXZ, onAnimationEnd) {
if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
if (onAnimationEnd === void 0) { onAnimationEnd = null; }
var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
var max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
for (var i = 0; i < meshes.length; i++) {
var boundingInfo = meshes[i].getHierarchyBoundingVectors(true);
BABYLON.Tools.CheckExtends(boundingInfo.min, min, max);
BABYLON.Tools.CheckExtends(boundingInfo.max, min, max);
}
this.zoomOnBoundingInfo(min, max, focusOnOriginXZ, onAnimationEnd);
};
/**
* Targets the given mesh and updates zoom level accordingly.
* @param mesh The mesh to target.
* @param radius Optional. If a cached radius position already exists, overrides default.
* @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
* @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
* @param onAnimationEnd Callback triggered at the end of the framing animation
*/
FramingBehavior.prototype.zoomOnBoundingInfo = function (minimumWorld, maximumWorld, focusOnOriginXZ, onAnimationEnd) {
var _this = this;
if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
if (onAnimationEnd === void 0) { onAnimationEnd = null; }
var zoomTarget;
if (!this._attachedCamera) {
return;
}
// Find target by interpolating from bottom of bounding box in world-space to top via framingPositionY
var bottom = minimumWorld.y;
var top = maximumWorld.y;
var zoomTargetY = bottom + (top - bottom) * this._positionScale;
var radiusWorld = maximumWorld.subtract(minimumWorld).scale(0.5);
if (focusOnOriginXZ) {
zoomTarget = new BABYLON.Vector3(0, zoomTargetY, 0);
}
else {
var centerWorld = minimumWorld.add(radiusWorld);
zoomTarget = new BABYLON.Vector3(centerWorld.x, zoomTargetY, centerWorld.z);
}
if (!this._vectorTransition) {
this._vectorTransition = BABYLON.Animation.CreateAnimation("target", BABYLON.Animation.ANIMATIONTYPE_VECTOR3, 60, FramingBehavior.EasingFunction);
}
this._betaIsAnimating = true;
var animatable = BABYLON.Animation.TransitionTo("target", zoomTarget, this._attachedCamera, this._attachedCamera.getScene(), 60, this._vectorTransition, this._framingTime);
if (animatable) {
this._animatables.push(animatable);
}
// sets the radius and lower radius bounds
// Small delta ensures camera is not always at lower zoom limit.
var radius = 0;
if (this._mode === FramingBehavior.FitFrustumSidesMode) {
var position = this._calculateLowerRadiusFromModelBoundingSphere(minimumWorld, maximumWorld);
this._attachedCamera.lowerRadiusLimit = radiusWorld.length() + this._attachedCamera.minZ;
radius = position;
}
else if (this._mode === FramingBehavior.IgnoreBoundsSizeMode) {
radius = this._calculateLowerRadiusFromModelBoundingSphere(minimumWorld, maximumWorld);
if (this._attachedCamera.lowerRadiusLimit === null) {
this._attachedCamera.lowerRadiusLimit = this._attachedCamera.minZ;
}
}
// Set sensibilities
var extend = maximumWorld.subtract(minimumWorld).length();
this._attachedCamera.panningSensibility = 5000 / extend;
this._attachedCamera.wheelPrecision = 100 / radius;
// transition to new radius
if (!this._radiusTransition) {
this._radiusTransition = BABYLON.Animation.CreateAnimation("radius", BABYLON.Animation.ANIMATIONTYPE_FLOAT, 60, FramingBehavior.EasingFunction);
}
animatable = BABYLON.Animation.TransitionTo("radius", radius, this._attachedCamera, this._attachedCamera.getScene(), 60, this._radiusTransition, this._framingTime, function () {
_this.stopAllAnimations();
if (onAnimationEnd) {
onAnimationEnd();
}
if (_this._attachedCamera) {
_this._attachedCamera.storeState();
}
});
if (animatable) {
this._animatables.push(animatable);
}
};
/**
* Calculates the lowest radius for the camera based on the bounding box of the mesh.
* @param mesh The mesh on which to base the calculation. mesh boundingInfo used to estimate necessary
* frustum width.
* @return The minimum distance from the primary mesh's center point at which the camera must be kept in order
* to fully enclose the mesh in the viewing frustum.
*/
FramingBehavior.prototype._calculateLowerRadiusFromModelBoundingSphere = function (minimumWorld, maximumWorld) {
var size = maximumWorld.subtract(minimumWorld);
var boxVectorGlobalDiagonal = size.length();
var frustumSlope = this._getFrustumSlope();
// Formula for setting distance
// (Good explanation: http://stackoverflow.com/questions/2866350/move-camera-to-fit-3d-scene)
var radiusWithoutFraming = boxVectorGlobalDiagonal * 0.5;
// Horizon distance
var radius = radiusWithoutFraming * this._radiusScale;
var distanceForHorizontalFrustum = radius * Math.sqrt(1.0 + 1.0 / (frustumSlope.x * frustumSlope.x));
var distanceForVerticalFrustum = radius * Math.sqrt(1.0 + 1.0 / (frustumSlope.y * frustumSlope.y));
var distance = Math.max(distanceForHorizontalFrustum, distanceForVerticalFrustum);
var camera = this._attachedCamera;
if (!camera) {
return 0;
}
if (camera.lowerRadiusLimit && this._mode === FramingBehavior.IgnoreBoundsSizeMode) {
// Don't exceed the requested limit
distance = distance < camera.lowerRadiusLimit ? camera.lowerRadiusLimit : distance;
}
// Don't exceed the upper radius limit
if (camera.upperRadiusLimit) {
distance = distance > camera.upperRadiusLimit ? camera.upperRadiusLimit : distance;
}
return distance;
};
/**
* Keeps the camera above the ground plane. If the user pulls the camera below the ground plane, the camera
* is automatically returned to its default position (expected to be above ground plane).
*/
FramingBehavior.prototype._maintainCameraAboveGround = function () {
var _this = this;
if (this._elevationReturnTime < 0) {
return;
}
var timeSinceInteraction = BABYLON.Tools.Now - this._lastInteractionTime;
var defaultBeta = Math.PI * 0.5 - this._defaultElevation;
var limitBeta = Math.PI * 0.5;
// Bring the camera back up if below the ground plane
if (this._attachedCamera && !this._betaIsAnimating && this._attachedCamera.beta > limitBeta && timeSinceInteraction >= this._elevationReturnWaitTime) {
this._betaIsAnimating = true;
//Transition to new position
this.stopAllAnimations();
if (!this._betaTransition) {
this._betaTransition = BABYLON.Animation.CreateAnimation("beta", BABYLON.Animation.ANIMATIONTYPE_FLOAT, 60, FramingBehavior.EasingFunction);
}
var animatabe = BABYLON.Animation.TransitionTo("beta", defaultBeta, this._attachedCamera, this._attachedCamera.getScene(), 60, this._betaTransition, this._elevationReturnTime, function () {
_this._clearAnimationLocks();
_this.stopAllAnimations();
});
if (animatabe) {
this._animatables.push(animatabe);
}
}
};
/**
* Returns the frustum slope based on the canvas ratio and camera FOV
* @returns The frustum slope represented as a Vector2 with X and Y slopes
*/
FramingBehavior.prototype._getFrustumSlope = function () {
// Calculate the viewport ratio
// Aspect Ratio is Height/Width.
var camera = this._attachedCamera;
if (!camera) {
return BABYLON.Vector2.Zero();
}
var engine = camera.getScene().getEngine();
var aspectRatio = engine.getAspectRatio(camera);
// Camera FOV is the vertical field of view (top-bottom) in radians.
// Slope of the frustum top/bottom planes in view space, relative to the forward vector.
var frustumSlopeY = Math.tan(camera.fov / 2);
// Slope of the frustum left/right planes in view space, relative to the forward vector.
// Provides the amount that one side (e.g. left) of the frustum gets wider for every unit
// along the forward vector.
var frustumSlopeX = frustumSlopeY * aspectRatio;
return new BABYLON.Vector2(frustumSlopeX, frustumSlopeY);
};
/**
* Removes all animation locks. Allows new animations to be added to any of the arcCamera properties.
*/
FramingBehavior.prototype._clearAnimationLocks = function () {
this._betaIsAnimating = false;
};
/**
* Applies any current user interaction to the camera. Takes into account maximum alpha rotation.
*/
FramingBehavior.prototype._applyUserInteraction = function () {
if (this.isUserIsMoving) {
this._lastInteractionTime = BABYLON.Tools.Now;
this.stopAllAnimations();
this._clearAnimationLocks();
}
};
/**
* Stops and removes all animations that have been applied to the camera
*/
FramingBehavior.prototype.stopAllAnimations = function () {
if (this._attachedCamera) {
this._attachedCamera.animations = [];
}
while (this._animatables.length) {
if (this._animatables[0]) {
this._animatables[0].onAnimationEnd = null;
this._animatables[0].stop();
}
this._animatables.shift();
}
};
Object.defineProperty(FramingBehavior.prototype, "isUserIsMoving", {
/**
* Gets a value indicating if the user is moving the camera
*/
get: function () {
if (!this._attachedCamera) {
return false;
}
return this._attachedCamera.inertialAlphaOffset !== 0 ||
this._attachedCamera.inertialBetaOffset !== 0 ||
this._attachedCamera.inertialRadiusOffset !== 0 ||
this._attachedCamera.inertialPanningX !== 0 ||
this._attachedCamera.inertialPanningY !== 0 ||
this._isPointerDown;
},
enumerable: true,
configurable: true
});
/**
* The easing function used by animations
*/
FramingBehavior.EasingFunction = new BABYLON.ExponentialEase();
/**
* The easing mode used by animations
*/
FramingBehavior.EasingMode = BABYLON.EasingFunction.EASINGMODE_EASEINOUT;
// Statics
/**
* The camera can move all the way towards the mesh.
*/
FramingBehavior.IgnoreBoundsSizeMode = 0;
/**
* The camera is not allowed to zoom closer to the mesh than the point at which the adjusted bounding sphere touches the frustum sides
*/
FramingBehavior.FitFrustumSidesMode = 1;
return FramingBehavior;
}());
BABYLON.FramingBehavior = FramingBehavior;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.framingBehavior.js.map
var BABYLON;
(function (BABYLON) {
/**
* Add a bouncing effect to an ArcRotateCamera when reaching a specified minimum and maximum radius
*/
var BouncingBehavior = /** @class */ (function () {
function BouncingBehavior() {
/**
* The duration of the animation, in milliseconds
*/
this.transitionDuration = 450;
/**
* Length of the distance animated by the transition when lower radius is reached
*/
this.lowerRadiusTransitionRange = 2;
/**
* Length of the distance animated by the transition when upper radius is reached
*/
this.upperRadiusTransitionRange = -2;
this._autoTransitionRange = false;
// Animations
this._radiusIsAnimating = false;
this._radiusBounceTransition = null;
this._animatables = new Array();
}
Object.defineProperty(BouncingBehavior.prototype, "name", {
get: function () {
return "Bouncing";
},
enumerable: true,
configurable: true
});
Object.defineProperty(BouncingBehavior.prototype, "autoTransitionRange", {
/**
* Gets a value indicating if the lowerRadiusTransitionRange and upperRadiusTransitionRange are defined automatically
*/
get: function () {
return this._autoTransitionRange;
},
/**
* Sets a value indicating if the lowerRadiusTransitionRange and upperRadiusTransitionRange are defined automatically
* Transition ranges will be set to 5% of the bounding box diagonal in world space
*/
set: function (value) {
var _this = this;
if (this._autoTransitionRange === value) {
return;
}
this._autoTransitionRange = value;
var camera = this._attachedCamera;
if (!camera) {
return;
}
if (value) {
this._onMeshTargetChangedObserver = camera.onMeshTargetChangedObservable.add(function (mesh) {
if (!mesh) {
return;
}
mesh.computeWorldMatrix(true);
var diagonal = mesh.getBoundingInfo().diagonalLength;
_this.lowerRadiusTransitionRange = diagonal * 0.05;
_this.upperRadiusTransitionRange = diagonal * 0.05;
});
}
else if (this._onMeshTargetChangedObserver) {
camera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
}
},
enumerable: true,
configurable: true
});
BouncingBehavior.prototype.init = function () {
// Do notihng
};
BouncingBehavior.prototype.attach = function (camera) {
var _this = this;
this._attachedCamera = camera;
this._onAfterCheckInputsObserver = camera.onAfterCheckInputsObservable.add(function () {
if (!_this._attachedCamera) {
return;
}
// Add the bounce animation to the lower radius limit
if (_this._isRadiusAtLimit(_this._attachedCamera.lowerRadiusLimit)) {
_this._applyBoundRadiusAnimation(_this.lowerRadiusTransitionRange);
}
// Add the bounce animation to the upper radius limit
if (_this._isRadiusAtLimit(_this._attachedCamera.upperRadiusLimit)) {
_this._applyBoundRadiusAnimation(_this.upperRadiusTransitionRange);
}
});
};
BouncingBehavior.prototype.detach = function () {
if (!this._attachedCamera) {
return;
}
if (this._onAfterCheckInputsObserver) {
this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
}
if (this._onMeshTargetChangedObserver) {
this._attachedCamera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
}
this._attachedCamera = null;
};
/**
* Checks if the camera radius is at the specified limit. Takes into account animation locks.
* @param radiusLimit The limit to check against.
* @return Bool to indicate if at limit.
*/
BouncingBehavior.prototype._isRadiusAtLimit = function (radiusLimit) {
if (!this._attachedCamera) {
return false;
}
if (this._attachedCamera.radius === radiusLimit && !this._radiusIsAnimating) {
return true;
}
return false;
};
/**
* Applies an animation to the radius of the camera, extending by the radiusDelta.
* @param radiusDelta The delta by which to animate to. Can be negative.
*/
BouncingBehavior.prototype._applyBoundRadiusAnimation = function (radiusDelta) {
var _this = this;
if (!this._attachedCamera) {
return;
}
if (!this._radiusBounceTransition) {
BouncingBehavior.EasingFunction.setEasingMode(BouncingBehavior.EasingMode);
this._radiusBounceTransition = BABYLON.Animation.CreateAnimation("radius", BABYLON.Animation.ANIMATIONTYPE_FLOAT, 60, BouncingBehavior.EasingFunction);
}
// Prevent zoom until bounce has completed
this._cachedWheelPrecision = this._attachedCamera.wheelPrecision;
this._attachedCamera.wheelPrecision = Infinity;
this._attachedCamera.inertialRadiusOffset = 0;
// Animate to the radius limit
this.stopAllAnimations();
this._radiusIsAnimating = true;
var animatable = BABYLON.Animation.TransitionTo("radius", this._attachedCamera.radius + radiusDelta, this._attachedCamera, this._attachedCamera.getScene(), 60, this._radiusBounceTransition, this.transitionDuration, function () { return _this._clearAnimationLocks(); });
if (animatable) {
this._animatables.push(animatable);
}
};
/**
* Removes all animation locks. Allows new animations to be added to any of the camera properties.
*/
BouncingBehavior.prototype._clearAnimationLocks = function () {
this._radiusIsAnimating = false;
if (this._attachedCamera) {
this._attachedCamera.wheelPrecision = this._cachedWheelPrecision;
}
};
/**
* Stops and removes all animations that have been applied to the camera
*/
BouncingBehavior.prototype.stopAllAnimations = function () {
if (this._attachedCamera) {
this._attachedCamera.animations = [];
}
while (this._animatables.length) {
this._animatables[0].onAnimationEnd = null;
this._animatables[0].stop();
this._animatables.shift();
}
};
/**
* The easing function used by animations
*/
BouncingBehavior.EasingFunction = new BABYLON.BackEase(0.3);
/**
* The easing mode used by animations
*/
BouncingBehavior.EasingMode = BABYLON.EasingFunction.EASINGMODE_EASEOUT;
return BouncingBehavior;
}());
BABYLON.BouncingBehavior = BouncingBehavior;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.bouncingBehavior.js.map
var BABYLON;
(function (BABYLON) {
var AutoRotationBehavior = /** @class */ (function () {
function AutoRotationBehavior() {
this._zoomStopsAnimation = false;
this._idleRotationSpeed = 0.05;
this._idleRotationWaitTime = 2000;
this._idleRotationSpinupTime = 2000;
this._isPointerDown = false;
this._lastFrameTime = null;
this._lastInteractionTime = -Infinity;
this._cameraRotationSpeed = 0;
this._lastFrameRadius = 0;
}
Object.defineProperty(AutoRotationBehavior.prototype, "name", {
get: function () {
return "AutoRotation";
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "zoomStopsAnimation", {
/**
* Gets the flag that indicates if user zooming should stop animation.
*/
get: function () {
return this._zoomStopsAnimation;
},
/**
* Sets the flag that indicates if user zooming should stop animation.
*/
set: function (flag) {
this._zoomStopsAnimation = flag;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "idleRotationSpeed", {
/**
* Gets the default speed at which the camera rotates around the model.
*/
get: function () {
return this._idleRotationSpeed;
},
/**
* Sets the default speed at which the camera rotates around the model.
*/
set: function (speed) {
this._idleRotationSpeed = speed;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "idleRotationWaitTime", {
/**
* Gets the time (milliseconds) to wait after user interaction before the camera starts rotating.
*/
get: function () {
return this._idleRotationWaitTime;
},
/**
* Sets the time (in milliseconds) to wait after user interaction before the camera starts rotating.
*/
set: function (time) {
this._idleRotationWaitTime = time;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "idleRotationSpinupTime", {
/**
* Gets the time (milliseconds) to take to spin up to the full idle rotation speed.
*/
get: function () {
return this._idleRotationSpinupTime;
},
/**
* Sets the time (milliseconds) to take to spin up to the full idle rotation speed.
*/
set: function (time) {
this._idleRotationSpinupTime = time;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "rotationInProgress", {
/**
* Gets a value indicating if the camera is currently rotating because of this behavior
*/
get: function () {
return Math.abs(this._cameraRotationSpeed) > 0;
},
enumerable: true,
configurable: true
});
AutoRotationBehavior.prototype.init = function () {
// Do notihng
};
AutoRotationBehavior.prototype.attach = function (camera) {
var _this = this;
this._attachedCamera = camera;
var scene = this._attachedCamera.getScene();
this._onPrePointerObservableObserver = scene.onPrePointerObservable.add(function (pointerInfoPre) {
if (pointerInfoPre.type === BABYLON.PointerEventTypes.POINTERDOWN) {
_this._isPointerDown = true;
return;
}
if (pointerInfoPre.type === BABYLON.PointerEventTypes.POINTERUP) {
_this._isPointerDown = false;
}
});
this._onAfterCheckInputsObserver = camera.onAfterCheckInputsObservable.add(function () {
var now = BABYLON.Tools.Now;
var dt = 0;
if (_this._lastFrameTime != null) {
dt = now - _this._lastFrameTime;
}
_this._lastFrameTime = now;
// Stop the animation if there is user interaction and the animation should stop for this interaction
_this._applyUserInteraction();
var timeToRotation = now - _this._lastInteractionTime - _this._idleRotationWaitTime;
var scale = Math.max(Math.min(timeToRotation / (_this._idleRotationSpinupTime), 1), 0);
_this._cameraRotationSpeed = _this._idleRotationSpeed * scale;
// Step camera rotation by rotation speed
if (_this._attachedCamera) {
_this._attachedCamera.alpha -= _this._cameraRotationSpeed * (dt / 1000);
}
});
};
AutoRotationBehavior.prototype.detach = function () {
if (!this._attachedCamera) {
return;
}
var scene = this._attachedCamera.getScene();
if (this._onPrePointerObservableObserver) {
scene.onPrePointerObservable.remove(this._onPrePointerObservableObserver);
}
this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
this._attachedCamera = null;
};
/**
* Returns true if user is scrolling.
* @return true if user is scrolling.
*/
AutoRotationBehavior.prototype._userIsZooming = function () {
if (!this._attachedCamera) {
return false;
}
return this._attachedCamera.inertialRadiusOffset !== 0;
};
AutoRotationBehavior.prototype._shouldAnimationStopForInteraction = function () {
if (!this._attachedCamera) {
return false;
}
var zoomHasHitLimit = false;
if (this._lastFrameRadius === this._attachedCamera.radius && this._attachedCamera.inertialRadiusOffset !== 0) {
zoomHasHitLimit = true;
}
// Update the record of previous radius - works as an approx. indicator of hitting radius limits
this._lastFrameRadius = this._attachedCamera.radius;
return this._zoomStopsAnimation ? zoomHasHitLimit : this._userIsZooming();
};
/**
* Applies any current user interaction to the camera. Takes into account maximum alpha rotation.
*/
AutoRotationBehavior.prototype._applyUserInteraction = function () {
if (this._userIsMoving() && !this._shouldAnimationStopForInteraction()) {
this._lastInteractionTime = BABYLON.Tools.Now;
}
};
// Tools
AutoRotationBehavior.prototype._userIsMoving = function () {
if (!this._attachedCamera) {
return false;
}
return this._attachedCamera.inertialAlphaOffset !== 0 ||
this._attachedCamera.inertialBetaOffset !== 0 ||
this._attachedCamera.inertialRadiusOffset !== 0 ||
this._attachedCamera.inertialPanningX !== 0 ||
this._attachedCamera.inertialPanningY !== 0 ||
this._isPointerDown;
};
return AutoRotationBehavior;
}());
BABYLON.AutoRotationBehavior = AutoRotationBehavior;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.autoRotationBehavior.js.map
var BABYLON;
(function (BABYLON) {
var NullEngineOptions = /** @class */ (function () {
function NullEngineOptions() {
this.renderWidth = 512;
this.renderHeight = 256;
this.textureSize = 512;
this.deterministicLockstep = false;
this.lockstepMaxSteps = 4;
}
return NullEngineOptions;
}());
BABYLON.NullEngineOptions = NullEngineOptions;
/**
* The null engine class provides support for headless version of babylon.js.
* This can be used in server side scenario or for testing purposes
*/
var NullEngine = /** @class */ (function (_super) {
__extends(NullEngine, _super);
function NullEngine(options) {
if (options === void 0) { options = new NullEngineOptions(); }
var _this = _super.call(this, null) || this;
if (options.deterministicLockstep === undefined) {
options.deterministicLockstep = false;
}
if (options.lockstepMaxSteps === undefined) {
options.lockstepMaxSteps = 4;
}
_this._options = options;
// Init caps
// We consider we are on a webgl1 capable device
_this._caps = new BABYLON.EngineCapabilities();
_this._caps.maxTexturesImageUnits = 16;
_this._caps.maxVertexTextureImageUnits = 16;
_this._caps.maxTextureSize = 512;
_this._caps.maxCubemapTextureSize = 512;
_this._caps.maxRenderTextureSize = 512;
_this._caps.maxVertexAttribs = 16;
_this._caps.maxVaryingVectors = 16;
_this._caps.maxFragmentUniformVectors = 16;
_this._caps.maxVertexUniformVectors = 16;
// Extensions
_this._caps.standardDerivatives = false;
_this._caps.astc = null;
_this._caps.s3tc = null;
_this._caps.pvrtc = null;
_this._caps.etc1 = null;
_this._caps.etc2 = null;
_this._caps.textureAnisotropicFilterExtension = null;
_this._caps.maxAnisotropy = 0;
_this._caps.uintIndices = false;
_this._caps.fragmentDepthSupported = false;
_this._caps.highPrecisionShaderSupported = true;
_this._caps.colorBufferFloat = false;
_this._caps.textureFloat = false;
_this._caps.textureFloatLinearFiltering = false;
_this._caps.textureFloatRender = false;
_this._caps.textureHalfFloat = false;
_this._caps.textureHalfFloatLinearFiltering = false;
_this._caps.textureHalfFloatRender = false;
_this._caps.textureLOD = false;
_this._caps.drawBuffersExtension = false;
_this._caps.depthTextureExtension = false;
_this._caps.vertexArrayObject = false;
_this._caps.instancedArrays = false;
BABYLON.Tools.Log("Babylon.js null engine (v" + BABYLON.Engine.Version + ") launched");
// Wrappers
if (typeof URL === "undefined") {
URL = {
createObjectURL: function () { },
revokeObjectURL: function () { }
};
}
if (typeof Blob === "undefined") {
Blob = function () { };
}
return _this;
}
NullEngine.prototype.isDeterministicLockStep = function () {
return this._options.deterministicLockstep;
};
NullEngine.prototype.getLockstepMaxSteps = function () {
return this._options.lockstepMaxSteps;
};
NullEngine.prototype.getHardwareScalingLevel = function () {
return 1.0;
};
NullEngine.prototype.createVertexBuffer = function (vertices) {
return {
capacity: 0,
references: 1,
is32Bits: false
};
};
NullEngine.prototype.createIndexBuffer = function (indices) {
return {
capacity: 0,
references: 1,
is32Bits: false
};
};
NullEngine.prototype.clear = function (color, backBuffer, depth, stencil) {
if (stencil === void 0) { stencil = false; }
};
NullEngine.prototype.getRenderWidth = function (useScreen) {
if (useScreen === void 0) { useScreen = false; }
if (!useScreen && this._currentRenderTarget) {
return this._currentRenderTarget.width;
}
return this._options.renderWidth;
};
NullEngine.prototype.getRenderHeight = function (useScreen) {
if (useScreen === void 0) { useScreen = false; }
if (!useScreen && this._currentRenderTarget) {
return this._currentRenderTarget.height;
}
return this._options.renderHeight;
};
NullEngine.prototype.setViewport = function (viewport, requiredWidth, requiredHeight) {
this._cachedViewport = viewport;
};
NullEngine.prototype.createShaderProgram = function (vertexCode, fragmentCode, defines, context) {
return {
transformFeedback: null,
__SPECTOR_rebuildProgram: null
};
};
NullEngine.prototype.getUniforms = function (shaderProgram, uniformsNames) {
return [];
};
NullEngine.prototype.getAttributes = function (shaderProgram, attributesNames) {
return [];
};
NullEngine.prototype.bindSamplers = function (effect) {
this._currentEffect = null;
};
NullEngine.prototype.enableEffect = function (effect) {
this._currentEffect = effect;
if (effect.onBind) {
effect.onBind(effect);
}
effect.onBindObservable.notifyObservers(effect);
};
NullEngine.prototype.setState = function (culling, zOffset, force, reverseSide) {
if (zOffset === void 0) { zOffset = 0; }
if (reverseSide === void 0) { reverseSide = false; }
};
NullEngine.prototype.setIntArray = function (uniform, array) {
};
NullEngine.prototype.setIntArray2 = function (uniform, array) {
};
NullEngine.prototype.setIntArray3 = function (uniform, array) {
};
NullEngine.prototype.setIntArray4 = function (uniform, array) {
};
NullEngine.prototype.setFloatArray = function (uniform, array) {
};
NullEngine.prototype.setFloatArray2 = function (uniform, array) {
};
NullEngine.prototype.setFloatArray3 = function (uniform, array) {
};
NullEngine.prototype.setFloatArray4 = function (uniform, array) {
};
NullEngine.prototype.setArray = function (uniform, array) {
};
NullEngine.prototype.setArray2 = function (uniform, array) {
};
NullEngine.prototype.setArray3 = function (uniform, array) {
};
NullEngine.prototype.setArray4 = function (uniform, array) {
};
NullEngine.prototype.setMatrices = function (uniform, matrices) {
};
NullEngine.prototype.setMatrix = function (uniform, matrix) {
};
NullEngine.prototype.setMatrix3x3 = function (uniform, matrix) {
};
NullEngine.prototype.setMatrix2x2 = function (uniform, matrix) {
};
NullEngine.prototype.setFloat = function (uniform, value) {
};
NullEngine.prototype.setFloat2 = function (uniform, x, y) {
};
NullEngine.prototype.setFloat3 = function (uniform, x, y, z) {
};
NullEngine.prototype.setBool = function (uniform, bool) {
};
NullEngine.prototype.setFloat4 = function (uniform, x, y, z, w) {
};
NullEngine.prototype.setColor3 = function (uniform, color3) {
};
NullEngine.prototype.setColor4 = function (uniform, color3, alpha) {
};
NullEngine.prototype.setAlphaMode = function (mode, noDepthWriteChange) {
if (noDepthWriteChange === void 0) { noDepthWriteChange = false; }
if (this._alphaMode === mode) {
return;
}
this._alphaState.alphaBlend = (mode !== BABYLON.Engine.ALPHA_DISABLE);
if (!noDepthWriteChange) {
this.setDepthWrite(mode === BABYLON.Engine.ALPHA_DISABLE);
}
this._alphaMode = mode;
};
NullEngine.prototype.bindBuffers = function (vertexBuffers, indexBuffer, effect) {
};
NullEngine.prototype.wipeCaches = function (bruteForce) {
if (this.preventCacheWipeBetweenFrames) {
return;
}
this.resetTextureCache();
this._currentEffect = null;
if (bruteForce) {
this._currentProgram = null;
this._stencilState.reset();
this._depthCullingState.reset();
this._alphaState.reset();
}
this._cachedVertexBuffers = null;
this._cachedIndexBuffer = null;
this._cachedEffectForVertexBuffers = null;
};
NullEngine.prototype.draw = function (useTriangles, indexStart, indexCount, instancesCount) {
};
NullEngine.prototype.drawElementsType = function (fillMode, indexStart, indexCount, instancesCount) {
};
NullEngine.prototype.drawArraysType = function (fillMode, verticesStart, verticesCount, instancesCount) {
};
NullEngine.prototype._createTexture = function () {
return {};
};
NullEngine.prototype._releaseTexture = function (texture) {
};
NullEngine.prototype.createTexture = function (urlArg, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallBack, format) {
if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
if (onLoad === void 0) { onLoad = null; }
if (onError === void 0) { onError = null; }
if (buffer === void 0) { buffer = null; }
var texture = new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_URL);
var url = String(urlArg);
texture.url = url;
texture.generateMipMaps = !noMipmap;
texture.samplingMode = samplingMode;
texture.invertY = invertY;
texture.baseWidth = this._options.textureSize;
texture.baseHeight = this._options.textureSize;
texture.width = this._options.textureSize;
texture.height = this._options.textureSize;
if (format) {
texture.format = format;
}
texture.isReady = true;
if (onLoad) {
onLoad();
}
return texture;
};
NullEngine.prototype.createRenderTargetTexture = function (size, options) {
var fullOptions = new BABYLON.RenderTargetCreationOptions();
if (options !== undefined && typeof options === "object") {
fullOptions.generateMipMaps = options.generateMipMaps;
fullOptions.generateDepthBuffer = options.generateDepthBuffer === undefined ? true : options.generateDepthBuffer;
fullOptions.generateStencilBuffer = fullOptions.generateDepthBuffer && options.generateStencilBuffer;
fullOptions.type = options.type === undefined ? BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT : options.type;
fullOptions.samplingMode = options.samplingMode === undefined ? BABYLON.Texture.TRILINEAR_SAMPLINGMODE : options.samplingMode;
}
else {
fullOptions.generateMipMaps = options;
fullOptions.generateDepthBuffer = true;
fullOptions.generateStencilBuffer = false;
fullOptions.type = BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
fullOptions.samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE;
}
var texture = new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_RENDERTARGET);
var width = size.width || size;
var height = size.height || size;
texture._depthStencilBuffer = {};
texture._framebuffer = {};
texture.baseWidth = width;
texture.baseHeight = height;
texture.width = width;
texture.height = height;
texture.isReady = true;
texture.samples = 1;
texture.generateMipMaps = fullOptions.generateMipMaps ? true : false;
texture.samplingMode = fullOptions.samplingMode;
texture.type = fullOptions.type;
texture._generateDepthBuffer = fullOptions.generateDepthBuffer;
texture._generateStencilBuffer = fullOptions.generateStencilBuffer ? true : false;
return texture;
};
NullEngine.prototype.updateTextureSamplingMode = function (samplingMode, texture) {
texture.samplingMode = samplingMode;
};
NullEngine.prototype.bindFramebuffer = function (texture, faceIndex, requiredWidth, requiredHeight, forceFullscreenViewport) {
if (this._currentRenderTarget) {
this.unBindFramebuffer(this._currentRenderTarget);
}
this._currentRenderTarget = texture;
this._currentFramebuffer = texture._MSAAFramebuffer ? texture._MSAAFramebuffer : texture._framebuffer;
if (this._cachedViewport && !forceFullscreenViewport) {
this.setViewport(this._cachedViewport, requiredWidth, requiredHeight);
}
};
NullEngine.prototype.unBindFramebuffer = function (texture, disableGenerateMipMaps, onBeforeUnbind) {
if (disableGenerateMipMaps === void 0) { disableGenerateMipMaps = false; }
this._currentRenderTarget = null;
if (onBeforeUnbind) {
if (texture._MSAAFramebuffer) {
this._currentFramebuffer = texture._framebuffer;
}
onBeforeUnbind();
}
this._currentFramebuffer = null;
};
NullEngine.prototype.createDynamicVertexBuffer = function (vertices) {
var vbo = {
capacity: 1,
references: 1,
is32Bits: false
};
return vbo;
};
NullEngine.prototype.updateDynamicIndexBuffer = function (indexBuffer, indices, offset) {
if (offset === void 0) { offset = 0; }
};
/**
* Updates a dynamic vertex buffer.
* @param vertexBuffer the vertex buffer to update
* @param data the data used to update the vertex buffer
* @param byteOffset the byte offset of the data (optional)
* @param byteLength the byte length of the data (optional)
*/
NullEngine.prototype.updateDynamicVertexBuffer = function (vertexBuffer, vertices, byteOffset, byteLength) {
};
NullEngine.prototype._bindTextureDirectly = function (target, texture) {
if (this._boundTexturesCache[this._activeChannel] !== texture) {
this._boundTexturesCache[this._activeChannel] = texture;
}
};
NullEngine.prototype._bindTexture = function (channel, texture) {
if (channel < 0) {
return;
}
this._bindTextureDirectly(0, texture);
};
NullEngine.prototype._releaseBuffer = function (buffer) {
buffer.references--;
if (buffer.references === 0) {
return true;
}
return false;
};
NullEngine.prototype.releaseEffects = function () {
};
return NullEngine;
}(BABYLON.Engine));
BABYLON.NullEngine = NullEngine;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.nullEngine.js.map
var BABYLON;
(function (BABYLON) {
/**
* This class can be used to get instrumentation data from a Babylon engine
*/
var EngineInstrumentation = /** @class */ (function () {
function EngineInstrumentation(engine) {
this.engine = engine;
this._captureGPUFrameTime = false;
this._gpuFrameTime = new BABYLON.PerfCounter();
this._captureShaderCompilationTime = false;
this._shaderCompilationTime = new BABYLON.PerfCounter();
// Observers
this._onBeginFrameObserver = null;
this._onEndFrameObserver = null;
this._onBeforeShaderCompilationObserver = null;
this._onAfterShaderCompilationObserver = null;
}
Object.defineProperty(EngineInstrumentation.prototype, "gpuFrameTimeCounter", {
// Properties
/**
* Gets the perf counter used for GPU frame time
*/
get: function () {
return this._gpuFrameTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EngineInstrumentation.prototype, "captureGPUFrameTime", {
/**
* Gets the GPU frame time capture status
*/
get: function () {
return this._captureGPUFrameTime;
},
/**
* Enable or disable the GPU frame time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureGPUFrameTime) {
return;
}
this._captureGPUFrameTime = value;
if (value) {
this._onBeginFrameObserver = this.engine.onBeginFrameObservable.add(function () {
if (!_this._gpuFrameTimeToken) {
_this._gpuFrameTimeToken = _this.engine.startTimeQuery();
}
});
this._onEndFrameObserver = this.engine.onEndFrameObservable.add(function () {
if (!_this._gpuFrameTimeToken) {
return;
}
var time = _this.engine.endTimeQuery(_this._gpuFrameTimeToken);
if (time > -1) {
_this._gpuFrameTimeToken = null;
_this._gpuFrameTime.fetchNewFrame();
_this._gpuFrameTime.addCount(time, true);
}
});
}
else {
this.engine.onBeginFrameObservable.remove(this._onBeginFrameObserver);
this._onBeginFrameObserver = null;
this.engine.onEndFrameObservable.remove(this._onEndFrameObserver);
this._onEndFrameObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(EngineInstrumentation.prototype, "shaderCompilationTimeCounter", {
/**
* Gets the perf counter used for shader compilation time
*/
get: function () {
return this._shaderCompilationTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EngineInstrumentation.prototype, "captureShaderCompilationTime", {
/**
* Gets the shader compilation time capture status
*/
get: function () {
return this._captureShaderCompilationTime;
},
/**
* Enable or disable the shader compilation time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureShaderCompilationTime) {
return;
}
this._captureShaderCompilationTime = value;
if (value) {
this._onBeforeShaderCompilationObserver = this.engine.onBeforeShaderCompilationObservable.add(function () {
_this._shaderCompilationTime.fetchNewFrame();
_this._shaderCompilationTime.beginMonitoring();
});
this._onAfterShaderCompilationObserver = this.engine.onAfterShaderCompilationObservable.add(function () {
_this._shaderCompilationTime.endMonitoring();
});
}
else {
this.engine.onBeforeShaderCompilationObservable.remove(this._onBeforeShaderCompilationObserver);
this._onBeforeShaderCompilationObserver = null;
this.engine.onAfterShaderCompilationObservable.remove(this._onAfterShaderCompilationObserver);
this._onAfterShaderCompilationObserver = null;
}
},
enumerable: true,
configurable: true
});
EngineInstrumentation.prototype.dispose = function () {
this.engine.onBeginFrameObservable.remove(this._onBeginFrameObserver);
this._onBeginFrameObserver = null;
this.engine.onEndFrameObservable.remove(this._onEndFrameObserver);
this._onEndFrameObserver = null;
this.engine.onBeforeShaderCompilationObservable.remove(this._onBeforeShaderCompilationObserver);
this._onBeforeShaderCompilationObserver = null;
this.engine.onAfterShaderCompilationObservable.remove(this._onAfterShaderCompilationObserver);
this._onAfterShaderCompilationObserver = null;
this.engine = null;
};
return EngineInstrumentation;
}());
BABYLON.EngineInstrumentation = EngineInstrumentation;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.engineInstrumentation.js.map
var BABYLON;
(function (BABYLON) {
/**
* This class can be used to get instrumentation data from a Babylon engine
*/
var SceneInstrumentation = /** @class */ (function () {
function SceneInstrumentation(scene) {
var _this = this;
this.scene = scene;
this._captureActiveMeshesEvaluationTime = false;
this._activeMeshesEvaluationTime = new BABYLON.PerfCounter();
this._captureRenderTargetsRenderTime = false;
this._renderTargetsRenderTime = new BABYLON.PerfCounter();
this._captureFrameTime = false;
this._frameTime = new BABYLON.PerfCounter();
this._captureRenderTime = false;
this._renderTime = new BABYLON.PerfCounter();
this._captureInterFrameTime = false;
this._interFrameTime = new BABYLON.PerfCounter();
this._captureParticlesRenderTime = false;
this._particlesRenderTime = new BABYLON.PerfCounter();
this._captureSpritesRenderTime = false;
this._spritesRenderTime = new BABYLON.PerfCounter();
this._capturePhysicsTime = false;
this._physicsTime = new BABYLON.PerfCounter();
this._captureAnimationsTime = false;
this._animationsTime = new BABYLON.PerfCounter();
// Observers
this._onBeforeActiveMeshesEvaluationObserver = null;
this._onAfterActiveMeshesEvaluationObserver = null;
this._onBeforeRenderTargetsRenderObserver = null;
this._onAfterRenderTargetsRenderObserver = null;
this._onAfterRenderObserver = null;
this._onBeforeDrawPhaseObserver = null;
this._onAfterDrawPhaseObserver = null;
this._onBeforeAnimationsObserver = null;
this._onBeforeParticlesRenderingObserver = null;
this._onAfterParticlesRenderingObserver = null;
this._onBeforeSpritesRenderingObserver = null;
this._onAfterSpritesRenderingObserver = null;
this._onBeforePhysicsObserver = null;
this._onAfterPhysicsObserver = null;
this._onAfterAnimationsObserver = null;
// Before render
this._onBeforeAnimationsObserver = scene.onBeforeAnimationsObservable.add(function () {
if (_this._captureActiveMeshesEvaluationTime) {
_this._activeMeshesEvaluationTime.fetchNewFrame();
}
if (_this._captureRenderTargetsRenderTime) {
_this._renderTargetsRenderTime.fetchNewFrame();
}
if (_this._captureFrameTime) {
BABYLON.Tools.StartPerformanceCounter("Scene rendering");
_this._frameTime.beginMonitoring();
}
if (_this._captureInterFrameTime) {
_this._interFrameTime.endMonitoring();
}
if (_this._captureParticlesRenderTime) {
_this._particlesRenderTime.fetchNewFrame();
}
if (_this._captureSpritesRenderTime) {
_this._spritesRenderTime.fetchNewFrame();
}
if (_this._captureAnimationsTime) {
_this._animationsTime.beginMonitoring();
}
_this.scene.getEngine()._drawCalls.fetchNewFrame();
_this.scene.getEngine()._textureCollisions.fetchNewFrame();
});
// After render
this._onAfterRenderObserver = scene.onAfterRenderObservable.add(function () {
if (_this._captureFrameTime) {
BABYLON.Tools.EndPerformanceCounter("Scene rendering");
_this._frameTime.endMonitoring();
}
if (_this._captureRenderTime) {
_this._renderTime.endMonitoring(false);
}
if (_this._captureInterFrameTime) {
_this._interFrameTime.beginMonitoring();
}
});
}
Object.defineProperty(SceneInstrumentation.prototype, "activeMeshesEvaluationTimeCounter", {
// Properties
/**
* Gets the perf counter used for active meshes evaluation time
*/
get: function () {
return this._activeMeshesEvaluationTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureActiveMeshesEvaluationTime", {
/**
* Gets the active meshes evaluation time capture status
*/
get: function () {
return this._captureActiveMeshesEvaluationTime;
},
/**
* Enable or disable the active meshes evaluation time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureActiveMeshesEvaluationTime) {
return;
}
this._captureActiveMeshesEvaluationTime = value;
if (value) {
this._onBeforeActiveMeshesEvaluationObserver = this.scene.onBeforeActiveMeshesEvaluationObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Active meshes evaluation");
_this._activeMeshesEvaluationTime.beginMonitoring();
});
this._onAfterActiveMeshesEvaluationObserver = this.scene.onAfterActiveMeshesEvaluationObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Active meshes evaluation");
_this._activeMeshesEvaluationTime.endMonitoring();
});
}
else {
this.scene.onBeforeActiveMeshesEvaluationObservable.remove(this._onBeforeActiveMeshesEvaluationObserver);
this._onBeforeActiveMeshesEvaluationObserver = null;
this.scene.onAfterActiveMeshesEvaluationObservable.remove(this._onAfterActiveMeshesEvaluationObserver);
this._onAfterActiveMeshesEvaluationObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "renderTargetsRenderTimeCounter", {
/**
* Gets the perf counter used for render targets render time
*/
get: function () {
return this._renderTargetsRenderTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureRenderTargetsRenderTime", {
/**
* Gets the render targets render time capture status
*/
get: function () {
return this._captureRenderTargetsRenderTime;
},
/**
* Enable or disable the render targets render time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureRenderTargetsRenderTime) {
return;
}
this._captureRenderTargetsRenderTime = value;
if (value) {
this._onBeforeRenderTargetsRenderObserver = this.scene.onBeforeRenderTargetsRenderObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Render targets rendering");
_this._renderTargetsRenderTime.beginMonitoring();
});
this._onAfterRenderTargetsRenderObserver = this.scene.onAfterRenderTargetsRenderObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Render targets rendering");
_this._renderTargetsRenderTime.endMonitoring(false);
});
}
else {
this.scene.onBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
this._onBeforeRenderTargetsRenderObserver = null;
this.scene.onAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
this._onAfterRenderTargetsRenderObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "particlesRenderTimeCounter", {
/**
* Gets the perf counter used for particles render time
*/
get: function () {
return this._particlesRenderTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureParticlesRenderTime", {
/**
* Gets the particles render time capture status
*/
get: function () {
return this._captureParticlesRenderTime;
},
/**
* Enable or disable the particles render time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureParticlesRenderTime) {
return;
}
this._captureParticlesRenderTime = value;
if (value) {
this._onBeforeParticlesRenderingObserver = this.scene.onBeforeParticlesRenderingObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Particles");
_this._particlesRenderTime.beginMonitoring();
});
this._onAfterParticlesRenderingObserver = this.scene.onAfterParticlesRenderingObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Particles");
_this._particlesRenderTime.endMonitoring(false);
});
}
else {
this.scene.onBeforeParticlesRenderingObservable.remove(this._onBeforeParticlesRenderingObserver);
this._onBeforeParticlesRenderingObserver = null;
this.scene.onAfterParticlesRenderingObservable.remove(this._onAfterParticlesRenderingObserver);
this._onAfterParticlesRenderingObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "spritesRenderTimeCounter", {
/**
* Gets the perf counter used for sprites render time
*/
get: function () {
return this._spritesRenderTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureSpritesRenderTime", {
/**
* Gets the sprites render time capture status
*/
get: function () {
return this._captureSpritesRenderTime;
},
/**
* Enable or disable the sprites render time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureSpritesRenderTime) {
return;
}
this._captureSpritesRenderTime = value;
if (value) {
this._onBeforeSpritesRenderingObserver = this.scene.onBeforeSpritesRenderingObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Sprites");
_this._spritesRenderTime.beginMonitoring();
});
this._onAfterSpritesRenderingObserver = this.scene.onAfterSpritesRenderingObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Sprites");
_this._spritesRenderTime.endMonitoring(false);
});
}
else {
this.scene.onBeforeSpritesRenderingObservable.remove(this._onBeforeSpritesRenderingObserver);
this._onBeforeSpritesRenderingObserver = null;
this.scene.onAfterSpritesRenderingObservable.remove(this._onAfterSpritesRenderingObserver);
this._onAfterSpritesRenderingObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "physicsTimeCounter", {
/**
* Gets the perf counter used for physics time
*/
get: function () {
return this._physicsTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "capturePhysicsTime", {
/**
* Gets the physics time capture status
*/
get: function () {
return this._capturePhysicsTime;
},
/**
* Enable or disable the physics time capture
*/
set: function (value) {
var _this = this;
if (value === this._capturePhysicsTime) {
return;
}
this._capturePhysicsTime = value;
if (value) {
this._onBeforePhysicsObserver = this.scene.onBeforePhysicsObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Physics");
_this._physicsTime.beginMonitoring();
});
this._onAfterPhysicsObserver = this.scene.onAfterPhysicsObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Physics");
_this._physicsTime.endMonitoring();
});
}
else {
this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
this._onBeforePhysicsObserver = null;
this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
this._onAfterPhysicsObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "animationsTimeCounter", {
/**
* Gets the perf counter used for animations time
*/
get: function () {
return this._animationsTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureAnimationsTime", {
/**
* Gets the animations time capture status
*/
get: function () {
return this._captureAnimationsTime;
},
/**
* Enable or disable the animations time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureAnimationsTime) {
return;
}
this._captureAnimationsTime = value;
if (value) {
this._onAfterAnimationsObserver = this.scene.onAfterAnimationsObservable.add(function () {
_this._animationsTime.endMonitoring();
});
}
else {
this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
this._onAfterAnimationsObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "frameTimeCounter", {
/**
* Gets the perf counter used for frame time capture
*/
get: function () {
return this._frameTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureFrameTime", {
/**
* Gets the frame time capture status
*/
get: function () {
return this._captureFrameTime;
},
/**
* Enable or disable the frame time capture
*/
set: function (value) {
this._captureFrameTime = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "interFrameTimeCounter", {
/**
* Gets the perf counter used for inter-frames time capture
*/
get: function () {
return this._interFrameTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureInterFrameTime", {
/**
* Gets the inter-frames time capture status
*/
get: function () {
return this._captureInterFrameTime;
},
/**
* Enable or disable the inter-frames time capture
*/
set: function (value) {
this._captureInterFrameTime = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "renderTimeCounter", {
/**
* Gets the perf counter used for render time capture
*/
get: function () {
return this._renderTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureRenderTime", {
/**
* Gets the render time capture status
*/
get: function () {
return this._captureRenderTime;
},
/**
* Enable or disable the render time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureRenderTime) {
return;
}
this._captureRenderTime = value;
if (value) {
this._onBeforeDrawPhaseObserver = this.scene.onBeforeDrawPhaseObservable.add(function () {
_this._renderTime.beginMonitoring();
BABYLON.Tools.StartPerformanceCounter("Main render");
});
this._onAfterDrawPhaseObserver = this.scene.onAfterDrawPhaseObservable.add(function () {
_this._renderTime.endMonitoring(false);
BABYLON.Tools.EndPerformanceCounter("Main render");
});
}
else {
this.scene.onBeforeDrawPhaseObservable.remove(this._onBeforeDrawPhaseObserver);
this._onBeforeDrawPhaseObserver = null;
this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
this._onAfterDrawPhaseObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "drawCallsCounter", {
/**
* Gets the perf counter used for draw calls
*/
get: function () {
return this.scene.getEngine()._drawCalls;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "textureCollisionsCounter", {
/**
* Gets the perf counter used for texture collisions
*/
get: function () {
return this.scene.getEngine()._textureCollisions;
},
enumerable: true,
configurable: true
});
SceneInstrumentation.prototype.dispose = function () {
this.scene.onAfterRenderObservable.remove(this._onAfterRenderObserver);
this._onAfterRenderObserver = null;
this.scene.onBeforeActiveMeshesEvaluationObservable.remove(this._onBeforeActiveMeshesEvaluationObserver);
this._onBeforeActiveMeshesEvaluationObserver = null;
this.scene.onAfterActiveMeshesEvaluationObservable.remove(this._onAfterActiveMeshesEvaluationObserver);
this._onAfterActiveMeshesEvaluationObserver = null;
this.scene.onBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
this._onBeforeRenderTargetsRenderObserver = null;
this.scene.onAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
this._onAfterRenderTargetsRenderObserver = null;
this.scene.onBeforeAnimationsObservable.remove(this._onBeforeAnimationsObserver);
this._onBeforeAnimationsObserver = null;
this.scene.onBeforeParticlesRenderingObservable.remove(this._onBeforeParticlesRenderingObserver);
this._onBeforeParticlesRenderingObserver = null;
this.scene.onAfterParticlesRenderingObservable.remove(this._onAfterParticlesRenderingObserver);
this._onAfterParticlesRenderingObserver = null;
this.scene.onBeforeSpritesRenderingObservable.remove(this._onBeforeSpritesRenderingObserver);
this._onBeforeSpritesRenderingObserver = null;
this.scene.onAfterSpritesRenderingObservable.remove(this._onAfterSpritesRenderingObserver);
this._onAfterSpritesRenderingObserver = null;
this.scene.onBeforeDrawPhaseObservable.remove(this._onBeforeDrawPhaseObserver);
this._onBeforeDrawPhaseObserver = null;
this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
this._onAfterDrawPhaseObserver = null;
this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
this._onBeforePhysicsObserver = null;
this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
this._onAfterPhysicsObserver = null;
this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
this._onAfterAnimationsObserver = null;
this.scene = null;
};
return SceneInstrumentation;
}());
BABYLON.SceneInstrumentation = SceneInstrumentation;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.sceneInstrumentation.js.map
var BABYLON;
(function (BABYLON) {
/**
* @hidden
**/
var _TimeToken = /** @class */ (function () {
function _TimeToken() {
this._timeElapsedQueryEnded = false;
}
return _TimeToken;
}());
BABYLON._TimeToken = _TimeToken;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.timeToken.js.map
var BABYLON;
(function (BABYLON) {
/**
* Background material defines definition.
* @hidden Mainly internal Use
*/
var BackgroundMaterialDefines = /** @class */ (function (_super) {
__extends(BackgroundMaterialDefines, _super);
/**
* Constructor of the defines.
*/
function BackgroundMaterialDefines() {
var _this = _super.call(this) || this;
/**
* True if the diffuse texture is in use.
*/
_this.DIFFUSE = false;
/**
* The direct UV channel to use.
*/
_this.DIFFUSEDIRECTUV = 0;
/**
* True if the diffuse texture is in gamma space.
*/
_this.GAMMADIFFUSE = false;
/**
* True if the diffuse texture has opacity in the alpha channel.
*/
_this.DIFFUSEHASALPHA = false;
/**
* True if you want the material to fade to transparent at grazing angle.
*/
_this.OPACITYFRESNEL = false;
/**
* True if an extra blur needs to be added in the reflection.
*/
_this.REFLECTIONBLUR = false;
/**
* True if you want the material to fade to reflection at grazing angle.
*/
_this.REFLECTIONFRESNEL = false;
/**
* True if you want the material to falloff as far as you move away from the scene center.
*/
_this.REFLECTIONFALLOFF = false;
/**
* False if the current Webgl implementation does not support the texture lod extension.
*/
_this.TEXTURELODSUPPORT = false;
/**
* True to ensure the data are premultiplied.
*/
_this.PREMULTIPLYALPHA = false;
/**
* True if the texture contains cooked RGB values and not gray scaled multipliers.
*/
_this.USERGBCOLOR = false;
/**
* True if highlight and shadow levels have been specified. It can help ensuring the main perceived color
* stays aligned with the desired configuration.
*/
_this.USEHIGHLIGHTANDSHADOWCOLORS = false;
/**
* True to add noise in order to reduce the banding effect.
*/
_this.NOISE = false;
/**
* is the reflection texture in BGR color scheme?
* Mainly used to solve a bug in ios10 video tag
*/
_this.REFLECTIONBGR = false;
_this.IMAGEPROCESSING = false;
_this.VIGNETTE = false;
_this.VIGNETTEBLENDMODEMULTIPLY = false;
_this.VIGNETTEBLENDMODEOPAQUE = false;
_this.TONEMAPPING = false;
_this.CONTRAST = false;
_this.COLORCURVES = false;
_this.COLORGRADING = false;
_this.COLORGRADING3D = false;
_this.SAMPLER3DGREENDEPTH = false;
_this.SAMPLER3DBGRMAP = false;
_this.IMAGEPROCESSINGPOSTPROCESS = false;
_this.EXPOSURE = false;
// Reflection.
_this.REFLECTION = false;
_this.REFLECTIONMAP_3D = false;
_this.REFLECTIONMAP_SPHERICAL = false;
_this.REFLECTIONMAP_PLANAR = false;
_this.REFLECTIONMAP_CUBIC = false;
_this.REFLECTIONMAP_PROJECTION = false;
_this.REFLECTIONMAP_SKYBOX = false;
_this.REFLECTIONMAP_EXPLICIT = false;
_this.REFLECTIONMAP_EQUIRECTANGULAR = false;
_this.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
_this.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
_this.INVERTCUBICMAP = false;
_this.REFLECTIONMAP_OPPOSITEZ = false;
_this.LODINREFLECTIONALPHA = false;
_this.GAMMAREFLECTION = false;
_this.EQUIRECTANGULAR_RELFECTION_FOV = false;
// Default BJS.
_this.MAINUV1 = false;
_this.MAINUV2 = false;
_this.UV1 = false;
_this.UV2 = false;
_this.CLIPPLANE = false;
_this.POINTSIZE = false;
_this.FOG = false;
_this.NORMAL = false;
_this.NUM_BONE_INFLUENCERS = 0;
_this.BonesPerMesh = 0;
_this.INSTANCES = false;
_this.SHADOWFLOAT = false;
_this.rebuild();
return _this;
}
return BackgroundMaterialDefines;
}(BABYLON.MaterialDefines));
/**
* Background material used to create an efficient environement around your scene.
*/
var BackgroundMaterial = /** @class */ (function (_super) {
__extends(BackgroundMaterial, _super);
/**
* Instantiates a Background Material in the given scene
* @param name The friendly name of the material
* @param scene The scene to add the material to
*/
function BackgroundMaterial(name, scene) {
var _this = _super.call(this, name, scene) || this;
/**
* Key light Color (multiply against the environement texture)
*/
_this.primaryColor = BABYLON.Color3.White();
_this._primaryColorShadowLevel = 0;
_this._primaryColorHighlightLevel = 0;
/**
* Reflection Texture used in the material.
* Should be author in a specific way for the best result (refer to the documentation).
*/
_this.reflectionTexture = null;
/**
* Reflection Texture level of blur.
*
* Can be use to reuse an existing HDR Texture and target a specific LOD to prevent authoring the
* texture twice.
*/
_this.reflectionBlur = 0;
/**
* Diffuse Texture used in the material.
* Should be author in a specific way for the best result (refer to the documentation).
*/
_this.diffuseTexture = null;
_this._shadowLights = null;
/**
* Specify the list of lights casting shadow on the material.
* All scene shadow lights will be included if null.
*/
_this.shadowLights = null;
/**
* Helps adjusting the shadow to a softer level if required.
* 0 means black shadows and 1 means no shadows.
*/
_this.shadowLevel = 0;
/**
* In case of opacity Fresnel or reflection falloff, this is use as a scene center.
* It is usually zero but might be interesting to modify according to your setup.
*/
_this.sceneCenter = BABYLON.Vector3.Zero();
/**
* This helps specifying that the material is falling off to the sky box at grazing angle.
* This helps ensuring a nice transition when the camera goes under the ground.
*/
_this.opacityFresnel = true;
/**
* This helps specifying that the material is falling off from diffuse to the reflection texture at grazing angle.
* This helps adding a mirror texture on the ground.
*/
_this.reflectionFresnel = false;
/**
* This helps specifying the falloff radius off the reflection texture from the sceneCenter.
* This helps adding a nice falloff effect to the reflection if used as a mirror for instance.
*/
_this.reflectionFalloffDistance = 0.0;
/**
* This specifies the weight of the reflection against the background in case of reflection Fresnel.
*/
_this.reflectionAmount = 1.0;
/**
* This specifies the weight of the reflection at grazing angle.
*/
_this.reflectionReflectance0 = 0.05;
/**
* This specifies the weight of the reflection at a perpendicular point of view.
*/
_this.reflectionReflectance90 = 0.5;
/**
* Helps to directly use the maps channels instead of their level.
*/
_this.useRGBColor = true;
/**
* This helps reducing the banding effect that could occur on the background.
*/
_this.enableNoise = false;
_this._fovMultiplier = 1.0;
/**
* Enable the FOV adjustment feature controlled by fovMultiplier.
*/
_this.useEquirectangularFOV = false;
_this._maxSimultaneousLights = 4;
/**
* Number of Simultaneous lights allowed on the material.
*/
_this.maxSimultaneousLights = 4;
/**
* Keep track of the image processing observer to allow dispose and replace.
*/
_this._imageProcessingObserver = null;
/**
* Due to a bug in iOS10, video tags (which are using the background material) are in BGR and not RGB.
* Setting this flag to true (not done automatically!) will convert it back to RGB.
*/
_this.switchToBGR = false;
// Temp values kept as cache in the material.
_this._renderTargets = new BABYLON.SmartArray(16);
_this._reflectionControls = BABYLON.Vector4.Zero();
_this._white = BABYLON.Color3.White();
_this._primaryShadowColor = BABYLON.Color3.Black();
_this._primaryHighlightColor = BABYLON.Color3.Black();
// Setup the default processing configuration to the scene.
_this._attachImageProcessingConfiguration(null);
_this.getRenderTargetTextures = function () {
_this._renderTargets.reset();
if (_this._diffuseTexture && _this._diffuseTexture.isRenderTarget) {
_this._renderTargets.push(_this._diffuseTexture);
}
if (_this._reflectionTexture && _this._reflectionTexture.isRenderTarget) {
_this._renderTargets.push(_this._reflectionTexture);
}
return _this._renderTargets;
};
return _this;
}
Object.defineProperty(BackgroundMaterial.prototype, "_perceptualColor", {
/**
* Experimental Internal Use Only.
*
* Key light Color in "perceptual value" meaning the color you would like to see on screen.
* This acts as a helper to set the primary color to a more "human friendly" value.
* Conversion to linear space as well as exposure and tone mapping correction will be applied to keep the
* output color as close as possible from the chosen value.
* (This does not account for contrast color grading and color curves as they are considered post effect and not directly
* part of lighting setup.)
*/
get: function () {
return this.__perceptualColor;
},
set: function (value) {
this.__perceptualColor = value;
this._computePrimaryColorFromPerceptualColor();
this._markAllSubMeshesAsLightsDirty();
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "primaryColorShadowLevel", {
/**
* Defines the level of the shadows (dark area of the reflection map) in order to help scaling the colors.
* The color opposite to the primary color is used at the level chosen to define what the black area would look.
*/
get: function () {
return this._primaryColorShadowLevel;
},
set: function (value) {
this._primaryColorShadowLevel = value;
this._computePrimaryColors();
this._markAllSubMeshesAsLightsDirty();
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "primaryColorHighlightLevel", {
/**
* Defines the level of the highliights (highlight area of the reflection map) in order to help scaling the colors.
* The primary color is used at the level chosen to define what the white area would look.
*/
get: function () {
return this._primaryColorHighlightLevel;
},
set: function (value) {
this._primaryColorHighlightLevel = value;
this._computePrimaryColors();
this._markAllSubMeshesAsLightsDirty();
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "reflectionStandardFresnelWeight", {
/**
* Sets the reflection reflectance fresnel values according to the default standard
* empirically know to work well :-)
*/
set: function (value) {
var reflectionWeight = value;
if (reflectionWeight < 0.5) {
reflectionWeight = reflectionWeight * 2.0;
this.reflectionReflectance0 = BackgroundMaterial.StandardReflectance0 * reflectionWeight;
this.reflectionReflectance90 = BackgroundMaterial.StandardReflectance90 * reflectionWeight;
}
else {
reflectionWeight = reflectionWeight * 2.0 - 1.0;
this.reflectionReflectance0 = BackgroundMaterial.StandardReflectance0 + (1.0 - BackgroundMaterial.StandardReflectance0) * reflectionWeight;
this.reflectionReflectance90 = BackgroundMaterial.StandardReflectance90 + (1.0 - BackgroundMaterial.StandardReflectance90) * reflectionWeight;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "fovMultiplier", {
/**
* The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
* Best used when trying to implement visual zoom effects like fish-eye or binoculars while not adjusting camera fov.
* Recommended to be keep at 1.0 except for special cases.
*/
get: function () {
return this._fovMultiplier;
},
set: function (value) {
if (isNaN(value)) {
value = 1.0;
}
this._fovMultiplier = Math.max(0.0, Math.min(2.0, value));
},
enumerable: true,
configurable: true
});
/**
* Attaches a new image processing configuration to the PBR Material.
* @param configuration (if null the scene configuration will be use)
*/
BackgroundMaterial.prototype._attachImageProcessingConfiguration = function (configuration) {
var _this = this;
if (configuration === this._imageProcessingConfiguration) {
return;
}
// Detaches observer.
if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
}
// Pick the scene configuration if needed.
if (!configuration) {
this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration;
}
else {
this._imageProcessingConfiguration = configuration;
}
// Attaches observer.
this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(function (conf) {
_this._computePrimaryColorFromPerceptualColor();
_this._markAllSubMeshesAsImageProcessingDirty();
});
};
Object.defineProperty(BackgroundMaterial.prototype, "imageProcessingConfiguration", {
/**
* Gets the image processing configuration used either in this material.
*/
get: function () {
return this._imageProcessingConfiguration;
},
/**
* Sets the Default image processing configuration used either in the this material.
*
* If sets to null, the scene one is in use.
*/
set: function (value) {
this._attachImageProcessingConfiguration(value);
// Ensure the effect will be rebuilt.
this._markAllSubMeshesAsTexturesDirty();
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraColorCurvesEnabled", {
/**
* Gets wether the color curves effect is enabled.
*/
get: function () {
return this.imageProcessingConfiguration.colorCurvesEnabled;
},
/**
* Sets wether the color curves effect is enabled.
*/
set: function (value) {
this.imageProcessingConfiguration.colorCurvesEnabled = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraColorGradingEnabled", {
/**
* Gets wether the color grading effect is enabled.
*/
get: function () {
return this.imageProcessingConfiguration.colorGradingEnabled;
},
/**
* Gets wether the color grading effect is enabled.
*/
set: function (value) {
this.imageProcessingConfiguration.colorGradingEnabled = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraToneMappingEnabled", {
/**
* Gets wether tonemapping is enabled or not.
*/
get: function () {
return this._imageProcessingConfiguration.toneMappingEnabled;
},
/**
* Sets wether tonemapping is enabled or not
*/
set: function (value) {
this._imageProcessingConfiguration.toneMappingEnabled = value;
},
enumerable: true,
configurable: true
});
;
;
Object.defineProperty(BackgroundMaterial.prototype, "cameraExposure", {
/**
* The camera exposure used on this material.
* This property is here and not in the camera to allow controlling exposure without full screen post process.
* This corresponds to a photographic exposure.
*/
get: function () {
return this._imageProcessingConfiguration.exposure;
},
/**
* The camera exposure used on this material.
* This property is here and not in the camera to allow controlling exposure without full screen post process.
* This corresponds to a photographic exposure.
*/
set: function (value) {
this._imageProcessingConfiguration.exposure = value;
},
enumerable: true,
configurable: true
});
;
;
Object.defineProperty(BackgroundMaterial.prototype, "cameraContrast", {
/**
* Gets The camera contrast used on this material.
*/
get: function () {
return this._imageProcessingConfiguration.contrast;
},
/**
* Sets The camera contrast used on this material.
*/
set: function (value) {
this._imageProcessingConfiguration.contrast = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraColorGradingTexture", {
/**
* Gets the Color Grading 2D Lookup Texture.
*/
get: function () {
return this._imageProcessingConfiguration.colorGradingTexture;
},
/**
* Sets the Color Grading 2D Lookup Texture.
*/
set: function (value) {
this.imageProcessingConfiguration.colorGradingTexture = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraColorCurves", {
/**
* The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
* They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
* These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
* corresponding to low luminance, medium luminance, and high luminance areas respectively.
*/
get: function () {
return this.imageProcessingConfiguration.colorCurves;
},
/**
* The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
* They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
* These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
* corresponding to low luminance, medium luminance, and high luminance areas respectively.
*/
set: function (value) {
this.imageProcessingConfiguration.colorCurves = value;
},
enumerable: true,
configurable: true
});
/**
* The entire material has been created in order to prevent overdraw.
* @returns false
*/
BackgroundMaterial.prototype.needAlphaTesting = function () {
return true;
};
/**
* The entire material has been created in order to prevent overdraw.
* @returns true if blending is enable
*/
BackgroundMaterial.prototype.needAlphaBlending = function () {
return ((this.alpha < 0) || (this._diffuseTexture != null && this._diffuseTexture.hasAlpha));
};
/**
* Checks wether the material is ready to be rendered for a given mesh.
* @param mesh The mesh to render
* @param subMesh The submesh to check against
* @param useInstances Specify wether or not the material is used with instances
* @returns true if all the dependencies are ready (Textures, Effects...)
*/
BackgroundMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
var _this = this;
if (useInstances === void 0) { useInstances = false; }
if (subMesh.effect && this.isFrozen) {
if (this._wasPreviouslyReady) {
return true;
}
}
if (!subMesh._materialDefines) {
subMesh._materialDefines = new BackgroundMaterialDefines();
}
var scene = this.getScene();
var defines = subMesh._materialDefines;
if (!this.checkReadyOnEveryCall && subMesh.effect) {
if (defines._renderId === scene.getRenderId()) {
return true;
}
}
var engine = scene.getEngine();
// Lights
BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights);
defines._needNormals = true;
// Textures
if (defines._areTexturesDirty) {
defines._needUVs = false;
if (scene.texturesEnabled) {
if (scene.getEngine().getCaps().textureLOD) {
defines.TEXTURELODSUPPORT = true;
}
if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
if (!this._diffuseTexture.isReadyOrNotBlocking()) {
return false;
}
BABYLON.MaterialHelper.PrepareDefinesForMergedUV(this._diffuseTexture, defines, "DIFFUSE");
defines.DIFFUSEHASALPHA = this._diffuseTexture.hasAlpha;
defines.GAMMADIFFUSE = this._diffuseTexture.gammaSpace;
defines.OPACITYFRESNEL = this._opacityFresnel;
}
else {
defines.DIFFUSE = false;
defines.DIFFUSEHASALPHA = false;
defines.GAMMADIFFUSE = false;
defines.OPACITYFRESNEL = false;
}
var reflectionTexture = this._reflectionTexture;
if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
if (!reflectionTexture.isReadyOrNotBlocking()) {
return false;
}
defines.REFLECTION = true;
defines.GAMMAREFLECTION = reflectionTexture.gammaSpace;
defines.REFLECTIONBLUR = this._reflectionBlur > 0;
defines.REFLECTIONMAP_OPPOSITEZ = this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ;
defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha;
defines.EQUIRECTANGULAR_RELFECTION_FOV = this.useEquirectangularFOV;
defines.REFLECTIONBGR = this.switchToBGR;
if (reflectionTexture.coordinatesMode === BABYLON.Texture.INVCUBIC_MODE) {
defines.INVERTCUBICMAP = true;
}
defines.REFLECTIONMAP_3D = reflectionTexture.isCube;
switch (reflectionTexture.coordinatesMode) {
case BABYLON.Texture.EXPLICIT_MODE:
defines.REFLECTIONMAP_EXPLICIT = true;
break;
case BABYLON.Texture.PLANAR_MODE:
defines.REFLECTIONMAP_PLANAR = true;
break;
case BABYLON.Texture.PROJECTION_MODE:
defines.REFLECTIONMAP_PROJECTION = true;
break;
case BABYLON.Texture.SKYBOX_MODE:
defines.REFLECTIONMAP_SKYBOX = true;
break;
case BABYLON.Texture.SPHERICAL_MODE:
defines.REFLECTIONMAP_SPHERICAL = true;
break;
case BABYLON.Texture.EQUIRECTANGULAR_MODE:
defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
break;
case BABYLON.Texture.FIXED_EQUIRECTANGULAR_MODE:
defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
break;
case BABYLON.Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE:
defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true;
break;
case BABYLON.Texture.CUBIC_MODE:
case BABYLON.Texture.INVCUBIC_MODE:
default:
defines.REFLECTIONMAP_CUBIC = true;
break;
}
if (this.reflectionFresnel) {
defines.REFLECTIONFRESNEL = true;
defines.REFLECTIONFALLOFF = this.reflectionFalloffDistance > 0;
this._reflectionControls.x = this.reflectionAmount;
this._reflectionControls.y = this.reflectionReflectance0;
this._reflectionControls.z = this.reflectionReflectance90;
this._reflectionControls.w = 1 / this.reflectionFalloffDistance;
}
else {
defines.REFLECTIONFRESNEL = false;
defines.REFLECTIONFALLOFF = false;
}
}
else {
defines.REFLECTION = false;
defines.REFLECTIONFRESNEL = false;
defines.REFLECTIONFALLOFF = false;
defines.REFLECTIONBLUR = false;
defines.REFLECTIONMAP_3D = false;
defines.REFLECTIONMAP_SPHERICAL = false;
defines.REFLECTIONMAP_PLANAR = false;
defines.REFLECTIONMAP_CUBIC = false;
defines.REFLECTIONMAP_PROJECTION = false;
defines.REFLECTIONMAP_SKYBOX = false;
defines.REFLECTIONMAP_EXPLICIT = false;
defines.REFLECTIONMAP_EQUIRECTANGULAR = false;
defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
defines.INVERTCUBICMAP = false;
defines.REFLECTIONMAP_OPPOSITEZ = false;
defines.LODINREFLECTIONALPHA = false;
defines.GAMMAREFLECTION = false;
}
}
defines.PREMULTIPLYALPHA = (this.alphaMode === BABYLON.Engine.ALPHA_PREMULTIPLIED || this.alphaMode === BABYLON.Engine.ALPHA_PREMULTIPLIED_PORTERDUFF);
defines.USERGBCOLOR = this._useRGBColor;
defines.NOISE = this._enableNoise;
}
if (defines._areLightsDirty) {
defines.USEHIGHLIGHTANDSHADOWCOLORS = !this._useRGBColor && (this._primaryColorShadowLevel !== 0 || this._primaryColorHighlightLevel !== 0);
}
if (defines._areImageProcessingDirty) {
if (!this._imageProcessingConfiguration.isReady()) {
return false;
}
this._imageProcessingConfiguration.prepareDefines(defines);
}
// Misc.
BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, this._shouldTurnAlphaTestOn(mesh), defines);
// Values that need to be evaluated on every frame
BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
// Attribs
if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {
if (mesh) {
if (!scene.getEngine().getCaps().standardDerivatives && !mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
mesh.createNormals(true);
BABYLON.Tools.Warn("BackgroundMaterial: Normals have been created for the mesh: " + mesh.name);
}
}
}
// Get correct effect
if (defines.isDirty) {
defines.markAsProcessed();
scene.resetCachedMaterial();
// Fallbacks
var fallbacks = new BABYLON.EffectFallbacks();
if (defines.FOG) {
fallbacks.addFallback(0, "FOG");
}
if (defines.POINTSIZE) {
fallbacks.addFallback(1, "POINTSIZE");
}
BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this._maxSimultaneousLights);
if (defines.NUM_BONE_INFLUENCERS > 0) {
fallbacks.addCPUSkinningFallback(0, mesh);
}
//Attributes
var attribs = [BABYLON.VertexBuffer.PositionKind];
if (defines.NORMAL) {
attribs.push(BABYLON.VertexBuffer.NormalKind);
}
if (defines.UV1) {
attribs.push(BABYLON.VertexBuffer.UVKind);
}
if (defines.UV2) {
attribs.push(BABYLON.VertexBuffer.UV2Kind);
}
BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType",
"vFogInfos", "vFogColor", "pointSize",
"vClipPlane", "mBones",
"vPrimaryColor", "vPrimaryColorShadow",
"vReflectionInfos", "reflectionMatrix", "vReflectionMicrosurfaceInfos", "fFovMultiplier",
"shadowLevel", "alpha",
"vBackgroundCenter", "vReflectionControl",
"vDiffuseInfos", "diffuseMatrix",
];
var samplers = ["diffuseSampler", "reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh"];
var uniformBuffers = ["Material", "Scene"];
BABYLON.ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
BABYLON.ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
BABYLON.MaterialHelper.PrepareUniformsAndSamplersList({
uniformsNames: uniforms,
uniformBuffersNames: uniformBuffers,
samplers: samplers,
defines: defines,
maxSimultaneousLights: this._maxSimultaneousLights
});
var onCompiled = function (effect) {
if (_this.onCompiled) {
_this.onCompiled(effect);
}
_this.bindSceneUniformBuffer(effect, scene.getSceneUniformBuffer());
};
var join = defines.toString();
subMesh.setEffect(scene.getEngine().createEffect("background", {
attributes: attribs,
uniformsNames: uniforms,
uniformBuffersNames: uniformBuffers,
samplers: samplers,
defines: join,
fallbacks: fallbacks,
onCompiled: onCompiled,
onError: this.onError,
indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights }
}, engine), defines);
this.buildUniformLayout();
}
if (!subMesh.effect || !subMesh.effect.isReady()) {
return false;
}
defines._renderId = scene.getRenderId();
this._wasPreviouslyReady = true;
return true;
};
/**
* Compute the primary color according to the chosen perceptual color.
*/
BackgroundMaterial.prototype._computePrimaryColorFromPerceptualColor = function () {
if (!this.__perceptualColor) {
return;
}
this._primaryColor.copyFrom(this.__perceptualColor);
// Revert gamma space.
this._primaryColor.toLinearSpaceToRef(this._primaryColor);
// Revert image processing configuration.
if (this._imageProcessingConfiguration) {
// Revert Exposure.
this._primaryColor.scaleToRef(1 / this._imageProcessingConfiguration.exposure, this._primaryColor);
}
this._computePrimaryColors();
};
/**
* Compute the highlights and shadow colors according to their chosen levels.
*/
BackgroundMaterial.prototype._computePrimaryColors = function () {
if (this._primaryColorShadowLevel === 0 && this._primaryColorHighlightLevel === 0) {
return;
}
// Find the highlight color based on the configuration.
this._primaryColor.scaleToRef(this._primaryColorShadowLevel, this._primaryShadowColor);
this._primaryColor.subtractToRef(this._primaryShadowColor, this._primaryShadowColor);
// Find the shadow color based on the configuration.
this._white.subtractToRef(this._primaryColor, this._primaryHighlightColor);
this._primaryHighlightColor.scaleToRef(this._primaryColorHighlightLevel, this._primaryHighlightColor);
this._primaryColor.addToRef(this._primaryHighlightColor, this._primaryHighlightColor);
};
/**
* Build the uniform buffer used in the material.
*/
BackgroundMaterial.prototype.buildUniformLayout = function () {
// Order is important !
this._uniformBuffer.addUniform("vPrimaryColor", 4);
this._uniformBuffer.addUniform("vPrimaryColorShadow", 4);
this._uniformBuffer.addUniform("vDiffuseInfos", 2);
this._uniformBuffer.addUniform("vReflectionInfos", 2);
this._uniformBuffer.addUniform("diffuseMatrix", 16);
this._uniformBuffer.addUniform("reflectionMatrix", 16);
this._uniformBuffer.addUniform("vReflectionMicrosurfaceInfos", 3);
this._uniformBuffer.addUniform("fFovMultiplier", 1);
this._uniformBuffer.addUniform("pointSize", 1);
this._uniformBuffer.addUniform("shadowLevel", 1);
this._uniformBuffer.addUniform("alpha", 1);
this._uniformBuffer.addUniform("vBackgroundCenter", 3);
this._uniformBuffer.addUniform("vReflectionControl", 4);
this._uniformBuffer.create();
};
/**
* Unbind the material.
*/
BackgroundMaterial.prototype.unbind = function () {
if (this._diffuseTexture && this._diffuseTexture.isRenderTarget) {
this._uniformBuffer.setTexture("diffuseSampler", null);
}
if (this._reflectionTexture && this._reflectionTexture.isRenderTarget) {
this._uniformBuffer.setTexture("reflectionSampler", null);
}
_super.prototype.unbind.call(this);
};
/**
* Bind only the world matrix to the material.
* @param world The world matrix to bind.
*/
BackgroundMaterial.prototype.bindOnlyWorldMatrix = function (world) {
this._activeEffect.setMatrix("world", world);
};
/**
* Bind the material for a dedicated submeh (every used meshes will be considered opaque).
* @param world The world matrix to bind.
* @param subMesh The submesh to bind for.
*/
BackgroundMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
var scene = this.getScene();
var defines = subMesh._materialDefines;
if (!defines) {
return;
}
var effect = subMesh.effect;
if (!effect) {
return;
}
this._activeEffect = effect;
// Matrices
this.bindOnlyWorldMatrix(world);
// Bones
BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
var mustRebind = this._mustRebind(scene, effect, mesh.visibility);
if (mustRebind) {
this._uniformBuffer.bindToEffect(effect, "Material");
this.bindViewProjection(effect);
var reflectionTexture = this._reflectionTexture;
if (!this._uniformBuffer.useUbo || !this.isFrozen || !this._uniformBuffer.isSync) {
// Texture uniforms
if (scene.texturesEnabled) {
if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
this._uniformBuffer.updateFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
BABYLON.MaterialHelper.BindTextureMatrix(this._diffuseTexture, this._uniformBuffer, "diffuse");
}
if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
this._uniformBuffer.updateMatrix("reflectionMatrix", reflectionTexture.getReflectionTextureMatrix());
this._uniformBuffer.updateFloat2("vReflectionInfos", reflectionTexture.level, this._reflectionBlur);
this._uniformBuffer.updateFloat3("vReflectionMicrosurfaceInfos", reflectionTexture.getSize().width, reflectionTexture.lodGenerationScale, reflectionTexture.lodGenerationOffset);
}
}
if (this.shadowLevel > 0) {
this._uniformBuffer.updateFloat("shadowLevel", this.shadowLevel);
}
this._uniformBuffer.updateFloat("alpha", this.alpha);
// Point size
if (this.pointsCloud) {
this._uniformBuffer.updateFloat("pointSize", this.pointSize);
}
if (defines.USEHIGHLIGHTANDSHADOWCOLORS) {
this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryHighlightColor, 1.0);
this._uniformBuffer.updateColor4("vPrimaryColorShadow", this._primaryShadowColor, 1.0);
}
else {
this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryColor, 1.0);
}
}
this._uniformBuffer.updateFloat("fFovMultiplier", this._fovMultiplier);
// Textures
if (scene.texturesEnabled) {
if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
this._uniformBuffer.setTexture("diffuseSampler", this._diffuseTexture);
}
if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
if (defines.REFLECTIONBLUR && defines.TEXTURELODSUPPORT) {
this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture);
}
else if (!defines.REFLECTIONBLUR) {
this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture);
}
else {
this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture._lodTextureMid || reflectionTexture);
this._uniformBuffer.setTexture("reflectionSamplerLow", reflectionTexture._lodTextureLow || reflectionTexture);
this._uniformBuffer.setTexture("reflectionSamplerHigh", reflectionTexture._lodTextureHigh || reflectionTexture);
}
if (defines.REFLECTIONFRESNEL) {
this._uniformBuffer.updateFloat3("vBackgroundCenter", this.sceneCenter.x, this.sceneCenter.y, this.sceneCenter.z);
this._uniformBuffer.updateFloat4("vReflectionControl", this._reflectionControls.x, this._reflectionControls.y, this._reflectionControls.z, this._reflectionControls.w);
}
}
}
// Clip plane
BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
BABYLON.MaterialHelper.BindEyePosition(effect, scene);
}
if (mustRebind || !this.isFrozen) {
if (scene.lightsEnabled) {
BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights, false);
}
// View
this.bindView(effect);
// Fog
BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
// image processing
this._imageProcessingConfiguration.bind(this._activeEffect);
}
this._uniformBuffer.update();
this._afterBind(mesh);
};
/**
* Dispose the material.
* @param forceDisposeEffect Force disposal of the associated effect.
* @param forceDisposeTextures Force disposal of the associated textures.
*/
BackgroundMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
if (forceDisposeEffect === void 0) { forceDisposeEffect = false; }
if (forceDisposeTextures === void 0) { forceDisposeTextures = false; }
if (forceDisposeTextures) {
if (this.diffuseTexture) {
this.diffuseTexture.dispose();
}
if (this.reflectionTexture) {
this.reflectionTexture.dispose();
}
}
this._renderTargets.dispose();
if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
}
_super.prototype.dispose.call(this, forceDisposeEffect);
};
/**
* Clones the material.
* @param name The cloned name.
* @returns The cloned material.
*/
BackgroundMaterial.prototype.clone = function (name) {
var _this = this;
return BABYLON.SerializationHelper.Clone(function () { return new BackgroundMaterial(name, _this.getScene()); }, this);
};
/**
* Serializes the current material to its JSON representation.
* @returns The JSON representation.
*/
BackgroundMaterial.prototype.serialize = function () {
var serializationObject = BABYLON.SerializationHelper.Serialize(this);
serializationObject.customType = "BABYLON.BackgroundMaterial";
return serializationObject;
};
/**
* Gets the class name of the material
* @returns "BackgroundMaterial"
*/
BackgroundMaterial.prototype.getClassName = function () {
return "BackgroundMaterial";
};
/**
* Parse a JSON input to create back a background material.
* @param source The JSON data to parse
* @param scene The scene to create the parsed material in
* @param rootUrl The root url of the assets the material depends upon
* @returns the instantiated BackgroundMaterial.
*/
BackgroundMaterial.Parse = function (source, scene, rootUrl) {
return BABYLON.SerializationHelper.Parse(function () { return new BackgroundMaterial(source.name, scene); }, source, scene, rootUrl);
};
/**
* Standard reflectance value at parallel view angle.
*/
BackgroundMaterial.StandardReflectance0 = 0.05;
/**
* Standard reflectance value at grazing angle.
*/
BackgroundMaterial.StandardReflectance90 = 0.5;
__decorate([
BABYLON.serializeAsColor3()
], BackgroundMaterial.prototype, "_primaryColor", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
], BackgroundMaterial.prototype, "primaryColor", void 0);
__decorate([
BABYLON.serializeAsColor3()
], BackgroundMaterial.prototype, "__perceptualColor", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_primaryColorShadowLevel", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_primaryColorHighlightLevel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
], BackgroundMaterial.prototype, "primaryColorHighlightLevel", null);
__decorate([
BABYLON.serializeAsTexture()
], BackgroundMaterial.prototype, "_reflectionTexture", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionTexture", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionBlur", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionBlur", void 0);
__decorate([
BABYLON.serializeAsTexture()
], BackgroundMaterial.prototype, "_diffuseTexture", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "diffuseTexture", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "shadowLights", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_shadowLevel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "shadowLevel", void 0);
__decorate([
BABYLON.serializeAsVector3()
], BackgroundMaterial.prototype, "_sceneCenter", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "sceneCenter", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_opacityFresnel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "opacityFresnel", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionFresnel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionFresnel", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionFalloffDistance", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionFalloffDistance", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionAmount", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionAmount", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionReflectance0", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionReflectance0", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionReflectance90", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionReflectance90", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_useRGBColor", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "useRGBColor", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_enableNoise", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "enableNoise", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_maxSimultaneousLights", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "maxSimultaneousLights", void 0);
__decorate([
BABYLON.serializeAsImageProcessingConfiguration()
], BackgroundMaterial.prototype, "_imageProcessingConfiguration", void 0);
return BackgroundMaterial;
}(BABYLON.PushMaterial));
BABYLON.BackgroundMaterial = BackgroundMaterial;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.backgroundMaterial.js.map
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var BABYLON;
(function (BABYLON) {
/**
* The Environment helper class can be used to add a fully featuread none expensive background to your scene.
* It includes by default a skybox and a ground relying on the BackgroundMaterial.
* It also helps with the default setup of your imageProcessing configuration.
*/
var EnvironmentHelper = /** @class */ (function () {
/**
* constructor
* @param options
* @param scene The scene to add the material to
*/
function EnvironmentHelper(options, scene) {
var _this = this;
this._errorHandler = function (message, exception) {
_this.onErrorObservable.notifyObservers({ message: message, exception: exception });
};
this._options = __assign({}, EnvironmentHelper._getDefaultOptions(), options);
this._scene = scene;
this.onErrorObservable = new BABYLON.Observable();
this._setupBackground();
this._setupImageProcessing();
}
/**
* Creates the default options for the helper.
*/
EnvironmentHelper._getDefaultOptions = function () {
return {
createGround: true,
groundSize: 15,
groundTexture: this._groundTextureCDNUrl,
groundColor: new BABYLON.Color3(0.2, 0.2, 0.3).toLinearSpace().scale(3),
groundOpacity: 0.9,
enableGroundShadow: true,
groundShadowLevel: 0.5,
enableGroundMirror: false,
groundMirrorSizeRatio: 0.3,
groundMirrorBlurKernel: 64,
groundMirrorAmount: 1,
groundMirrorFresnelWeight: 1,
groundMirrorFallOffDistance: 0,
groundMirrorTextureType: BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT,
groundYBias: 0.00001,
createSkybox: true,
skyboxSize: 20,
skyboxTexture: this._skyboxTextureCDNUrl,
skyboxColor: new BABYLON.Color3(0.2, 0.2, 0.3).toLinearSpace().scale(3),
backgroundYRotation: 0,
sizeAuto: true,
rootPosition: BABYLON.Vector3.Zero(),
setupImageProcessing: true,
environmentTexture: this._environmentTextureCDNUrl,
cameraExposure: 0.8,
cameraContrast: 1.2,
toneMappingEnabled: true,
};
};
Object.defineProperty(EnvironmentHelper.prototype, "rootMesh", {
/**
* Gets the root mesh created by the helper.
*/
get: function () {
return this._rootMesh;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "skybox", {
/**
* Gets the skybox created by the helper.
*/
get: function () {
return this._skybox;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "skyboxTexture", {
/**
* Gets the skybox texture created by the helper.
*/
get: function () {
return this._skyboxTexture;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "skyboxMaterial", {
/**
* Gets the skybox material created by the helper.
*/
get: function () {
return this._skyboxMaterial;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "ground", {
/**
* Gets the ground mesh created by the helper.
*/
get: function () {
return this._ground;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "groundTexture", {
/**
* Gets the ground texture created by the helper.
*/
get: function () {
return this._groundTexture;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "groundMirror", {
/**
* Gets the ground mirror created by the helper.
*/
get: function () {
return this._groundMirror;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "groundMirrorRenderList", {
/**
* Gets the ground mirror render list to helps pushing the meshes
* you wish in the ground reflection.
*/
get: function () {
if (this._groundMirror) {
return this._groundMirror.renderList;
}
return null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "groundMaterial", {
/**
* Gets the ground material created by the helper.
*/
get: function () {
return this._groundMaterial;
},
enumerable: true,
configurable: true
});
/**
* Updates the background according to the new options
* @param options
*/
EnvironmentHelper.prototype.updateOptions = function (options) {
var newOptions = __assign({}, this._options, options);
if (this._ground && !newOptions.createGround) {
this._ground.dispose();
this._ground = null;
}
if (this._groundMaterial && !newOptions.createGround) {
this._groundMaterial.dispose();
this._groundMaterial = null;
}
if (this._groundTexture) {
if (this._options.groundTexture != newOptions.groundTexture) {
this._groundTexture.dispose();
this._groundTexture = null;
}
}
if (this._skybox && !newOptions.createSkybox) {
this._skybox.dispose();
this._skybox = null;
}
if (this._skyboxMaterial && !newOptions.createSkybox) {
this._skyboxMaterial.dispose();
this._skyboxMaterial = null;
}
if (this._skyboxTexture) {
if (this._options.skyboxTexture != newOptions.skyboxTexture) {
this._skyboxTexture.dispose();
this._skyboxTexture = null;
}
}
if (this._groundMirror && !newOptions.enableGroundMirror) {
this._groundMirror.dispose();
this._groundMirror = null;
}
if (this._scene.environmentTexture) {
if (this._options.environmentTexture != newOptions.environmentTexture) {
this._scene.environmentTexture.dispose();
}
}
this._options = newOptions;
this._setupBackground();
this._setupImageProcessing();
};
/**
* Sets the primary color of all the available elements.
* @param color the main color to affect to the ground and the background
*/
EnvironmentHelper.prototype.setMainColor = function (color) {
if (this.groundMaterial) {
this.groundMaterial.primaryColor = color;
}
if (this.skyboxMaterial) {
this.skyboxMaterial.primaryColor = color;
}
if (this.groundMirror) {
this.groundMirror.clearColor = new BABYLON.Color4(color.r, color.g, color.b, 1.0);
}
};
/**
* Setup the image processing according to the specified options.
*/
EnvironmentHelper.prototype._setupImageProcessing = function () {
if (this._options.setupImageProcessing) {
this._scene.imageProcessingConfiguration.contrast = this._options.cameraContrast;
this._scene.imageProcessingConfiguration.exposure = this._options.cameraExposure;
this._scene.imageProcessingConfiguration.toneMappingEnabled = this._options.toneMappingEnabled;
this._setupEnvironmentTexture();
}
};
/**
* Setup the environment texture according to the specified options.
*/
EnvironmentHelper.prototype._setupEnvironmentTexture = function () {
if (this._scene.environmentTexture) {
return;
}
if (this._options.environmentTexture instanceof BABYLON.BaseTexture) {
this._scene.environmentTexture = this._options.environmentTexture;
return;
}
var environmentTexture = BABYLON.CubeTexture.CreateFromPrefilteredData(this._options.environmentTexture, this._scene);
this._scene.environmentTexture = environmentTexture;
};
/**
* Setup the background according to the specified options.
*/
EnvironmentHelper.prototype._setupBackground = function () {
if (!this._rootMesh) {
this._rootMesh = new BABYLON.Mesh("BackgroundHelper", this._scene);
}
this._rootMesh.rotation.y = this._options.backgroundYRotation;
var sceneSize = this._getSceneSize();
if (this._options.createGround) {
this._setupGround(sceneSize);
this._setupGroundMaterial();
this._setupGroundDiffuseTexture();
if (this._options.enableGroundMirror) {
this._setupGroundMirrorTexture(sceneSize);
}
this._setupMirrorInGroundMaterial();
}
if (this._options.createSkybox) {
this._setupSkybox(sceneSize);
this._setupSkyboxMaterial();
this._setupSkyboxReflectionTexture();
}
this._rootMesh.position.x = sceneSize.rootPosition.x;
this._rootMesh.position.z = sceneSize.rootPosition.z;
this._rootMesh.position.y = sceneSize.rootPosition.y;
};
/**
* Get the scene sizes according to the setup.
*/
EnvironmentHelper.prototype._getSceneSize = function () {
var _this = this;
var groundSize = this._options.groundSize;
var skyboxSize = this._options.skyboxSize;
var rootPosition = this._options.rootPosition;
if (!this._scene.meshes || this._scene.meshes.length === 1) { // 1 only means the root of the helper.
return { groundSize: groundSize, skyboxSize: skyboxSize, rootPosition: rootPosition };
}
var sceneExtends = this._scene.getWorldExtends(function (mesh) {
return (mesh !== _this._ground && mesh !== _this._rootMesh && mesh !== _this._skybox);
});
var sceneDiagonal = sceneExtends.max.subtract(sceneExtends.min);
if (this._options.sizeAuto) {
if (this._scene.activeCamera instanceof BABYLON.ArcRotateCamera &&
this._scene.activeCamera.upperRadiusLimit) {
groundSize = this._scene.activeCamera.upperRadiusLimit * 2;
skyboxSize = groundSize;
}
var sceneDiagonalLenght = sceneDiagonal.length();
if (sceneDiagonalLenght > groundSize) {
groundSize = sceneDiagonalLenght * 2;
skyboxSize = groundSize;
}
// 10 % bigger.
groundSize *= 1.1;
skyboxSize *= 1.5;
rootPosition = sceneExtends.min.add(sceneDiagonal.scale(0.5));
rootPosition.y = sceneExtends.min.y - this._options.groundYBias;
}
return { groundSize: groundSize, skyboxSize: skyboxSize, rootPosition: rootPosition };
};
/**
* Setup the ground according to the specified options.
*/
EnvironmentHelper.prototype._setupGround = function (sceneSize) {
var _this = this;
if (!this._ground) {
this._ground = BABYLON.Mesh.CreatePlane("BackgroundPlane", sceneSize.groundSize, this._scene);
this._ground.rotation.x = Math.PI / 2; // Face up by default.
this._ground.parent = this._rootMesh;
this._ground.onDisposeObservable.add(function () { _this._ground = null; });
}
this._ground.receiveShadows = this._options.enableGroundShadow;
};
/**
* Setup the ground material according to the specified options.
*/
EnvironmentHelper.prototype._setupGroundMaterial = function () {
if (!this._groundMaterial) {
this._groundMaterial = new BABYLON.BackgroundMaterial("BackgroundPlaneMaterial", this._scene);
}
this._groundMaterial.alpha = this._options.groundOpacity;
this._groundMaterial.alphaMode = BABYLON.Engine.ALPHA_PREMULTIPLIED_PORTERDUFF;
this._groundMaterial.shadowLevel = this._options.groundShadowLevel;
this._groundMaterial.primaryColor = this._options.groundColor;
this._groundMaterial.useRGBColor = false;
this._groundMaterial.enableNoise = true;
if (this._ground) {
this._ground.material = this._groundMaterial;
}
};
/**
* Setup the ground diffuse texture according to the specified options.
*/
EnvironmentHelper.prototype._setupGroundDiffuseTexture = function () {
if (!this._groundMaterial) {
return;
}
if (this._groundTexture) {
return;
}
if (this._options.groundTexture instanceof BABYLON.BaseTexture) {
this._groundMaterial.diffuseTexture = this._options.groundTexture;
return;
}
var diffuseTexture = new BABYLON.Texture(this._options.groundTexture, this._scene, undefined, undefined, undefined, undefined, this._errorHandler);
diffuseTexture.gammaSpace = false;
diffuseTexture.hasAlpha = true;
this._groundMaterial.diffuseTexture = diffuseTexture;
};
/**
* Setup the ground mirror texture according to the specified options.
*/
EnvironmentHelper.prototype._setupGroundMirrorTexture = function (sceneSize) {
var wrapping = BABYLON.Texture.CLAMP_ADDRESSMODE;
if (!this._groundMirror) {
this._groundMirror = new BABYLON.MirrorTexture("BackgroundPlaneMirrorTexture", { ratio: this._options.groundMirrorSizeRatio }, this._scene, false, this._options.groundMirrorTextureType, BABYLON.Texture.BILINEAR_SAMPLINGMODE, true);
this._groundMirror.mirrorPlane = new BABYLON.Plane(0, -1, 0, sceneSize.rootPosition.y);
this._groundMirror.anisotropicFilteringLevel = 1;
this._groundMirror.wrapU = wrapping;
this._groundMirror.wrapV = wrapping;
this._groundMirror.gammaSpace = false;
if (this._groundMirror.renderList) {
for (var i = 0; i < this._scene.meshes.length; i++) {
var mesh = this._scene.meshes[i];
if (mesh !== this._ground &&
mesh !== this._skybox &&
mesh !== this._rootMesh) {
this._groundMirror.renderList.push(mesh);
}
}
}
}
this._groundMirror.clearColor = new BABYLON.Color4(this._options.groundColor.r, this._options.groundColor.g, this._options.groundColor.b, 1);
this._groundMirror.adaptiveBlurKernel = this._options.groundMirrorBlurKernel;
};
/**
* Setup the ground to receive the mirror texture.
*/
EnvironmentHelper.prototype._setupMirrorInGroundMaterial = function () {
if (this._groundMaterial) {
this._groundMaterial.reflectionTexture = this._groundMirror;
this._groundMaterial.reflectionFresnel = true;
this._groundMaterial.reflectionAmount = this._options.groundMirrorAmount;
this._groundMaterial.reflectionStandardFresnelWeight = this._options.groundMirrorFresnelWeight;
this._groundMaterial.reflectionFalloffDistance = this._options.groundMirrorFallOffDistance;
}
};
/**
* Setup the skybox according to the specified options.
*/
EnvironmentHelper.prototype._setupSkybox = function (sceneSize) {
var _this = this;
if (!this._skybox) {
this._skybox = BABYLON.Mesh.CreateBox("BackgroundSkybox", sceneSize.skyboxSize, this._scene, undefined, BABYLON.Mesh.BACKSIDE);
this._skybox.onDisposeObservable.add(function () { _this._skybox = null; });
}
this._skybox.parent = this._rootMesh;
};
/**
* Setup the skybox material according to the specified options.
*/
EnvironmentHelper.prototype._setupSkyboxMaterial = function () {
if (!this._skybox) {
return;
}
if (!this._skyboxMaterial) {
this._skyboxMaterial = new BABYLON.BackgroundMaterial("BackgroundSkyboxMaterial", this._scene);
}
this._skyboxMaterial.useRGBColor = false;
this._skyboxMaterial.primaryColor = this._options.skyboxColor;
this._skyboxMaterial.enableNoise = true;
this._skybox.material = this._skyboxMaterial;
};
/**
* Setup the skybox reflection texture according to the specified options.
*/
EnvironmentHelper.prototype._setupSkyboxReflectionTexture = function () {
if (!this._skyboxMaterial) {
return;
}
if (this._skyboxTexture) {
return;
}
if (this._options.skyboxTexture instanceof BABYLON.BaseTexture) {
this._skyboxMaterial.reflectionTexture = this._options.skyboxTexture;
return;
}
this._skyboxTexture = new BABYLON.CubeTexture(this._options.skyboxTexture, this._scene, undefined, undefined, undefined, undefined, this._errorHandler);
this._skyboxTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
this._skyboxTexture.gammaSpace = false;
this._skyboxMaterial.reflectionTexture = this._skyboxTexture;
};
/**
* Dispose all the elements created by the Helper.
*/
EnvironmentHelper.prototype.dispose = function () {
if (this._groundMaterial) {
this._groundMaterial.dispose(true, true);
}
if (this._skyboxMaterial) {
this._skyboxMaterial.dispose(true, true);
}
this._rootMesh.dispose(false);
};
/**
* Default ground texture URL.
*/
EnvironmentHelper._groundTextureCDNUrl = "https://assets.babylonjs.com/environments/backgroundGround.png";
/**
* Default skybox texture URL.
*/
EnvironmentHelper._skyboxTextureCDNUrl = "https://assets.babylonjs.com/environments/backgroundSkybox.dds";
/**
* Default environment texture URL.
*/
EnvironmentHelper._environmentTextureCDNUrl = "https://assets.babylonjs.com/environments/environmentSpecular.dds";
return EnvironmentHelper;
}());
BABYLON.EnvironmentHelper = EnvironmentHelper;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.environmentHelper.js.map
var BABYLON;
(function (BABYLON) {
/**
* Display a 360 degree video on an approximately spherical surface, useful for VR applications or skyboxes.
* As a subclass of Node, this allow parenting to the camera or multiple videos with different locations in the scene.
* This class achieves its effect with a VideoTexture and a correctly configured BackgroundMaterial on an inverted sphere.
* Potential additions to this helper include zoom and and non-infinite distance rendering effects.
*/
var VideoDome = /** @class */ (function (_super) {
__extends(VideoDome, _super);
/**
* Create an instance of this class and pass through the parameters to the relevant classes, VideoTexture, StandardMaterial, and Mesh.
* @param name Element's name, child elements will append suffixes for their own names.
* @param urlsOrVideo
* @param options An object containing optional or exposed sub element properties:
* @param options **resolution=12** Integer, lower resolutions have more artifacts at extreme fovs
* @param options **clickToPlay=false** Add a click to play listener to the video, does not prevent autoplay.
* @param options **autoPlay=true** Automatically attempt to being playing the video.
* @param options **loop=true** Automatically loop video on end.
* @param options **size=1000** Physical radius to create the dome at, defaults to approximately half the far clip plane.
*/
function VideoDome(name, urlsOrVideo, options, scene) {
var _this = _super.call(this, name, scene) || this;
// set defaults and manage values
name = name || "videoDome";
options.resolution = (Math.abs(options.resolution) | 0) || 12;
options.clickToPlay = Boolean(options.clickToPlay);
options.autoPlay = options.autoPlay === undefined ? true : Boolean(options.autoPlay);
options.loop = options.loop === undefined ? true : Boolean(options.loop);
options.size = Math.abs(options.size) || (scene.activeCamera ? scene.activeCamera.maxZ * 0.48 : 1000);
// create
var tempOptions = { loop: options.loop, autoPlay: options.autoPlay, autoUpdateTexture: true };
var material = _this._material = new BABYLON.BackgroundMaterial(name + "_material", scene);
var texture = _this._videoTexture = new BABYLON.VideoTexture(name + "_texture", urlsOrVideo, scene, false, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, tempOptions);
_this._mesh = BABYLON.MeshBuilder.CreateIcoSphere(name + "_mesh", {
flat: false,
radius: options.size,
subdivisions: options.resolution,
sideOrientation: BABYLON.Mesh.BACKSIDE // needs to be inside out
}, scene);
// configure material
texture.coordinatesMode = BABYLON.Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE; // matches orientation
texture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE; // always clamp the up/down
material.reflectionTexture = _this._videoTexture;
material.useEquirectangularFOV = true;
material.fovMultiplier = 1.0;
// configure mesh
_this._mesh.material = material;
_this._mesh.parent = _this;
// optional configuration
if (options.clickToPlay) {
scene.onPointerUp = function () {
_this._videoTexture.video.play();
};
}
return _this;
}
Object.defineProperty(VideoDome.prototype, "fovMultiplier", {
/**
* The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
* Also see the options.resolution property.
*/
get: function () {
return this._material.fovMultiplier;
},
set: function (value) {
this._material.fovMultiplier = value;
},
enumerable: true,
configurable: true
});
/**
* Releases resources associated with this node.
* @param doNotRecurse Set to true to not recurse into each children (recurse into each children by default)
* @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
*/
VideoDome.prototype.dispose = function (doNotRecurse, disposeMaterialAndTextures) {
if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
this._videoTexture.dispose();
this._mesh.dispose();
this._material.dispose();
_super.prototype.dispose.call(this, doNotRecurse, disposeMaterialAndTextures);
};
return VideoDome;
}(BABYLON.Node));
BABYLON.VideoDome = VideoDome;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.videoDome.js.map
BABYLON.Effect.ShadersStore={"defaultVertexShader":"#include<__decl__defaultVertex>\n\n#define CUSTOM_VERTEX_BEGIN\nattribute vec3 position;\n#ifdef NORMAL\nattribute vec3 normal;\n#endif\n#ifdef TANGENT\nattribute vec4 tangent;\n#endif\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec4 color;\n#endif\n#include\n#include\n\n#include\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif\n#ifdef MAINUV2\nvarying vec2 vMainUV2;\n#endif\n#if defined(DIFFUSE) && DIFFUSEDIRECTUV == 0\nvarying vec2 vDiffuseUV;\n#endif\n#if defined(AMBIENT) && AMBIENTDIRECTUV == 0\nvarying vec2 vAmbientUV;\n#endif\n#if defined(OPACITY) && OPACITYDIRECTUV == 0\nvarying vec2 vOpacityUV;\n#endif\n#if defined(EMISSIVE) && EMISSIVEDIRECTUV == 0\nvarying vec2 vEmissiveUV;\n#endif\n#if defined(LIGHTMAP) && LIGHTMAPDIRECTUV == 0\nvarying vec2 vLightmapUV;\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM) && SPECULARDIRECTUV == 0\nvarying vec2 vSpecularUV;\n#endif\n#if defined(BUMP) && BUMPDIRECTUV == 0\nvarying vec2 vBumpUV;\n#endif\n\nvarying vec3 vPositionW;\n#ifdef NORMAL\nvarying vec3 vNormalW;\n#endif\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\n#include\n#include\n#include\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#include\n#include[0..maxSimultaneousMorphTargets]\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#include\n#define CUSTOM_VERTEX_DEFINITIONS\nvoid main(void) {\n#define CUSTOM_VERTEX_MAIN_BEGIN\nvec3 positionUpdated=position;\n#ifdef NORMAL \nvec3 normalUpdated=normal;\n#endif\n#ifdef TANGENT\nvec4 tangentUpdated=tangent;\n#endif\n#include[0..maxSimultaneousMorphTargets]\n#ifdef REFLECTIONMAP_SKYBOX\nvPositionUVW=positionUpdated;\n#endif \n#define CUSTOM_VERTEX_UPDATE_POSITION\n#define CUSTOM_VERTEX_UPDATE_NORMAL\n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(positionUpdated,1.0);\nvec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\nvPositionW=vec3(worldPos);\n#ifdef NORMAL\nmat3 normalWorld=mat3(finalWorld);\n#ifdef NONUNIFORMSCALING\nnormalWorld=transposeMat3(inverseMat3(normalWorld));\n#endif\nvNormalW=normalize(normalWorld*normalUpdated);\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvDirectionW=normalize(vec3(finalWorld*vec4(positionUpdated,0.0)));\n#endif\n\n#ifndef UV1\nvec2 uv=vec2(0.,0.);\n#endif\n#ifndef UV2\nvec2 uv2=vec2(0.,0.);\n#endif\n#ifdef MAINUV1\nvMainUV1=uv;\n#endif\n#ifdef MAINUV2\nvMainUV2=uv2;\n#endif\n#if defined(DIFFUSE) && DIFFUSEDIRECTUV == 0\nif (vDiffuseInfos.x == 0.)\n{\nvDiffuseUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvDiffuseUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(AMBIENT) && AMBIENTDIRECTUV == 0\nif (vAmbientInfos.x == 0.)\n{\nvAmbientUV=vec2(ambientMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvAmbientUV=vec2(ambientMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(OPACITY) && OPACITYDIRECTUV == 0\nif (vOpacityInfos.x == 0.)\n{\nvOpacityUV=vec2(opacityMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvOpacityUV=vec2(opacityMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(EMISSIVE) && EMISSIVEDIRECTUV == 0\nif (vEmissiveInfos.x == 0.)\n{\nvEmissiveUV=vec2(emissiveMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvEmissiveUV=vec2(emissiveMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(LIGHTMAP) && LIGHTMAPDIRECTUV == 0\nif (vLightmapInfos.x == 0.)\n{\nvLightmapUV=vec2(lightmapMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvLightmapUV=vec2(lightmapMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM) && SPECULARDIRECTUV == 0\nif (vSpecularInfos.x == 0.)\n{\nvSpecularUV=vec2(specularMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvSpecularUV=vec2(specularMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(BUMP) && BUMPDIRECTUV == 0\nif (vBumpInfos.x == 0.)\n{\nvBumpUV=vec2(bumpMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvBumpUV=vec2(bumpMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#include\n#include\n#include\n#include[0..maxSimultaneousLights]\n#ifdef VERTEXCOLOR\n\nvColor=color;\n#endif\n#include\n#include\n#define CUSTOM_VERTEX_MAIN_END\n}\n","defaultPixelShader":"#include<__decl__defaultFragment>\n#if defined(BUMP) || !defined(NORMAL)\n#extension GL_OES_standard_derivatives : enable\n#endif\n#define CUSTOM_FRAGMENT_BEGIN\n#ifdef LOGARITHMICDEPTH\n#extension GL_EXT_frag_depth : enable\n#endif\n\n#define RECIPROCAL_PI2 0.15915494\nuniform vec3 vEyePosition;\nuniform vec3 vAmbientColor;\n\nvarying vec3 vPositionW;\n#ifdef NORMAL\nvarying vec3 vNormalW;\n#endif\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif\n#ifdef MAINUV2\nvarying vec2 vMainUV2;\n#endif\n\n#include\n\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#include\n#include\n\n#ifdef DIFFUSE\n#if DIFFUSEDIRECTUV == 1\n#define vDiffuseUV vMainUV1\n#elif DIFFUSEDIRECTUV == 2\n#define vDiffuseUV vMainUV2\n#else\nvarying vec2 vDiffuseUV;\n#endif\nuniform sampler2D diffuseSampler;\n#endif\n#ifdef AMBIENT\n#if AMBIENTDIRECTUV == 1\n#define vAmbientUV vMainUV1\n#elif AMBIENTDIRECTUV == 2\n#define vAmbientUV vMainUV2\n#else\nvarying vec2 vAmbientUV;\n#endif\nuniform sampler2D ambientSampler;\n#endif\n#ifdef OPACITY \n#if OPACITYDIRECTUV == 1\n#define vOpacityUV vMainUV1\n#elif OPACITYDIRECTUV == 2\n#define vOpacityUV vMainUV2\n#else\nvarying vec2 vOpacityUV;\n#endif\nuniform sampler2D opacitySampler;\n#endif\n#ifdef EMISSIVE\n#if EMISSIVEDIRECTUV == 1\n#define vEmissiveUV vMainUV1\n#elif EMISSIVEDIRECTUV == 2\n#define vEmissiveUV vMainUV2\n#else\nvarying vec2 vEmissiveUV;\n#endif\nuniform sampler2D emissiveSampler;\n#endif\n#ifdef LIGHTMAP\n#if LIGHTMAPDIRECTUV == 1\n#define vLightmapUV vMainUV1\n#elif LIGHTMAPDIRECTUV == 2\n#define vLightmapUV vMainUV2\n#else\nvarying vec2 vLightmapUV;\n#endif\nuniform sampler2D lightmapSampler;\n#endif\n#ifdef REFRACTION\n#ifdef REFRACTIONMAP_3D\nuniform samplerCube refractionCubeSampler;\n#else\nuniform sampler2D refraction2DSampler;\n#endif\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM)\n#if SPECULARDIRECTUV == 1\n#define vSpecularUV vMainUV1\n#elif SPECULARDIRECTUV == 2\n#define vSpecularUV vMainUV2\n#else\nvarying vec2 vSpecularUV;\n#endif\nuniform sampler2D specularSampler;\n#endif\n#ifdef ALPHATEST\nuniform float alphaCutOff;\n#endif\n\n#include\n\n#ifdef REFLECTION\n#ifdef REFLECTIONMAP_3D\nuniform samplerCube reflectionCubeSampler;\n#else\nuniform sampler2D reflection2DSampler;\n#endif\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#else\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#endif\n#include\n#endif\n#include\n#include\n#include\n#include\n#include\n#include\n#define CUSTOM_FRAGMENT_DEFINITIONS\nvoid main(void) {\n#define CUSTOM_FRAGMENT_MAIN_BEGIN\n#include\nvec3 viewDirectionW=normalize(vEyePosition-vPositionW);\n\nvec4 baseColor=vec4(1.,1.,1.,1.);\nvec3 diffuseColor=vDiffuseColor.rgb;\n\nfloat alpha=vDiffuseColor.a;\n\n#ifdef NORMAL\nvec3 normalW=normalize(vNormalW);\n#else\nvec3 normalW=normalize(-cross(dFdx(vPositionW),dFdy(vPositionW)));\n#endif\n#include\n#ifdef TWOSIDEDLIGHTING\nnormalW=gl_FrontFacing ? normalW : -normalW;\n#endif\n#ifdef DIFFUSE\nbaseColor=texture2D(diffuseSampler,vDiffuseUV+uvOffset);\n#ifdef ALPHATEST\nif (baseColor.a\n#ifdef VERTEXCOLOR\nbaseColor.rgb*=vColor.rgb;\n#endif\n#define CUSTOM_FRAGMENT_UPDATE_DIFFUSE\n\nvec3 baseAmbientColor=vec3(1.,1.,1.);\n#ifdef AMBIENT\nbaseAmbientColor=texture2D(ambientSampler,vAmbientUV+uvOffset).rgb*vAmbientInfos.y;\n#endif\n#define CUSTOM_FRAGMENT_BEFORE_LIGHTS\n\n#ifdef SPECULARTERM\nfloat glossiness=vSpecularColor.a;\nvec3 specularColor=vSpecularColor.rgb;\n#ifdef SPECULAR\nvec4 specularMapColor=texture2D(specularSampler,vSpecularUV+uvOffset);\nspecularColor=specularMapColor.rgb;\n#ifdef GLOSSINESS\nglossiness=glossiness*specularMapColor.a;\n#endif\n#endif\n#else\nfloat glossiness=0.;\n#endif\n\nvec3 diffuseBase=vec3(0.,0.,0.);\nlightingInfo info;\n#ifdef SPECULARTERM\nvec3 specularBase=vec3(0.,0.,0.);\n#endif\nfloat shadow=1.;\n#ifdef LIGHTMAP\nvec3 lightmapColor=texture2D(lightmapSampler,vLightmapUV+uvOffset).rgb*vLightmapInfos.y;\n#endif\n#include[0..maxSimultaneousLights]\n\nvec3 refractionColor=vec3(0.,0.,0.);\n#ifdef REFRACTION\nvec3 refractionVector=normalize(refract(-viewDirectionW,normalW,vRefractionInfos.y));\n#ifdef REFRACTIONMAP_3D\nrefractionVector.y=refractionVector.y*vRefractionInfos.w;\nif (dot(refractionVector,viewDirectionW)<1.0) {\nrefractionColor=textureCube(refractionCubeSampler,refractionVector).rgb;\n}\n#else\nvec3 vRefractionUVW=vec3(refractionMatrix*(view*vec4(vPositionW+refractionVector*vRefractionInfos.z,1.0)));\nvec2 refractionCoords=vRefractionUVW.xy/vRefractionUVW.z;\nrefractionCoords.y=1.0-refractionCoords.y;\nrefractionColor=texture2D(refraction2DSampler,refractionCoords).rgb;\n#endif\n#ifdef IS_REFRACTION_LINEAR\nrefractionColor=toGammaSpace(refractionColor);\n#endif\nrefractionColor*=vRefractionInfos.x;\n#endif\n\nvec3 reflectionColor=vec3(0.,0.,0.);\n#ifdef REFLECTION\nvec3 vReflectionUVW=computeReflectionCoords(vec4(vPositionW,1.0),normalW);\n#ifdef REFLECTIONMAP_3D\n#ifdef ROUGHNESS\nfloat bias=vReflectionInfos.y;\n#ifdef SPECULARTERM\n#ifdef SPECULAR\n#ifdef GLOSSINESS\nbias*=(1.0-specularMapColor.a);\n#endif\n#endif\n#endif\nreflectionColor=textureCube(reflectionCubeSampler,vReflectionUVW,bias).rgb;\n#else\nreflectionColor=textureCube(reflectionCubeSampler,vReflectionUVW).rgb;\n#endif\n#else\nvec2 coords=vReflectionUVW.xy;\n#ifdef REFLECTIONMAP_PROJECTION\ncoords/=vReflectionUVW.z;\n#endif\ncoords.y=1.0-coords.y;\nreflectionColor=texture2D(reflection2DSampler,coords).rgb;\n#endif\n#ifdef IS_REFLECTION_LINEAR\nreflectionColor=toGammaSpace(reflectionColor);\n#endif\nreflectionColor*=vReflectionInfos.x;\n#ifdef REFLECTIONFRESNEL\nfloat reflectionFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,reflectionRightColor.a,reflectionLeftColor.a);\n#ifdef REFLECTIONFRESNELFROMSPECULAR\n#ifdef SPECULARTERM\nreflectionColor*=specularColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n#else\nreflectionColor*=reflectionLeftColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n#endif\n#else\nreflectionColor*=reflectionLeftColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n#endif\n#endif\n#endif\n#ifdef REFRACTIONFRESNEL\nfloat refractionFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,refractionRightColor.a,refractionLeftColor.a);\nrefractionColor*=refractionLeftColor.rgb*(1.0-refractionFresnelTerm)+refractionFresnelTerm*refractionRightColor.rgb;\n#endif\n#ifdef OPACITY\nvec4 opacityMap=texture2D(opacitySampler,vOpacityUV+uvOffset);\n#ifdef OPACITYRGB\nopacityMap.rgb=opacityMap.rgb*vec3(0.3,0.59,0.11);\nalpha*=(opacityMap.x+opacityMap.y+opacityMap.z)* vOpacityInfos.y;\n#else\nalpha*=opacityMap.a*vOpacityInfos.y;\n#endif\n#endif\n#ifdef VERTEXALPHA\nalpha*=vColor.a;\n#endif\n#ifdef OPACITYFRESNEL\nfloat opacityFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,opacityParts.z,opacityParts.w);\nalpha+=opacityParts.x*(1.0-opacityFresnelTerm)+opacityFresnelTerm*opacityParts.y;\n#endif\n\nvec3 emissiveColor=vEmissiveColor;\n#ifdef EMISSIVE\nemissiveColor+=texture2D(emissiveSampler,vEmissiveUV+uvOffset).rgb*vEmissiveInfos.y;\n#endif\n#ifdef EMISSIVEFRESNEL\nfloat emissiveFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,emissiveRightColor.a,emissiveLeftColor.a);\nemissiveColor*=emissiveLeftColor.rgb*(1.0-emissiveFresnelTerm)+emissiveFresnelTerm*emissiveRightColor.rgb;\n#endif\n\n#ifdef DIFFUSEFRESNEL\nfloat diffuseFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,diffuseRightColor.a,diffuseLeftColor.a);\ndiffuseBase*=diffuseLeftColor.rgb*(1.0-diffuseFresnelTerm)+diffuseFresnelTerm*diffuseRightColor.rgb;\n#endif\n\n#ifdef EMISSIVEASILLUMINATION\nvec3 finalDiffuse=clamp(diffuseBase*diffuseColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n#else\n#ifdef LINKEMISSIVEWITHDIFFUSE\nvec3 finalDiffuse=clamp((diffuseBase+emissiveColor)*diffuseColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n#else\nvec3 finalDiffuse=clamp(diffuseBase*diffuseColor+emissiveColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n#endif\n#endif\n#ifdef SPECULARTERM\nvec3 finalSpecular=specularBase*specularColor;\n#ifdef SPECULAROVERALPHA\nalpha=clamp(alpha+dot(finalSpecular,vec3(0.3,0.59,0.11)),0.,1.);\n#endif\n#else\nvec3 finalSpecular=vec3(0.0);\n#endif\n#ifdef REFLECTIONOVERALPHA\nalpha=clamp(alpha+dot(reflectionColor,vec3(0.3,0.59,0.11)),0.,1.);\n#endif\n\n#ifdef EMISSIVEASILLUMINATION\nvec4 color=vec4(clamp(finalDiffuse*baseAmbientColor+finalSpecular+reflectionColor+emissiveColor+refractionColor,0.0,1.0),alpha);\n#else\nvec4 color=vec4(finalDiffuse*baseAmbientColor+finalSpecular+reflectionColor+refractionColor,alpha);\n#endif\n\n#ifdef LIGHTMAP\n#ifndef LIGHTMAPEXCLUDED\n#ifdef USELIGHTMAPASSHADOWMAP\ncolor.rgb*=lightmapColor;\n#else\ncolor.rgb+=lightmapColor;\n#endif\n#endif\n#endif\n#define CUSTOM_FRAGMENT_BEFORE_FOG\ncolor.rgb=max(color.rgb,0.);\n#include\n#include\n\n\n#ifdef IMAGEPROCESSINGPOSTPROCESS\ncolor.rgb=toLinearSpace(color.rgb);\n#else\n#ifdef IMAGEPROCESSING\ncolor.rgb=toLinearSpace(color.rgb);\ncolor=applyImageProcessing(color);\n#endif\n#endif\n#ifdef PREMULTIPLYALPHA\n\ncolor.rgb*=color.a;\n#endif\n#define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR\ngl_FragColor=color;\n}\n","pbrVertexShader":"precision highp float;\n#include<__decl__pbrVertex>\n\nattribute vec3 position;\n#ifdef NORMAL\nattribute vec3 normal;\n#endif\n#ifdef TANGENT\nattribute vec4 tangent;\n#endif\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif\n#ifdef MAINUV2\nvarying vec2 vMainUV2; \n#endif \n#ifdef VERTEXCOLOR\nattribute vec4 color;\n#endif\n#include\n#include\n\n#include\n#if defined(ALBEDO) && ALBEDODIRECTUV == 0\nvarying vec2 vAlbedoUV;\n#endif\n#if defined(AMBIENT) && AMBIENTDIRECTUV == 0\nvarying vec2 vAmbientUV;\n#endif\n#if defined(OPACITY) && OPACITYDIRECTUV == 0\nvarying vec2 vOpacityUV;\n#endif\n#if defined(EMISSIVE) && EMISSIVEDIRECTUV == 0\nvarying vec2 vEmissiveUV;\n#endif\n#if defined(LIGHTMAP) && LIGHTMAPDIRECTUV == 0\nvarying vec2 vLightmapUV;\n#endif\n#if defined(REFLECTIVITY) && REFLECTIVITYDIRECTUV == 0\nvarying vec2 vReflectivityUV;\n#endif\n#if defined(MICROSURFACEMAP) && MICROSURFACEMAPDIRECTUV == 0\nvarying vec2 vMicroSurfaceSamplerUV;\n#endif\n#if defined(BUMP) && BUMPDIRECTUV == 0\nvarying vec2 vBumpUV;\n#endif\n\nvarying vec3 vPositionW;\n#ifdef NORMAL\nvarying vec3 vNormalW;\n#if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX)\nvarying vec3 vEnvironmentIrradiance;\n#include\n#endif\n#endif\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\n#include\n#include\n#include\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#include\n#include[0..maxSimultaneousMorphTargets]\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#include\nvoid main(void) {\nvec3 positionUpdated=position;\n#ifdef NORMAL\nvec3 normalUpdated=normal;\n#endif\n#ifdef TANGENT\nvec4 tangentUpdated=tangent;\n#endif\n#include[0..maxSimultaneousMorphTargets]\n#ifdef REFLECTIONMAP_SKYBOX\nvPositionUVW=positionUpdated;\n#endif \n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(positionUpdated,1.0);\nvec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\nvPositionW=vec3(worldPos);\n#ifdef NORMAL\nmat3 normalWorld=mat3(finalWorld);\n#ifdef NONUNIFORMSCALING\nnormalWorld=transposeMat3(inverseMat3(normalWorld));\n#endif\nvNormalW=normalize(normalWorld*normalUpdated);\n#if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX)\nvec3 reflectionVector=vec3(reflectionMatrix*vec4(vNormalW,0)).xyz;\n#ifdef REFLECTIONMAP_OPPOSITEZ\nreflectionVector.z*=-1.0;\n#endif\nvEnvironmentIrradiance=environmentIrradianceJones(reflectionVector);\n#endif\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvDirectionW=normalize(vec3(finalWorld*vec4(positionUpdated,0.0)));\n#endif\n\n#ifndef UV1\nvec2 uv=vec2(0.,0.);\n#endif\n#ifndef UV2\nvec2 uv2=vec2(0.,0.);\n#endif\n#ifdef MAINUV1\nvMainUV1=uv;\n#endif \n#ifdef MAINUV2\nvMainUV2=uv2;\n#endif \n#if defined(ALBEDO) && ALBEDODIRECTUV == 0 \nif (vAlbedoInfos.x == 0.)\n{\nvAlbedoUV=vec2(albedoMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvAlbedoUV=vec2(albedoMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(AMBIENT) && AMBIENTDIRECTUV == 0 \nif (vAmbientInfos.x == 0.)\n{\nvAmbientUV=vec2(ambientMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvAmbientUV=vec2(ambientMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(OPACITY) && OPACITYDIRECTUV == 0 \nif (vOpacityInfos.x == 0.)\n{\nvOpacityUV=vec2(opacityMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvOpacityUV=vec2(opacityMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(EMISSIVE) && EMISSIVEDIRECTUV == 0 \nif (vEmissiveInfos.x == 0.)\n{\nvEmissiveUV=vec2(emissiveMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvEmissiveUV=vec2(emissiveMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(LIGHTMAP) && LIGHTMAPDIRECTUV == 0 \nif (vLightmapInfos.x == 0.)\n{\nvLightmapUV=vec2(lightmapMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvLightmapUV=vec2(lightmapMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(REFLECTIVITY) && REFLECTIVITYDIRECTUV == 0 \nif (vReflectivityInfos.x == 0.)\n{\nvReflectivityUV=vec2(reflectivityMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvReflectivityUV=vec2(reflectivityMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(MICROSURFACEMAP) && MICROSURFACEMAPDIRECTUV == 0 \nif (vMicroSurfaceSamplerInfos.x == 0.)\n{\nvMicroSurfaceSamplerUV=vec2(microSurfaceSamplerMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvMicroSurfaceSamplerUV=vec2(microSurfaceSamplerMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(BUMP) && BUMPDIRECTUV == 0 \nif (vBumpInfos.x == 0.)\n{\nvBumpUV=vec2(bumpMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvBumpUV=vec2(bumpMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n\n#include\n\n#include\n\n#include\n\n#include[0..maxSimultaneousLights]\n\n#ifdef VERTEXCOLOR\nvColor=color;\n#endif\n\n#ifdef POINTSIZE\ngl_PointSize=pointSize;\n#endif\n\n#include\n}","pbrPixelShader":"#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD) || defined(SPECULARAA)\n#extension GL_OES_standard_derivatives : enable\n#endif\n#ifdef LODBASEDMICROSFURACE\n#extension GL_EXT_shader_texture_lod : enable\n#endif\n#ifdef LOGARITHMICDEPTH\n#extension GL_EXT_frag_depth : enable\n#endif\nprecision highp float;\n#include<__decl__pbrFragment>\nuniform vec4 vEyePosition;\nuniform vec3 vAmbientColor;\nuniform vec4 vCameraInfos;\n\nvarying vec3 vPositionW;\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif \n#ifdef MAINUV2 \nvarying vec2 vMainUV2;\n#endif \n#ifdef NORMAL\nvarying vec3 vNormalW;\n#if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX)\nvarying vec3 vEnvironmentIrradiance;\n#endif\n#endif\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\n\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n\n#ifdef ALBEDO\n#if ALBEDODIRECTUV == 1\n#define vAlbedoUV vMainUV1\n#elif ALBEDODIRECTUV == 2\n#define vAlbedoUV vMainUV2\n#else\nvarying vec2 vAlbedoUV;\n#endif\nuniform sampler2D albedoSampler;\n#endif\n#ifdef AMBIENT\n#if AMBIENTDIRECTUV == 1\n#define vAmbientUV vMainUV1\n#elif AMBIENTDIRECTUV == 2\n#define vAmbientUV vMainUV2\n#else\nvarying vec2 vAmbientUV;\n#endif\nuniform sampler2D ambientSampler;\n#endif\n#ifdef OPACITY\n#if OPACITYDIRECTUV == 1\n#define vOpacityUV vMainUV1\n#elif OPACITYDIRECTUV == 2\n#define vOpacityUV vMainUV2\n#else\nvarying vec2 vOpacityUV;\n#endif\nuniform sampler2D opacitySampler;\n#endif\n#ifdef EMISSIVE\n#if EMISSIVEDIRECTUV == 1\n#define vEmissiveUV vMainUV1\n#elif EMISSIVEDIRECTUV == 2\n#define vEmissiveUV vMainUV2\n#else\nvarying vec2 vEmissiveUV;\n#endif\nuniform sampler2D emissiveSampler;\n#endif\n#ifdef LIGHTMAP\n#if LIGHTMAPDIRECTUV == 1\n#define vLightmapUV vMainUV1\n#elif LIGHTMAPDIRECTUV == 2\n#define vLightmapUV vMainUV2\n#else\nvarying vec2 vLightmapUV;\n#endif\nuniform sampler2D lightmapSampler;\n#endif\n#ifdef REFLECTIVITY\n#if REFLECTIVITYDIRECTUV == 1\n#define vReflectivityUV vMainUV1\n#elif REFLECTIVITYDIRECTUV == 2\n#define vReflectivityUV vMainUV2\n#else\nvarying vec2 vReflectivityUV;\n#endif\nuniform sampler2D reflectivitySampler;\n#endif\n#ifdef MICROSURFACEMAP\n#if MICROSURFACEMAPDIRECTUV == 1\n#define vMicroSurfaceSamplerUV vMainUV1\n#elif MICROSURFACEMAPDIRECTUV == 2\n#define vMicroSurfaceSamplerUV vMainUV2\n#else\nvarying vec2 vMicroSurfaceSamplerUV;\n#endif\nuniform sampler2D microSurfaceSampler;\n#endif\n\n#ifdef REFRACTION\n#ifdef REFRACTIONMAP_3D\n#define sampleRefraction(s,c) textureCube(s,c)\nuniform samplerCube refractionSampler;\n#ifdef LODBASEDMICROSFURACE\n#define sampleRefractionLod(s,c,l) textureCubeLodEXT(s,c,l)\n#else\nuniform samplerCube refractionSamplerLow;\nuniform samplerCube refractionSamplerHigh;\n#endif\n#else\n#define sampleRefraction(s,c) texture2D(s,c)\nuniform sampler2D refractionSampler;\n#ifdef LODBASEDMICROSFURACE\n#define sampleRefractionLod(s,c,l) texture2DLodEXT(s,c,l)\n#else\nuniform samplerCube refractionSamplerLow;\nuniform samplerCube refractionSamplerHigh;\n#endif\n#endif\n#endif\n\n#ifdef REFLECTION\n#ifdef REFLECTIONMAP_3D\n#define sampleReflection(s,c) textureCube(s,c)\nuniform samplerCube reflectionSampler;\n#ifdef LODBASEDMICROSFURACE\n#define sampleReflectionLod(s,c,l) textureCubeLodEXT(s,c,l)\n#else\nuniform samplerCube reflectionSamplerLow;\nuniform samplerCube reflectionSamplerHigh;\n#endif\n#else\n#define sampleReflection(s,c) texture2D(s,c)\nuniform sampler2D reflectionSampler;\n#ifdef LODBASEDMICROSFURACE\n#define sampleReflectionLod(s,c,l) texture2DLodEXT(s,c,l)\n#else\nuniform samplerCube reflectionSamplerLow;\nuniform samplerCube reflectionSamplerHigh;\n#endif\n#endif\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#else\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#endif\n#include\n#endif\n#ifdef ENVIRONMENTBRDF\nuniform sampler2D environmentBrdfSampler;\n#endif\n\n#ifndef FROMLINEARSPACE\n#define FROMLINEARSPACE;\n#endif\n#include\n#include\n#include\n\n#include\n#include\n#include\n#include\n#include\n#include\n#include\n\n#include\nvoid main(void) {\n#include\n\n\nvec3 viewDirectionW=normalize(vEyePosition.xyz-vPositionW);\n#ifdef NORMAL\nvec3 normalW=normalize(vNormalW);\n#else\nvec3 normalW=normalize(cross(dFdx(vPositionW),dFdy(vPositionW)))*vEyePosition.w;\n#endif\n#include\n#ifdef SPECULARAA\nvec3 nDfdx=dFdx(normalW.xyz);\nvec3 nDfdy=dFdy(normalW.xyz);\nfloat slopeSquare=max(dot(nDfdx,nDfdx),dot(nDfdy,nDfdy));\n\nfloat geometricRoughnessFactor=pow(clamp(slopeSquare ,0.,1.),0.333);\n\nfloat geometricAlphaGFactor=sqrt(slopeSquare);\n#else\nfloat geometricRoughnessFactor=0.;\n#endif\n#if defined(FORCENORMALFORWARD) && defined(NORMAL)\nvec3 faceNormal=normalize(cross(dFdx(vPositionW),dFdy(vPositionW)))*vEyePosition.w;\n#if defined(TWOSIDEDLIGHTING)\nfaceNormal=gl_FrontFacing ? faceNormal : -faceNormal;\n#endif\nnormalW*=sign(dot(normalW,faceNormal));\n#endif\n#if defined(TWOSIDEDLIGHTING) && defined(NORMAL)\nnormalW=gl_FrontFacing ? normalW : -normalW;\n#endif\n\n\nvec3 surfaceAlbedo=vAlbedoColor.rgb;\n\nfloat alpha=vAlbedoColor.a;\n#ifdef ALBEDO\nvec4 albedoTexture=texture2D(albedoSampler,vAlbedoUV+uvOffset);\n#if defined(ALPHAFROMALBEDO) || defined(ALPHATEST)\nalpha*=albedoTexture.a;\n#endif\nsurfaceAlbedo*=toLinearSpace(albedoTexture.rgb);\nsurfaceAlbedo*=vAlbedoInfos.y;\n#endif\n\n#ifdef OPACITY\nvec4 opacityMap=texture2D(opacitySampler,vOpacityUV+uvOffset);\n#ifdef OPACITYRGB\nalpha=getLuminance(opacityMap.rgb);\n#else\nalpha*=opacityMap.a;\n#endif\nalpha*=vOpacityInfos.y;\n#endif\n#ifdef VERTEXALPHA\nalpha*=vColor.a;\n#endif\n#if !defined(LINKREFRACTIONTOTRANSPARENCY) && !defined(ALPHAFRESNEL)\n#ifdef ALPHATEST\nif (alpha\n#ifdef VERTEXCOLOR\nsurfaceAlbedo*=vColor.rgb;\n#endif\n\nvec3 ambientOcclusionColor=vec3(1.,1.,1.);\n#ifdef AMBIENT\nvec3 ambientOcclusionColorMap=texture2D(ambientSampler,vAmbientUV+uvOffset).rgb*vAmbientInfos.y;\n#ifdef AMBIENTINGRAYSCALE\nambientOcclusionColorMap=vec3(ambientOcclusionColorMap.r,ambientOcclusionColorMap.r,ambientOcclusionColorMap.r);\n#endif\nambientOcclusionColor=mix(ambientOcclusionColor,ambientOcclusionColorMap,vAmbientInfos.z);\n#endif\n#ifdef UNLIT\nvec3 diffuseBase=vec3(1.,1.,1.);\n#else\n\nfloat microSurface=vReflectivityColor.a;\nvec3 surfaceReflectivityColor=vReflectivityColor.rgb;\n#ifdef METALLICWORKFLOW\nvec2 metallicRoughness=surfaceReflectivityColor.rg;\n#ifdef REFLECTIVITY\nvec4 surfaceMetallicColorMap=texture2D(reflectivitySampler,vReflectivityUV+uvOffset);\n#ifdef AOSTOREINMETALMAPRED\nvec3 aoStoreInMetalMap=vec3(surfaceMetallicColorMap.r,surfaceMetallicColorMap.r,surfaceMetallicColorMap.r);\nambientOcclusionColor=mix(ambientOcclusionColor,aoStoreInMetalMap,vReflectivityInfos.z);\n#endif\n#ifdef METALLNESSSTOREINMETALMAPBLUE\nmetallicRoughness.r*=surfaceMetallicColorMap.b;\n#else\nmetallicRoughness.r*=surfaceMetallicColorMap.r;\n#endif\n#ifdef ROUGHNESSSTOREINMETALMAPALPHA\nmetallicRoughness.g*=surfaceMetallicColorMap.a;\n#else\n#ifdef ROUGHNESSSTOREINMETALMAPGREEN\nmetallicRoughness.g*=surfaceMetallicColorMap.g;\n#endif\n#endif\n#endif\n#ifdef MICROSURFACEMAP\nvec4 microSurfaceTexel=texture2D(microSurfaceSampler,vMicroSurfaceSamplerUV+uvOffset)*vMicroSurfaceSamplerInfos.y;\nmetallicRoughness.g*=microSurfaceTexel.r;\n#endif\n\nmicroSurface=1.0-metallicRoughness.g;\n\nvec3 baseColor=surfaceAlbedo;\n\n\nconst vec3 DefaultSpecularReflectanceDielectric=vec3(0.04,0.04,0.04);\n\nsurfaceAlbedo=mix(baseColor.rgb*(1.0-DefaultSpecularReflectanceDielectric.r),vec3(0.,0.,0.),metallicRoughness.r);\n\nsurfaceReflectivityColor=mix(DefaultSpecularReflectanceDielectric,baseColor,metallicRoughness.r);\n#else\n#ifdef REFLECTIVITY\nvec4 surfaceReflectivityColorMap=texture2D(reflectivitySampler,vReflectivityUV+uvOffset);\nsurfaceReflectivityColor*=toLinearSpace(surfaceReflectivityColorMap.rgb);\nsurfaceReflectivityColor*=vReflectivityInfos.y;\n#ifdef MICROSURFACEFROMREFLECTIVITYMAP\nmicroSurface*=surfaceReflectivityColorMap.a;\nmicroSurface*=vReflectivityInfos.z;\n#else\n#ifdef MICROSURFACEAUTOMATIC\nmicroSurface*=computeDefaultMicroSurface(microSurface,surfaceReflectivityColor);\n#endif\n#ifdef MICROSURFACEMAP\nvec4 microSurfaceTexel=texture2D(microSurfaceSampler,vMicroSurfaceSamplerUV+uvOffset)*vMicroSurfaceSamplerInfos.y;\nmicroSurface*=microSurfaceTexel.r;\n#endif\n#endif\n#endif\n#endif\n\nmicroSurface=clamp(microSurface,0.,1.);\n\nfloat roughness=1.-microSurface;\n\n#ifdef ALPHAFRESNEL\n#if defined(ALPHATEST) || defined(ALPHABLEND)\n\n\n\nfloat opacityPerceptual=alpha;\n#ifdef LINEARALPHAFRESNEL\nfloat opacity0=opacityPerceptual;\n#else\nfloat opacity0=opacityPerceptual*opacityPerceptual;\n#endif\nfloat opacity90=fresnelGrazingReflectance(opacity0);\nvec3 normalForward=faceforward(normalW,-viewDirectionW,normalW);\n\nalpha=fresnelSchlickEnvironmentGGX(clamp(dot(viewDirectionW,normalForward),0.0,1.0),vec3(opacity0),vec3(opacity90),sqrt(microSurface)).x;\n#ifdef ALPHATEST\nif (alpha[0..maxSimultaneousLights]\n\n#if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)\n\nvec2 brdfSamplerUV=vec2(NdotV,roughness);\n\nvec4 environmentBrdf=texture2D(environmentBrdfSampler,brdfSamplerUV);\nvec3 specularEnvironmentReflectance=specularEnvironmentR0*environmentBrdf.x+environmentBrdf.y;\n#ifdef RADIANCEOCCLUSION\n#ifdef AMBIENTINGRAYSCALE\nfloat ambientMonochrome=ambientOcclusionColor.r;\n#else\nfloat ambientMonochrome=getLuminance(ambientOcclusionColor);\n#endif\nfloat seo=environmentRadianceOcclusion(ambientMonochrome,NdotVUnclamped);\nspecularEnvironmentReflectance*=seo;\n#endif\n#ifdef HORIZONOCCLUSION\n#ifdef BUMP\n#ifdef REFLECTIONMAP_3D\nfloat eho=environmentHorizonOcclusion(-viewDirectionW,normalW);\nspecularEnvironmentReflectance*=eho;\n#endif\n#endif\n#endif\n#else\n\nvec3 specularEnvironmentReflectance=fresnelSchlickEnvironmentGGX(NdotV,specularEnvironmentR0,specularEnvironmentR90,sqrt(microSurface));\n#endif\n\n#ifdef REFRACTION\nvec3 refractance=vec3(0.0,0.0,0.0);\nvec3 transmission=vec3(1.0,1.0,1.0);\n#ifdef LINKREFRACTIONTOTRANSPARENCY\n\ntransmission*=(1.0-alpha);\n\n\nvec3 mixedAlbedo=surfaceAlbedo;\nfloat maxChannel=max(max(mixedAlbedo.r,mixedAlbedo.g),mixedAlbedo.b);\nvec3 tint=clamp(maxChannel*mixedAlbedo,0.0,1.0);\n\nsurfaceAlbedo*=alpha;\n\nenvironmentIrradiance*=alpha;\n\nenvironmentRefraction*=tint;\n\nalpha=1.0;\n#endif\n\nvec3 bounceSpecularEnvironmentReflectance=(2.0*specularEnvironmentReflectance)/(1.0+specularEnvironmentReflectance);\nspecularEnvironmentReflectance=mix(bounceSpecularEnvironmentReflectance,specularEnvironmentReflectance,alpha);\n\ntransmission*=1.0-specularEnvironmentReflectance;\n\nrefractance=transmission;\n#endif\n\n\n\n\nsurfaceAlbedo.rgb=(1.-reflectance)*surfaceAlbedo.rgb;\n\n#ifdef REFLECTION\nvec3 finalIrradiance=environmentIrradiance;\nfinalIrradiance*=surfaceAlbedo.rgb;\n#endif\n\n#ifdef SPECULARTERM\nvec3 finalSpecular=specularBase;\nfinalSpecular=max(finalSpecular,0.0);\n\nvec3 finalSpecularScaled=finalSpecular*vLightingIntensity.x*vLightingIntensity.w;\n#endif\n\n#ifdef REFLECTION\nvec3 finalRadiance=environmentRadiance;\nfinalRadiance*=specularEnvironmentReflectance;\n\nvec3 finalRadianceScaled=finalRadiance*vLightingIntensity.z;\n#endif\n\n#ifdef REFRACTION\nvec3 finalRefraction=environmentRefraction;\nfinalRefraction*=refractance;\n#endif\n\n#ifdef ALPHABLEND\nfloat luminanceOverAlpha=0.0;\n#if defined(REFLECTION) && defined(RADIANCEOVERALPHA)\nluminanceOverAlpha+=getLuminance(finalRadianceScaled);\n#endif\n#if defined(SPECULARTERM) && defined(SPECULAROVERALPHA)\nluminanceOverAlpha+=getLuminance(finalSpecularScaled);\n#endif\n#if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA)\nalpha=clamp(alpha+luminanceOverAlpha*luminanceOverAlpha,0.,1.);\n#endif\n#endif\n#endif\n\nvec3 finalDiffuse=diffuseBase;\nfinalDiffuse.rgb+=vAmbientColor;\nfinalDiffuse*=surfaceAlbedo.rgb;\nfinalDiffuse=max(finalDiffuse,0.0);\n\nvec3 finalEmissive=vEmissiveColor;\n#ifdef EMISSIVE\nvec3 emissiveColorTex=texture2D(emissiveSampler,vEmissiveUV+uvOffset).rgb;\nfinalEmissive*=toLinearSpace(emissiveColorTex.rgb);\nfinalEmissive*=vEmissiveInfos.y;\n#endif\n\n\n\nvec4 finalColor=vec4(\nfinalDiffuse*ambientOcclusionColor*vLightingIntensity.x +\n#ifndef UNLIT\n#ifdef REFLECTION\nfinalIrradiance*ambientOcclusionColor*vLightingIntensity.z +\n#endif\n#ifdef SPECULARTERM\n\n\nfinalSpecularScaled +\n#endif\n#ifdef REFLECTION\n\n\nfinalRadianceScaled +\n#endif\n#ifdef REFRACTION\nfinalRefraction*vLightingIntensity.z +\n#endif\n#endif\nfinalEmissive*vLightingIntensity.y,\nalpha);\n\n#ifdef LIGHTMAP\n#ifndef LIGHTMAPEXCLUDED\n#ifdef USELIGHTMAPASSHADOWMAP\nfinalColor.rgb*=lightmapColor;\n#else\nfinalColor.rgb+=lightmapColor;\n#endif\n#endif\n#endif\n\nfinalColor=max(finalColor,0.0);\n#include\n#include(color,finalColor)\n#ifdef IMAGEPROCESSINGPOSTPROCESS\n\n\nfinalColor.rgb=clamp(finalColor.rgb,0.,30.0);\n#else\n\nfinalColor=applyImageProcessing(finalColor);\n#endif\n#ifdef PREMULTIPLYALPHA\n\nfinalColor.rgb*=finalColor.a;\n#endif\ngl_FragColor=finalColor;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n}","spritesVertexShader":"\nattribute vec4 position;\nattribute vec4 options;\nattribute vec4 cellInfo;\nattribute vec4 color;\n\nuniform vec2 textureInfos;\nuniform mat4 view;\nuniform mat4 projection;\n\nvarying vec2 vUV;\nvarying vec4 vColor;\n#include\nvoid main(void) { \nvec3 viewPos=(view*vec4(position.xyz,1.0)).xyz; \nvec2 cornerPos;\nfloat angle=position.w;\nvec2 size=vec2(options.x,options.y);\nvec2 offset=options.zw;\nvec2 uvScale=textureInfos.xy;\ncornerPos=vec2(offset.x-0.5,offset.y-0.5)*size;\n\nvec3 rotatedCorner;\nrotatedCorner.x=cornerPos.x*cos(angle)-cornerPos.y*sin(angle);\nrotatedCorner.y=cornerPos.x*sin(angle)+cornerPos.y*cos(angle);\nrotatedCorner.z=0.;\n\nviewPos+=rotatedCorner;\ngl_Position=projection*vec4(viewPos,1.0); \n\nvColor=color;\n\nvec2 uvOffset=vec2(abs(offset.x-cellInfo.x),1.0-abs(offset.y-cellInfo.y));\nvUV=(uvOffset+cellInfo.zw)*uvScale;\n\n#ifdef FOG\nvFogDistance=viewPos;\n#endif\n}","spritesPixelShader":"uniform bool alphaTest;\nvarying vec4 vColor;\n\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n\n#include\nvoid main(void) {\nvec4 color=texture2D(diffuseSampler,vUV);\nif (alphaTest) \n{\nif (color.a<0.95)\ndiscard;\n}\ncolor*=vColor;\n#include\ngl_FragColor=color;\n}","particlesVertexShader":"\nattribute vec3 position;\nattribute vec4 color;\nattribute vec4 options;\nattribute float cellIndex;\n\nuniform mat4 view;\nuniform mat4 projection;\nuniform vec3 particlesInfos; \n\nvarying vec2 vUV;\nvarying vec4 vColor;\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nuniform mat4 invView;\nvarying float fClipDistance;\n#endif\nvoid main(void) { \nvec3 viewPos=(view*vec4(position,1.0)).xyz; \nvec3 cornerPos;\nfloat size=options.y;\nfloat angle=options.x;\nvec2 offset=options.zw;\ncornerPos=vec3(offset.x-0.5,offset.y-0.5,0.)*size;\n\nvec3 rotatedCorner;\nrotatedCorner.x=cornerPos.x*cos(angle)-cornerPos.y*sin(angle);\nrotatedCorner.y=cornerPos.x*sin(angle)+cornerPos.y*cos(angle);\nrotatedCorner.z=0.;\n\nviewPos+=rotatedCorner;\ngl_Position=projection*vec4(viewPos,1.0); \nvColor=color;\n#ifdef ANIMATESHEET\nfloat rowOffset=floor(cellIndex/particlesInfos.z);\nfloat columnOffset=cellIndex-rowOffset*particlesInfos.z;\nvec2 uvScale=particlesInfos.xy;\nvec2 uvOffset=vec2(offset.x ,1.0-offset.y);\nvUV=(uvOffset+vec2(columnOffset,rowOffset))*uvScale;\n#else\nvUV=offset;\n#endif\n\n#ifdef CLIPPLANE\nvec4 worldPos=invView*vec4(viewPos,1.0);\nfClipDistance=dot(worldPos,vClipPlane);\n#endif\n}","particlesPixelShader":"\nvarying vec2 vUV;\nvarying vec4 vColor;\nuniform vec4 textureMask;\nuniform sampler2D diffuseSampler;\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\nvoid main(void) {\n#ifdef CLIPPLANE\nif (fClipDistance>0.0)\ndiscard;\n#endif\nvec4 baseColor=texture2D(diffuseSampler,vUV);\ngl_FragColor=(baseColor*textureMask+(vec4(1.,1.,1.,1.)-textureMask))*vColor;\n}","gpuRenderParticlesVertexShader":"#version 300 es\nuniform vec4 colorDead;\nuniform mat4 view;\nuniform mat4 projection;\n\nin vec3 position;\nin float age;\nin float life;\nin float size;\nin vec4 color;\nin vec2 offset;\nin vec2 uv;\nout vec2 vUV;\nout vec4 vColor;\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nuniform mat4 invView;\nout float fClipDistance;\n#endif\nvoid main() {\nvUV=uv;\nfloat ratio=age/life;\nvColor=color*vec4(1.0-ratio)+colorDead*vec4(ratio);\n\nvec4 viewPosition=view*vec4(position,1.0);\ngl_Position=projection*(viewPosition+vec4(offset*size,0.,0.));\n\n#ifdef CLIPPLANE\nvec4 worldPos=invView*viewPosition;\nfClipDistance=dot(worldPos,vClipPlane);\n#endif \n}","gpuRenderParticlesPixelShader":"#version 300 es\nuniform sampler2D textureSampler;\nin vec2 vUV;\nin vec4 vColor;\nout vec4 outFragColor;\n#ifdef CLIPPLANE\nin float fClipDistance;\n#endif\nvoid main() {\n#ifdef CLIPPLANE\nif (fClipDistance>0.0)\ndiscard;\n#endif \noutFragColor=texture(textureSampler,vUV)*vColor;\n}\n","gpuUpdateParticlesVertexShader":"#version 300 es\n#define PI 3.14159\nuniform float currentCount;\nuniform float timeDelta;\nuniform float stopFactor;\nuniform vec3 generalRandoms;\nuniform mat4 emitterWM;\nuniform vec2 lifeTime;\nuniform vec2 emitPower;\nuniform vec2 sizeRange;\nuniform vec4 color1;\nuniform vec4 color2;\nuniform vec3 gravity;\nuniform sampler2D randomSampler;\n#ifdef BOXEMITTER\nuniform vec3 direction1;\nuniform vec3 direction2;\nuniform vec3 minEmitBox;\nuniform vec3 maxEmitBox;\n#endif\n#ifdef SPHEREEMITTER\nuniform float radius;\n#ifdef DIRECTEDSPHEREEMITTER\nuniform vec3 direction1;\nuniform vec3 direction2;\n#else\nuniform float directionRandomizer;\n#endif\n#endif\n#ifdef CONEEMITTER\nuniform float radius;\nuniform float angle;\nuniform float height;\nuniform float directionRandomizer;\n#endif\n\nin vec3 position;\nin float age;\nin float life;\nin float seed;\nin float size;\nin vec4 color;\nin vec3 direction;\n\nout vec3 outPosition;\nout float outAge;\nout float outLife;\nout float outSeed;\nout float outSize;\nout vec4 outColor;\nout vec3 outDirection;\nvec3 getRandomVec3(float offset) {\nreturn texture(randomSampler,vec2(float(gl_VertexID)*offset/currentCount,0)).rgb;\n}\nvec4 getRandomVec4(float offset) {\nreturn texture(randomSampler,vec2(float(gl_VertexID)*offset/currentCount,0));\n}\nvoid main() {\nif (age>=life) {\nif (stopFactor == 0.) {\noutPosition=position;\noutAge=life;\noutLife=life;\noutSeed=seed;\noutColor=vec4(0.,0.,0.,0.);\noutSize=0.;\noutDirection=direction;\nreturn;\n}\nvec3 position;\nvec3 direction;\n\nvec4 randoms=getRandomVec4(generalRandoms.x);\n\noutAge=0.0;\noutLife=lifeTime.x+(lifeTime.y-lifeTime.x)*randoms.r;\n\noutSeed=seed;\n\noutSize=sizeRange.x+(sizeRange.y-sizeRange.x)*randoms.g;\n\noutColor=color1+(color2-color1)*randoms.b;\n\n#ifdef BOXEMITTER\nvec3 randoms2=getRandomVec3(generalRandoms.y);\nvec3 randoms3=getRandomVec3(generalRandoms.z);\nposition=minEmitBox+(maxEmitBox-minEmitBox)*randoms2;\ndirection=direction1+(direction2-direction1)*randoms3;\n#elif defined(SPHEREEMITTER)\nvec3 randoms2=getRandomVec3(generalRandoms.y);\nvec3 randoms3=getRandomVec3(generalRandoms.z);\n\nfloat phi=2.0*PI*randoms2.x;\nfloat theta=PI*randoms2.y;\nfloat randX=cos(phi)*sin(theta);\nfloat randY=cos(theta);\nfloat randZ=sin(phi)*sin(theta);\nposition=(radius*randoms2.z)*vec3(randX,randY,randZ);\n#ifdef DIRECTEDSPHEREEMITTER\ndirection=direction1+(direction2-direction1)*randoms3;\n#else\n\ndirection=position+directionRandomizer*randoms3;\n#endif\n#elif defined(CONEEMITTER)\nvec3 randoms2=getRandomVec3(generalRandoms.y);\nfloat s=2.0*PI*randoms2.x;\nfloat h=randoms2.y;\n\nh=1.-h*h;\nfloat lRadius=radius*randoms2.z;\nlRadius=lRadius*h;\nfloat randX=lRadius*sin(s);\nfloat randZ=lRadius*cos(s);\nfloat randY=h*height;\nposition=vec3(randX,randY,randZ); \n\nif (angle == 0.) {\ndirection=vec3(0.,1.0,0.);\n} else {\nvec3 randoms3=getRandomVec3(generalRandoms.z);\ndirection=position+directionRandomizer*randoms3;\n}\n#else \n\nposition=vec3(0.,0.,0.);\n\ndirection=2.0*(getRandomVec3(seed)-vec3(0.5,0.5,0.5));\n#endif\nfloat power=emitPower.x+(emitPower.y-emitPower.x)*randoms.a;\noutPosition=(emitterWM*vec4(position,1.)).xyz;\noutDirection=(emitterWM*vec4(direction*power,0.)).xyz;\n} else { \noutPosition=position+direction*timeDelta;\noutAge=age+timeDelta;\noutLife=life;\noutSeed=seed;\noutColor=color;\noutSize=size;\noutDirection=direction+gravity*timeDelta;\n}\n}","gpuUpdateParticlesPixelShader":"#version 300 es\nvoid main() {\ndiscard;\n}\n","colorVertexShader":"\nattribute vec3 position;\n#ifdef VERTEXCOLOR\nattribute vec4 color;\n#endif\n#include\n\nuniform mat4 viewProjection;\nuniform mat4 world;\n\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\nvoid main(void) {\nmat4 finalWorld=world;\n#include\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\n#ifdef VERTEXCOLOR\n\nvColor=color;\n#endif\n}","colorPixelShader":"#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#else\nuniform vec4 color;\n#endif\nvoid main(void) {\n#ifdef VERTEXCOLOR\ngl_FragColor=vColor;\n#else\ngl_FragColor=color;\n#endif\n}","postprocessVertexShader":"\nattribute vec2 position;\nuniform vec2 scale;\n\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvUV=(position*madd+madd)*scale;\ngl_Position=vec4(position,0.0,1.0);\n}","passPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nvoid main(void) \n{\ngl_FragColor=texture2D(textureSampler,vUV);\n}","shadowMapVertexShader":"\nattribute vec3 position;\n#ifdef NORMAL\nattribute vec3 normal;\nuniform vec3 lightData;\n#endif\n#include\n#include\n#include[0..maxSimultaneousMorphTargets]\n\n#include\n#include\nuniform mat4 viewProjection;\nuniform vec3 biasAndScale;\nuniform vec2 depthValues;\nvarying float vDepthMetric;\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform mat4 diffuseMatrix;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#endif\nvoid main(void)\n{\nvec3 positionUpdated=position;\n#include[0..maxSimultaneousMorphTargets]\n#include\n#include\nvec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\n\n#ifdef NORMAL\nmat3 normalWorld=mat3(finalWorld);\n#ifdef NONUNIFORMSCALING\nnormalWorld=transposeMat3(inverseMat3(normalWorld));\n#endif\nvec3 worldNor=normalize(normalWorld*normal);\n#ifdef DIRECTIONINLIGHTDATA\nvec3 worldLightDir=normalize(-lightData.xyz);\n#else\nvec3 directionToLight=lightData.xyz-worldPos.xyz;\nvec3 worldLightDir=normalize(directionToLight);\n#endif\nfloat ndl=dot(worldNor,worldLightDir);\nfloat sinNL=sqrt(1.0-ndl*ndl);\nfloat normalBias=biasAndScale.y*sinNL;\nworldPos.xyz-=worldNor*normalBias;\n#endif\n\ngl_Position=viewProjection*worldPos;\n#ifdef DEPTHTEXTURE\n\ngl_Position.z+=biasAndScale.x*gl_Position.w;\n#endif\n\nvDepthMetric=((gl_Position.z+depthValues.x)/(depthValues.y))+biasAndScale.x;\n#ifdef ALPHATEST\n#ifdef UV1\nvUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef UV2\nvUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n}","shadowMapPixelShader":"#ifndef FLOAT\nvec4 pack(float depth)\n{\nconst vec4 bit_shift=vec4(255.0*255.0*255.0,255.0*255.0,255.0,1.0);\nconst vec4 bit_mask=vec4(0.0,1.0/255.0,1.0/255.0,1.0/255.0);\nvec4 res=fract(depth*bit_shift);\nres-=res.xxyz*bit_mask;\nreturn res;\n}\n#endif\nvarying float vDepthMetric;\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n#endif\nuniform vec3 biasAndScale;\nuniform vec2 depthValues;\nvoid main(void)\n{\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUV).a<0.4)\ndiscard;\n#endif\nfloat depth=vDepthMetric;\n#ifdef ESM\ndepth=clamp(exp(-min(87.,biasAndScale.z*depth)),0.,1.);\n#endif\n#ifdef FLOAT\ngl_FragColor=vec4(depth,1.0,1.0,1.0);\n#else\ngl_FragColor=pack(depth);\n#endif\n}","depthBoxBlurPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nuniform vec2 screenSize;\nvoid main(void)\n{\nvec4 colorDepth=vec4(0.0);\nfor (int x=-OFFSET; x<=OFFSET; x++)\nfor (int y=-OFFSET; y<=OFFSET; y++)\ncolorDepth+=texture2D(textureSampler,vUV+vec2(x,y)/screenSize);\ngl_FragColor=(colorDepth/float((OFFSET*2+1)*(OFFSET*2+1)));\n}","proceduralVertexShader":"\nattribute vec2 position;\n\nvarying vec2 vPosition;\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvPosition=position;\nvUV=position*madd+madd;\ngl_Position=vec4(position,0.0,1.0);\n}","depthVertexShader":"\nattribute vec3 position;\n#include\n\n#include\nuniform mat4 viewProjection;\nuniform vec2 depthValues;\n#if defined(ALPHATEST) || defined(NEED_UV)\nvarying vec2 vUV;\nuniform mat4 diffuseMatrix;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#endif\nvarying float vDepthMetric;\nvoid main(void)\n{\n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\nvDepthMetric=((gl_Position.z+depthValues.x)/(depthValues.y));\n#if defined(ALPHATEST) || defined(BASIC_RENDER)\n#ifdef UV1\nvUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef UV2\nvUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n}","depthPixelShader":"#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n#endif\nvarying float vDepthMetric;\nvoid main(void)\n{\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUV).a<0.4)\ndiscard;\n#endif\ngl_FragColor=vec4(vDepthMetric,vDepthMetric*vDepthMetric,0.0,1.0);\n}","ssaoPixelShader":"\nuniform sampler2D textureSampler;\nvarying vec2 vUV;\n#ifdef SSAO\nuniform sampler2D randomSampler;\nuniform float randTextureTiles;\nuniform float samplesFactor;\nuniform vec3 sampleSphere[SAMPLES];\nuniform float totalStrength;\nuniform float radius;\nuniform float area;\nuniform float fallOff;\nuniform float base;\nvec3 normalFromDepth(float depth,vec2 coords)\n{\nvec2 offset1=vec2(0.0,radius);\nvec2 offset2=vec2(radius,0.0);\nfloat depth1=texture2D(textureSampler,coords+offset1).r;\nfloat depth2=texture2D(textureSampler,coords+offset2).r;\nvec3 p1=vec3(offset1,depth1-depth);\nvec3 p2=vec3(offset2,depth2-depth);\nvec3 normal=cross(p1,p2);\nnormal.z=-normal.z;\nreturn normalize(normal);\n}\nvoid main()\n{\nvec3 random=normalize(texture2D(randomSampler,vUV*randTextureTiles).rgb);\nfloat depth=texture2D(textureSampler,vUV).r;\nvec3 position=vec3(vUV,depth);\nvec3 normal=normalFromDepth(depth,vUV);\nfloat radiusDepth=radius/depth;\nfloat occlusion=0.0;\nvec3 ray;\nvec3 hemiRay;\nfloat occlusionDepth;\nfloat difference;\nfor (int i=0; imaxZ) {\ngl_FragColor=vec4(1.0,1.0,1.0,1.0);\nreturn;\n}\nfor (int i=0; i1.0 || offset.y>1.0) {\ncontinue;\n}\n\nfloat sampleDepth=abs(texture2D(textureSampler,offset.xy).r);\n\nfloat rangeCheck=abs(depth-sampleDepth)=1e-5 ? 1.0 : 0.0)*rangeCheck;\n}\n\nfloat ao=1.0-totalStrength*occlusion*samplesFactor;\nfloat result=clamp(ao+base,0.0,1.0);\ngl_FragColor=vec4(vec3(result),1.0);\n}\n#endif\n#ifdef BILATERAL_BLUR\nuniform sampler2D depthSampler;\nuniform float outSize;\nuniform float samplerOffsets[SAMPLES];\nvec4 blur9(sampler2D image,vec2 uv,float resolution,vec2 direction) {\nvec4 color=vec4(0.0);\nvec2 off1=vec2(1.3846153846)*direction;\nvec2 off2=vec2(3.2307692308)*direction;\ncolor+=texture2D(image,uv)*0.2270270270;\ncolor+=texture2D(image,uv+(off1/resolution))*0.3162162162;\ncolor+=texture2D(image,uv-(off1/resolution))*0.3162162162;\ncolor+=texture2D(image,uv+(off2/resolution))*0.0702702703;\ncolor+=texture2D(image,uv-(off2/resolution))*0.0702702703;\nreturn color;\n}\nvec4 blur13(sampler2D image,vec2 uv,float resolution,vec2 direction) {\nvec4 color=vec4(0.0);\nvec2 off1=vec2(1.411764705882353)*direction;\nvec2 off2=vec2(3.2941176470588234)*direction;\nvec2 off3=vec2(5.176470588235294)*direction;\ncolor+=texture2D(image,uv)*0.1964825501511404;\ncolor+=texture2D(image,uv+(off1/resolution))*0.2969069646728344;\ncolor+=texture2D(image,uv-(off1/resolution))*0.2969069646728344;\ncolor+=texture2D(image,uv+(off2/resolution))*0.09447039785044732;\ncolor+=texture2D(image,uv-(off2/resolution))*0.09447039785044732;\ncolor+=texture2D(image,uv+(off3/resolution))*0.010381362401148057;\ncolor+=texture2D(image,uv-(off3/resolution))*0.010381362401148057;\nreturn color;\n}\nvec4 blur13Bilateral(sampler2D image,vec2 uv,float resolution,vec2 direction) {\nvec4 color=vec4(0.0);\nvec2 off1=vec2(1.411764705882353)*direction;\nvec2 off2=vec2(3.2941176470588234)*direction;\nvec2 off3=vec2(5.176470588235294)*direction;\nfloat compareDepth=abs(texture2D(depthSampler,uv).r);\nfloat sampleDepth;\nfloat weight;\nfloat weightSum=30.0;\ncolor+=texture2D(image,uv)*30.0;\nsampleDepth=abs(texture2D(depthSampler,uv+(off1/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv+(off1/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv-(off1/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv-(off1/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv+(off2/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv+(off2/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv-(off2/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv-(off2/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv+(off3/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv+(off3/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv-(off3/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv-(off3/resolution))*weight;\nreturn color/weightSum;\n}\nvoid main()\n{\n#if EXPENSIVE\nfloat compareDepth=abs(texture2D(depthSampler,vUV).r);\nfloat texelsize=1.0/outSize;\nfloat result=0.0;\nfloat weightSum=0.0;\nfor (int i=0; i1.0) { lum_threshold=0.94+0.01*threshold; }\nelse { lum_threshold=0.5+0.44*threshold; }\nluminance=clamp((luminance-lum_threshold)*(1.0/(1.0-lum_threshold)),0.0,1.0);\nhighlight*=luminance*gain;\nhighlight.a=1.0;\nreturn highlight;\n}\nvoid main(void)\n{\nvec4 original=texture2D(textureSampler,vUV);\n\nif (gain == -1.0) {\ngl_FragColor=vec4(0.0,0.0,0.0,1.0);\nreturn;\n}\nfloat w=2.0/screen_width;\nfloat h=2.0/screen_height;\nfloat weight=1.0;\n\nvec4 blurred=vec4(0.0,0.0,0.0,0.0);\n#ifdef PENTAGON\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.84*w,0.43*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.48*w,-1.29*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.61*w,1.51*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.55*w,-0.74*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.71*w,-0.52*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.94*w,1.59*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.40*w,-1.87*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.62*w,1.16*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.09*w,0.25*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.46*w,-1.71*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.08*w,2.42*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.85*w,-1.89*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.89*w,0.16*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.29*w,1.88*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.40*w,-2.81*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.54*w,2.26*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.60*w,-0.61*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.31*w,-1.30*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.83*w,2.53*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.12*w,-2.48*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.60*w,1.11*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.82*w,0.99*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.50*w,-2.81*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.85*w,3.33*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.94*w,-1.92*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.27*w,-0.53*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.95*w,2.48*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.23*w,-3.04*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.17*w,2.05*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.97*w,-0.04*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.25*w,-2.00*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.31*w,3.08*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.94*w,-2.59*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.37*w,0.64*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-3.13*w,1.93*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.03*w,-3.65*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.60*w,3.17*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-3.14*w,-1.19*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.00*w,-1.19*h)));\n#else\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.85*w,0.36*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.52*w,-1.14*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.46*w,1.42*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.46*w,-0.83*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.79*w,-0.42*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.11*w,1.62*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.29*w,-2.07*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.69*w,1.39*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.28*w,0.12*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.65*w,-1.69*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.08*w,2.44*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.63*w,-1.90*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.55*w,0.31*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.13*w,1.52*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.56*w,-2.61*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.38*w,2.34*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.64*w,-0.81*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.53*w,-1.21*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.06*w,2.63*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.00*w,-2.69*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.59*w,1.32*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.82*w,0.78*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.57*w,-2.50*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.54*w,2.93*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.39*w,-1.81*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.01*w,-0.28*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.04*w,2.25*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.02*w,-3.05*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.09*w,2.25*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-3.07*w,-0.25*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.44*w,-1.90*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.52*w,3.05*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.68*w,-2.61*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.01*w,0.79*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.76*w,1.46*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.05*w,-2.94*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.21*w,2.88*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.84*w,-1.30*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.98*w,-0.96*h)));\n#endif\nblurred/=39.0;\ngl_FragColor=blurred;\n\n}","depthOfFieldPixelShader":"\n\n\n\n\nuniform sampler2D textureSampler;\nuniform sampler2D highlightsSampler;\nuniform sampler2D depthSampler;\nuniform sampler2D grainSampler;\n\nuniform float grain_amount;\nuniform bool blur_noise;\nuniform float screen_width;\nuniform float screen_height;\nuniform float distortion;\nuniform bool dof_enabled;\n\nuniform float screen_distance; \nuniform float aperture;\nuniform float darken;\nuniform float edge_blur;\nuniform bool highlights;\n\nuniform float near;\nuniform float far;\n\nvarying vec2 vUV;\n\n#define PI 3.14159265\n#define TWOPI 6.28318530\n#define inverse_focal_length 0.1 \n\nvec2 centered_screen_pos;\nvec2 distorted_coords;\nfloat radius2;\nfloat radius;\n\nvec2 rand(vec2 co)\n{\nfloat noise1=(fract(sin(dot(co,vec2(12.9898,78.233)))*43758.5453));\nfloat noise2=(fract(sin(dot(co,vec2(12.9898,78.233)*2.0))*43758.5453));\nreturn clamp(vec2(noise1,noise2),0.0,1.0);\n}\n\nvec2 getDistortedCoords(vec2 coords) {\nif (distortion == 0.0) { return coords; }\nvec2 direction=1.0*normalize(centered_screen_pos);\nvec2 dist_coords=vec2(0.5,0.5);\ndist_coords.x=0.5+direction.x*radius2*1.0;\ndist_coords.y=0.5+direction.y*radius2*1.0;\nfloat dist_amount=clamp(distortion*0.23,0.0,1.0);\ndist_coords=mix(coords,dist_coords,dist_amount);\nreturn dist_coords;\n}\n\nfloat sampleScreen(inout vec4 color,const in vec2 offset,const in float weight) {\n\nvec2 coords=distorted_coords;\nfloat angle=rand(coords*100.0).x*TWOPI;\ncoords+=vec2(offset.x*cos(angle)-offset.y*sin(angle),offset.x*sin(angle)+offset.y*cos(angle));\ncolor+=texture2D(textureSampler,coords)*weight;\nreturn weight;\n}\n\nfloat getBlurLevel(float size) {\nreturn min(3.0,ceil(size/1.0));\n}\n\nvec4 getBlurColor(float size) {\nvec4 col=texture2D(textureSampler,distorted_coords);\nif (size == 0.0) { return col; }\n\n\nfloat blur_level=getBlurLevel(size);\nfloat w=(size/screen_width);\nfloat h=(size/screen_height);\nfloat total_weight=1.0;\nvec2 sample_coords;\ntotal_weight+=sampleScreen(col,vec2(-0.50*w,0.24*h),0.93);\ntotal_weight+=sampleScreen(col,vec2(0.30*w,-0.75*h),0.90);\ntotal_weight+=sampleScreen(col,vec2(0.36*w,0.96*h),0.87);\ntotal_weight+=sampleScreen(col,vec2(-1.08*w,-0.55*h),0.85);\ntotal_weight+=sampleScreen(col,vec2(1.33*w,-0.37*h),0.83);\ntotal_weight+=sampleScreen(col,vec2(-0.82*w,1.31*h),0.80);\ntotal_weight+=sampleScreen(col,vec2(-0.31*w,-1.67*h),0.78);\ntotal_weight+=sampleScreen(col,vec2(1.47*w,1.11*h),0.76);\ntotal_weight+=sampleScreen(col,vec2(-1.97*w,0.19*h),0.74);\ntotal_weight+=sampleScreen(col,vec2(1.42*w,-1.57*h),0.72);\nif (blur_level>1.0) {\ntotal_weight+=sampleScreen(col,vec2(0.01*w,2.25*h),0.70);\ntotal_weight+=sampleScreen(col,vec2(-1.62*w,-1.74*h),0.67);\ntotal_weight+=sampleScreen(col,vec2(2.49*w,0.20*h),0.65);\ntotal_weight+=sampleScreen(col,vec2(-2.07*w,1.61*h),0.63);\ntotal_weight+=sampleScreen(col,vec2(0.46*w,-2.70*h),0.61);\ntotal_weight+=sampleScreen(col,vec2(1.55*w,2.40*h),0.59);\ntotal_weight+=sampleScreen(col,vec2(-2.88*w,-0.75*h),0.56);\ntotal_weight+=sampleScreen(col,vec2(2.73*w,-1.44*h),0.54);\ntotal_weight+=sampleScreen(col,vec2(-1.08*w,3.02*h),0.52);\ntotal_weight+=sampleScreen(col,vec2(-1.28*w,-3.05*h),0.49);\n}\nif (blur_level>2.0) {\ntotal_weight+=sampleScreen(col,vec2(3.11*w,1.43*h),0.46);\ntotal_weight+=sampleScreen(col,vec2(-3.36*w,1.08*h),0.44);\ntotal_weight+=sampleScreen(col,vec2(1.80*w,-3.16*h),0.41);\ntotal_weight+=sampleScreen(col,vec2(0.83*w,3.65*h),0.38);\ntotal_weight+=sampleScreen(col,vec2(-3.16*w,-2.19*h),0.34);\ntotal_weight+=sampleScreen(col,vec2(3.92*w,-0.53*h),0.31);\ntotal_weight+=sampleScreen(col,vec2(-2.59*w,3.12*h),0.26);\ntotal_weight+=sampleScreen(col,vec2(-0.20*w,-4.15*h),0.22);\ntotal_weight+=sampleScreen(col,vec2(3.02*w,3.00*h),0.15);\n}\ncol/=total_weight; \n\nif (darken>0.0) {\ncol.rgb*=clamp(0.3,1.0,1.05-size*0.5*darken);\n}\n\n\n\n\nreturn col;\n}\nvoid main(void)\n{\n\ncentered_screen_pos=vec2(vUV.x-0.5,vUV.y-0.5);\nradius2=centered_screen_pos.x*centered_screen_pos.x+centered_screen_pos.y*centered_screen_pos.y;\nradius=sqrt(radius2);\ndistorted_coords=getDistortedCoords(vUV); \nvec2 texels_coords=vec2(vUV.x*screen_width,vUV.y*screen_height); \nfloat depth=texture2D(depthSampler,distorted_coords).r; \nfloat distance=near+(far-near)*depth; \nvec4 color=texture2D(textureSampler,vUV); \n\n\nfloat coc=abs(aperture*(screen_distance*(inverse_focal_length-1.0/distance)-1.0));\n\nif (dof_enabled == false || coc<0.07) { coc=0.0; }\n\nfloat edge_blur_amount=0.0;\nif (edge_blur>0.0) {\nedge_blur_amount=clamp((radius*2.0-1.0+0.15*edge_blur)*1.5,0.0,1.0)*1.3;\n}\n\nfloat blur_amount=max(edge_blur_amount,coc);\n\nif (blur_amount == 0.0) {\ngl_FragColor=texture2D(textureSampler,distorted_coords);\n}\nelse {\n\ngl_FragColor=getBlurColor(blur_amount*1.7);\n\nif (highlights) {\ngl_FragColor.rgb+=clamp(coc,0.0,1.0)*texture2D(highlightsSampler,distorted_coords).rgb;\n}\nif (blur_noise) {\n\nvec2 noise=rand(distorted_coords)*0.01*blur_amount;\nvec2 blurred_coord=vec2(distorted_coords.x+noise.x,distorted_coords.y+noise.y);\ngl_FragColor=0.04*texture2D(textureSampler,blurred_coord)+0.96*gl_FragColor;\n}\n}\n\nif (grain_amount>0.0) {\nvec4 grain_color=texture2D(grainSampler,texels_coords*0.003);\ngl_FragColor.rgb+=(-0.5+grain_color.rgb)*0.30*grain_amount;\n}\n}\n","standardPixelShader":"uniform sampler2D textureSampler;\nvarying vec2 vUV;\n#if defined(PASS_POST_PROCESS)\nvoid main(void)\n{\nvec4 color=texture2D(textureSampler,vUV);\ngl_FragColor=color;\n}\n#endif\n#if defined(DOWN_SAMPLE_X4)\nuniform vec2 dsOffsets[16];\nvoid main(void)\n{\nvec4 average=vec4(0.0,0.0,0.0,0.0);\naverage=texture2D(textureSampler,vUV+dsOffsets[0]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[1]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[2]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[3]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[4]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[5]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[6]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[7]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[8]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[9]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[10]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[11]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[12]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[13]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[14]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[15]);\naverage/=16.0;\ngl_FragColor=average;\n}\n#endif\n#if defined(BRIGHT_PASS)\nuniform vec2 dsOffsets[4];\nuniform float brightThreshold;\nvoid main(void)\n{\nvec4 average=vec4(0.0,0.0,0.0,0.0);\naverage=texture2D(textureSampler,vUV+vec2(dsOffsets[0].x,dsOffsets[0].y));\naverage+=texture2D(textureSampler,vUV+vec2(dsOffsets[1].x,dsOffsets[1].y));\naverage+=texture2D(textureSampler,vUV+vec2(dsOffsets[2].x,dsOffsets[2].y));\naverage+=texture2D(textureSampler,vUV+vec2(dsOffsets[3].x,dsOffsets[3].y));\naverage*=0.25;\nfloat luminance=length(average.rgb);\nif (luminanceshadowPixelDepth)\naccumFog+=sunColor*computeScattering(dot(rayDirection,sunDirection));\ncurrentPosition+=stepL;\n}\naccumFog/=NB_STEPS;\nvec3 color=accumFog*scatteringPower;\ngl_FragColor=vec4(color*exp(color) ,1.0);\n}\n#endif\n#if defined(VLSMERGE)\nuniform sampler2D originalSampler;\nvoid main(void)\n{\ngl_FragColor=texture2D(originalSampler,vUV)+texture2D(textureSampler,vUV);\n}\n#endif\n#if defined(LUMINANCE)\nuniform vec2 lumOffsets[4];\nvoid main()\n{\nfloat average=0.0;\nvec4 color=vec4(0.0);\nfloat maximum=-1e20;\nvec3 weight=vec3(0.299,0.587,0.114);\nfor (int i=0; i<4; i++)\n{\ncolor=texture2D(textureSampler,vUV+ lumOffsets[i]);\n\nfloat GreyValue=dot(color.rgb,vec3(0.33,0.33,0.33));\n\n#ifdef WEIGHTED_AVERAGE\nfloat GreyValue=dot(color.rgb,weight);\n#endif\n#ifdef BRIGHTNESS\nfloat GreyValue=max(color.r,max(color.g,color.b));\n#endif\n#ifdef HSL_COMPONENT\nfloat GreyValue=0.5*(max(color.r,max(color.g,color.b))+min(color.r,min(color.g,color.b)));\n#endif\n#ifdef MAGNITUDE\nfloat GreyValue=length(color.rgb);\n#endif\nmaximum=max(maximum,GreyValue);\naverage+=(0.25*log(1e-5+GreyValue));\n}\naverage=exp(average);\ngl_FragColor=vec4(average,maximum,0.0,1.0);\n}\n#endif\n#if defined(LUMINANCE_DOWN_SAMPLE)\nuniform vec2 dsOffsets[9];\nuniform float halfDestPixelSize;\n#ifdef FINAL_DOWN_SAMPLER\nvec4 pack(float value) {\nconst vec4 bit_shift=vec4(255.0*255.0*255.0,255.0*255.0,255.0,1.0);\nconst vec4 bit_mask=vec4(0.0,1.0/255.0,1.0/255.0,1.0/255.0);\nvec4 res=fract(value*bit_shift);\nres-=res.xxyz*bit_mask;\nreturn res;\n}\n#endif\nvoid main()\n{\nvec4 color=vec4(0.0);\nfloat average=0.0;\nfor (int i=0; i<9; i++)\n{\ncolor=texture2D(textureSampler,vUV+vec2(halfDestPixelSize,halfDestPixelSize)+dsOffsets[i]);\naverage+=color.r;\n}\naverage/=9.0;\n#ifdef FINAL_DOWN_SAMPLER\ngl_FragColor=pack(average);\n#else\ngl_FragColor=vec4(average,average,0.0,1.0);\n#endif\n}\n#endif\n#if defined(HDR)\nuniform sampler2D textureAdderSampler;\nuniform float averageLuminance;\nvoid main()\n{\nvec4 color=texture2D(textureAdderSampler,vUV);\nvec4 adjustedColor=color/averageLuminance;\ncolor=adjustedColor;\ncolor.a=1.0;\ngl_FragColor=color;\n}\n#endif\n#if defined(LENS_FLARE)\n#define GHOSTS 3\nuniform sampler2D lensColorSampler;\nuniform float strength;\nuniform float ghostDispersal;\nuniform float haloWidth;\nuniform vec2 resolution;\nuniform float distortionStrength;\nfloat hash(vec2 p)\n{\nfloat h=dot(p,vec2(127.1,311.7));\nreturn -1.0+2.0*fract(sin(h)*43758.5453123);\n}\nfloat noise(in vec2 p)\n{\nvec2 i=floor(p);\nvec2 f=fract(p);\nvec2 u=f*f*(3.0-2.0*f);\nreturn mix(mix(hash(i+vec2(0.0,0.0)),\nhash(i+vec2(1.0,0.0)),u.x),\nmix(hash(i+vec2(0.0,1.0)),\nhash(i+vec2(1.0,1.0)),u.x),u.y);\n}\nfloat fbm(vec2 p)\n{\nfloat f=0.0;\nf+=0.5000*noise(p); p*=2.02;\nf+=0.2500*noise(p); p*=2.03;\nf+=0.1250*noise(p); p*=2.01;\nf+=0.0625*noise(p); p*=2.04;\nf/=0.9375;\nreturn f;\n}\nvec3 pattern(vec2 uv)\n{\nvec2 p=-1.0+2.0*uv;\nfloat p2=dot(p,p);\nfloat f=fbm(vec2(15.0*p2))/2.0;\nfloat r=0.2+0.6*sin(12.5*length(uv-vec2(0.5)));\nfloat g=0.2+0.6*sin(20.5*length(uv-vec2(0.5)));\nfloat b=0.2+0.6*sin(17.2*length(uv-vec2(0.5)));\nreturn (1.0-f)*vec3(r,g,b);\n}\nfloat luminance(vec3 color)\n{\nreturn dot(color.rgb,vec3(0.2126,0.7152,0.0722));\n}\nvec4 textureDistorted(sampler2D tex,vec2 texcoord,vec2 direction,vec3 distortion)\n{\nreturn vec4(\ntexture2D(tex,texcoord+direction*distortion.r).r,\ntexture2D(tex,texcoord+direction*distortion.g).g,\ntexture2D(tex,texcoord+direction*distortion.b).b,\n1.0\n);\n}\nvoid main(void)\n{\nvec2 uv=-vUV+vec2(1.0);\nvec2 ghostDir=(vec2(0.5)-uv)*ghostDispersal;\nvec2 texelSize=1.0/resolution;\nvec3 distortion=vec3(-texelSize.x*distortionStrength,0.0,texelSize.x*distortionStrength);\nvec4 result=vec4(0.0);\nfloat ghostIndice=1.0;\nfor (int i=0; i=nSamples)\nbreak;\nvec2 offset1=vUV+velocity*(float(i)/float(nSamples-1)-0.5);\nresult+=texture2D(textureSampler,offset1);\n}\ngl_FragColor=result/float(nSamples);\n}\n#endif\n","fxaaVertexShader":"\nattribute vec2 position;\nuniform vec2 texelSize;\n\nvarying vec2 vUV;\nvarying vec2 sampleCoordS;\nvarying vec2 sampleCoordE;\nvarying vec2 sampleCoordN;\nvarying vec2 sampleCoordW;\nvarying vec2 sampleCoordNW;\nvarying vec2 sampleCoordSE;\nvarying vec2 sampleCoordNE;\nvarying vec2 sampleCoordSW;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvUV=(position*madd+madd);\nsampleCoordS=vUV+vec2( 0.0,1.0)*texelSize;\nsampleCoordE=vUV+vec2( 1.0,0.0)*texelSize;\nsampleCoordN=vUV+vec2( 0.0,-1.0)*texelSize;\nsampleCoordW=vUV+vec2(-1.0,0.0)*texelSize;\nsampleCoordNW=vUV+vec2(-1.0,-1.0)*texelSize;\nsampleCoordSE=vUV+vec2( 1.0,1.0)*texelSize;\nsampleCoordNE=vUV+vec2( 1.0,-1.0)*texelSize;\nsampleCoordSW=vUV+vec2(-1.0,1.0)*texelSize;\ngl_Position=vec4(position,0.0,1.0);\n}","fxaaPixelShader":"uniform sampler2D textureSampler;\nuniform vec2 texelSize;\nvarying vec2 vUV;\nvarying vec2 sampleCoordS;\nvarying vec2 sampleCoordE;\nvarying vec2 sampleCoordN;\nvarying vec2 sampleCoordW;\nvarying vec2 sampleCoordNW;\nvarying vec2 sampleCoordSE;\nvarying vec2 sampleCoordNE;\nvarying vec2 sampleCoordSW;\nconst float fxaaQualitySubpix=1.0;\nconst float fxaaQualityEdgeThreshold=0.166;\nconst float fxaaQualityEdgeThresholdMin=0.0833;\nconst vec3 kLumaCoefficients=vec3(0.2126,0.7152,0.0722);\n#define FxaaLuma(rgba) dot(rgba.rgb,kLumaCoefficients)\nvoid main(){\nvec2 posM;\nposM.x=vUV.x;\nposM.y=vUV.y;\nvec4 rgbyM=texture2D(textureSampler,vUV,0.0);\nfloat lumaM=FxaaLuma(rgbyM);\nfloat lumaS=FxaaLuma(texture2D(textureSampler,sampleCoordS,0.0));\nfloat lumaE=FxaaLuma(texture2D(textureSampler,sampleCoordE,0.0));\nfloat lumaN=FxaaLuma(texture2D(textureSampler,sampleCoordN,0.0));\nfloat lumaW=FxaaLuma(texture2D(textureSampler,sampleCoordW,0.0));\nfloat maxSM=max(lumaS,lumaM);\nfloat minSM=min(lumaS,lumaM);\nfloat maxESM=max(lumaE,maxSM);\nfloat minESM=min(lumaE,minSM);\nfloat maxWN=max(lumaN,lumaW);\nfloat minWN=min(lumaN,lumaW);\nfloat rangeMax=max(maxWN,maxESM);\nfloat rangeMin=min(minWN,minESM);\nfloat rangeMaxScaled=rangeMax*fxaaQualityEdgeThreshold;\nfloat range=rangeMax-rangeMin;\nfloat rangeMaxClamped=max(fxaaQualityEdgeThresholdMin,rangeMaxScaled);\n#ifndef MALI\nif(range=edgeVert;\nfloat subpixA=subpixNSWE*2.0+subpixNWSWNESE;\nif (!horzSpan)\n{\nlumaN=lumaW;\n}\nif (!horzSpan) \n{\nlumaS=lumaE;\n}\nif (horzSpan) \n{\nlengthSign=texelSize.y;\n}\nfloat subpixB=(subpixA*(1.0/12.0))-lumaM;\nfloat gradientN=lumaN-lumaM;\nfloat gradientS=lumaS-lumaM;\nfloat lumaNN=lumaN+lumaM;\nfloat lumaSS=lumaS+lumaM;\nbool pairN=abs(gradientN)>=abs(gradientS);\nfloat gradient=max(abs(gradientN),abs(gradientS));\nif (pairN)\n{\nlengthSign=-lengthSign;\n}\nfloat subpixC=clamp(abs(subpixB)*subpixRcpRange,0.0,1.0);\nvec2 posB;\nposB.x=posM.x;\nposB.y=posM.y;\nvec2 offNP;\noffNP.x=(!horzSpan) ? 0.0 : texelSize.x;\noffNP.y=(horzSpan) ? 0.0 : texelSize.y;\nif (!horzSpan) \n{\nposB.x+=lengthSign*0.5;\n}\nif (horzSpan)\n{\nposB.y+=lengthSign*0.5;\n}\nvec2 posN;\nposN.x=posB.x-offNP.x*1.5;\nposN.y=posB.y-offNP.y*1.5;\nvec2 posP;\nposP.x=posB.x+offNP.x*1.5;\nposP.y=posB.y+offNP.y*1.5;\nfloat subpixD=((-2.0)*subpixC)+3.0;\nfloat lumaEndN=FxaaLuma(texture2D(textureSampler,posN,0.0));\nfloat subpixE=subpixC*subpixC;\nfloat lumaEndP=FxaaLuma(texture2D(textureSampler,posP,0.0));\nif (!pairN) \n{\nlumaNN=lumaSS;\n}\nfloat gradientScaled=gradient*1.0/4.0;\nfloat lumaMM=lumaM-lumaNN*0.5;\nfloat subpixF=subpixD*subpixE;\nbool lumaMLTZero=lumaMM<0.0;\nlumaEndN-=lumaNN*0.5;\nlumaEndP-=lumaNN*0.5;\nbool doneN=abs(lumaEndN)>=gradientScaled;\nbool doneP=abs(lumaEndP)>=gradientScaled;\nif (!doneN) \n{\nposN.x-=offNP.x*3.0;\n}\nif (!doneN) \n{\nposN.y-=offNP.y*3.0;\n}\nbool doneNP=(!doneN) || (!doneP);\nif (!doneP) \n{\nposP.x+=offNP.x*3.0;\n}\nif (!doneP)\n{\nposP.y+=offNP.y*3.0;\n}\nif (doneNP)\n{\nif (!doneN) lumaEndN=FxaaLuma(texture2D(textureSampler,posN.xy,0.0));\nif (!doneP) lumaEndP=FxaaLuma(texture2D(textureSampler,posP.xy,0.0));\nif (!doneN) lumaEndN=lumaEndN-lumaNN*0.5;\nif (!doneP) lumaEndP=lumaEndP-lumaNN*0.5;\ndoneN=abs(lumaEndN)>=gradientScaled;\ndoneP=abs(lumaEndP)>=gradientScaled;\nif (!doneN) posN.x-=offNP.x*12.0;\nif (!doneN) posN.y-=offNP.y*12.0;\ndoneNP=(!doneN) || (!doneP);\nif (!doneP) posP.x+=offNP.x*12.0;\nif (!doneP) posP.y+=offNP.y*12.0;\n}\nfloat dstN=posM.x-posN.x;\nfloat dstP=posP.x-posM.x;\nif (!horzSpan)\n{\ndstN=posM.y-posN.y;\n}\nif (!horzSpan) \n{\ndstP=posP.y-posM.y;\n}\nbool goodSpanN=(lumaEndN<0.0) != lumaMLTZero;\nfloat spanLength=(dstP+dstN);\nbool goodSpanP=(lumaEndP<0.0) != lumaMLTZero;\nfloat spanLengthRcp=1.0/spanLength;\nbool directionN=dstN\n\nuniform sampler2D textureSampler; \n\nuniform float intensity;\nuniform float animatedSeed;\n\nvarying vec2 vUV;\nvoid main(void)\n{\ngl_FragColor=texture2D(textureSampler,vUV);\nvec2 seed=vUV*(animatedSeed);\nfloat grain=dither(seed,intensity);\n\nfloat lum=getLuminance(gl_FragColor.rgb);\nfloat grainAmount=(cos(-PI+(lum*PI*2.))+1.)/2.;\ngl_FragColor.rgb+=grain*grainAmount;\ngl_FragColor.rgb=max(gl_FragColor.rgb,0.0);\n}","sharpenPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform vec2 screenSize;\nuniform vec2 sharpnessAmounts;\nvoid main(void)\n{\nvec2 onePixel=vec2(1.0,1.0)/screenSize;\nvec4 color=texture2D(textureSampler,vUV);\nvec4 edgeDetection=texture2D(textureSampler,vUV+onePixel*vec2(0,-1)) +\ntexture2D(textureSampler,vUV+onePixel*vec2(-1,0)) +\ntexture2D(textureSampler,vUV+onePixel*vec2(1,0)) +\ntexture2D(textureSampler,vUV+onePixel*vec2(0,1)) -\ncolor*4.0;\ngl_FragColor=max(vec4(color.rgb*sharpnessAmounts.y,color.a)-(sharpnessAmounts.x*vec4(edgeDetection.rgb,0)),0.);\n}","kernelBlurVertexShader":"\nattribute vec2 position;\n\nuniform vec2 delta;\n\nvarying vec2 sampleCenter;\n#include[0..varyingCount]\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nsampleCenter=(position*madd+madd);\n#include[0..varyingCount]\ngl_Position=vec4(position,0.0,1.0);\n}","kernelBlurPixelShader":"\nuniform sampler2D textureSampler;\nuniform vec2 delta;\n\nvarying vec2 sampleCenter;\n#ifdef DOF\nuniform sampler2D circleOfConfusionSampler;\nuniform vec2 cameraMinMaxZ;\nfloat sampleDistance(const in vec2 offset) {\nfloat depth=texture2D(circleOfConfusionSampler,offset).g; \nreturn cameraMinMaxZ.x+(cameraMinMaxZ.y-cameraMinMaxZ.x)*depth; \n}\nfloat sampleCoC(const in vec2 offset) {\nfloat coc=texture2D(circleOfConfusionSampler,offset).r; \nreturn coc; \n}\n#endif\n#include[0..varyingCount]\n#ifdef PACKEDFLOAT\nvec4 pack(float depth)\n{\nconst vec4 bit_shift=vec4(255.0*255.0*255.0,255.0*255.0,255.0,1.0);\nconst vec4 bit_mask=vec4(0.0,1.0/255.0,1.0/255.0,1.0/255.0);\nvec4 res=fract(depth*bit_shift);\nres-=res.xxyz*bit_mask;\nreturn res;\n}\nfloat unpack(vec4 color)\n{\nconst vec4 bit_shift=vec4(1.0/(255.0*255.0*255.0),1.0/(255.0*255.0),1.0/255.0,1.0);\nreturn dot(color,bit_shift);\n}\n#endif\nvoid main(void)\n{\nfloat computedWeight=0.0;\n#ifdef PACKEDFLOAT \nfloat blend=0.;\n#else\nvec4 blend=vec4(0.);\n#endif\n#ifdef DOF\nfloat sumOfWeights=CENTER_WEIGHT; \nfloat factor=0.0;\n\n#ifdef PACKEDFLOAT\nblend+=unpack(texture2D(textureSampler,sampleCenter))*CENTER_WEIGHT;\n#else\nblend+=texture2D(textureSampler,sampleCenter)*CENTER_WEIGHT;\n#endif\n#endif\n#include[0..varyingCount]\n#include[0..depCount]\n#ifdef PACKEDFLOAT\ngl_FragColor=pack(blend);\n#else\ngl_FragColor=blend;\n#endif\n#ifdef DOF\ngl_FragColor/=sumOfWeights;\n#endif\n}","depthOfFieldMergePixelShader":"uniform sampler2D textureSampler;\nvarying vec2 vUV;\nuniform sampler2D circleOfConfusionSampler;\nuniform sampler2D blurStep0;\n#if BLUR_LEVEL>0\nuniform sampler2D blurStep1;\n#endif\n#if BLUR_LEVEL>1\nuniform sampler2D blurStep2;\n#endif\nvoid main(void)\n{\nfloat coc=texture2D(circleOfConfusionSampler,vUV).r;\n#if BLUR_LEVEL == 0\nvec4 original=texture2D(textureSampler,vUV);\nvec4 blurred0=texture2D(blurStep0,vUV);\ngl_FragColor=mix(original,blurred0,coc);\n#endif\n#if BLUR_LEVEL == 1\nif(coc<0.5){\nvec4 original=texture2D(textureSampler,vUV);\nvec4 blurred1=texture2D(blurStep1,vUV);\ngl_FragColor=mix(original,blurred1,coc/0.5);\n}else{\nvec4 blurred0=texture2D(blurStep0,vUV); \nvec4 blurred1=texture2D(blurStep1,vUV);\ngl_FragColor=mix(blurred1,blurred0,(coc-0.5)/0.5);\n}\n#endif\n#if BLUR_LEVEL == 2\nif(coc<0.33){\nvec4 original=texture2D(textureSampler,vUV);\nvec4 blurred2=texture2D(blurStep2,vUV);\ngl_FragColor=mix(original,blurred2,coc/0.33);\n}else if(coc<0.66){\nvec4 blurred1=texture2D(blurStep1,vUV);\nvec4 blurred2=texture2D(blurStep2,vUV);\ngl_FragColor=mix(blurred2,blurred1,(coc-0.33)/0.33);\n}else{\nvec4 blurred0=texture2D(blurStep0,vUV);\nvec4 blurred1=texture2D(blurStep1,vUV);\ngl_FragColor=mix(blurred1,blurred0,(coc-0.66)/0.34);\n}\n#endif\n}\n","circleOfConfusionPixelShader":"\nuniform sampler2D depthSampler;\n\nvarying vec2 vUV;\n\nuniform vec2 cameraMinMaxZ;\n\nuniform float focusDistance;\nuniform float cocPrecalculation;\nvoid main(void)\n{\nfloat depth=texture2D(depthSampler,vUV).r;\nfloat pixelDistance=(cameraMinMaxZ.x+(cameraMinMaxZ.y-cameraMinMaxZ.x)*depth)*1000.0; \nfloat coc=abs(cocPrecalculation* ((focusDistance-pixelDistance)/pixelDistance));\ncoc=clamp(coc,0.0,1.0);\ngl_FragColor=vec4(coc,depth,coc,1.0);\n}\n","bloomMergePixelShader":"uniform sampler2D textureSampler;\nuniform sampler2D bloomBlur;\nvarying vec2 vUV;\nuniform float bloomWeight;\nvoid main(void)\n{\ngl_FragColor=texture2D(textureSampler,vUV);\nvec3 blurred=texture2D(bloomBlur,vUV).rgb;\ngl_FragColor.rgb=gl_FragColor.rgb+(blurred.rgb*bloomWeight); \n}\n","extractHighlightsPixelShader":"#include\n\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform float threshold;\nuniform float exposure;\nvoid main(void) \n{\ngl_FragColor=texture2D(textureSampler,vUV);\nfloat luma=getLuminance(gl_FragColor.rgb*exposure);\ngl_FragColor.rgb=step(threshold,luma)*gl_FragColor.rgb;\n}","geometryVertexShader":"precision highp float;\nprecision highp int;\n#include\n#include\nattribute vec3 position;\nattribute vec3 normal;\n#if defined(ALPHATEST) || defined(NEED_UV)\nvarying vec2 vUV;\nuniform mat4 diffuseMatrix;\n#ifdef UV1\nvarying vec2 uv;\n#endif\n#ifdef UV2\nvarying vec2 uv2;\n#endif\n#endif\n\nuniform mat4 viewProjection;\nuniform mat4 view;\nvarying vec3 vNormalV;\nvarying vec4 vViewPos;\n#ifdef POSITION\nvarying vec3 vPosition;\n#endif\nvoid main(void)\n{\n#include\n#include\nvec4 pos=vec4(finalWorld*vec4(position,1.0));\nvNormalV=normalize(vec3((view*finalWorld)*vec4(normal,0.0)));\nvViewPos=view*pos;\n#ifdef POSITION\nvPosition=pos.xyz/pos.w;\n#endif\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\n#if defined(ALPHATEST) || defined(BASIC_RENDER)\n#ifdef UV1\nvUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef UV2\nvUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n}","geometryPixelShader":"#extension GL_EXT_draw_buffers : require\nprecision highp float;\nprecision highp int;\nvarying vec3 vNormalV;\nvarying vec4 vViewPos;\n#ifdef POSITION\nvarying vec3 vPosition;\n#endif\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n#endif\n#ifdef POSITION\n#include[3]\n#else\n#include[2]\n#endif\nvoid main() {\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUV).a<0.4)\ndiscard;\n#endif\ngl_FragData[0]=vec4(vViewPos.z/vViewPos.w,0.0,0.0,1.0);\n\ngl_FragData[1]=vec4(normalize(vNormalV),1.0);\n\n#ifdef POSITION\ngl_FragData[2]=vec4(vPosition,1.0);\n#endif\n}","refractionPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform sampler2D refractionSampler;\n\nuniform vec3 baseColor;\nuniform float depth;\nuniform float colorLevel;\nvoid main() {\nfloat ref=1.0-texture2D(refractionSampler,vUV).r;\nvec2 uv=vUV-vec2(0.5);\nvec2 offset=uv*depth*ref;\nvec3 sourceColor=texture2D(textureSampler,vUV-offset).rgb;\ngl_FragColor=vec4(sourceColor+sourceColor*ref*colorLevel,1.0);\n}","blackAndWhitePixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform float degree;\nvoid main(void) \n{\nvec3 color=texture2D(textureSampler,vUV).rgb;\nfloat luminance=dot(color,vec3(0.3,0.59,0.11)); \nvec3 blackAndWhite=vec3(luminance,luminance,luminance);\ngl_FragColor=vec4(color-((color-blackAndWhite)*degree),1.0);\n}","convolutionPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform vec2 screenSize;\nuniform float kernel[9];\nvoid main(void)\n{\nvec2 onePixel=vec2(1.0,1.0)/screenSize;\nvec4 colorSum =\ntexture2D(textureSampler,vUV+onePixel*vec2(-1,-1))*kernel[0] +\ntexture2D(textureSampler,vUV+onePixel*vec2(0,-1))*kernel[1] +\ntexture2D(textureSampler,vUV+onePixel*vec2(1,-1))*kernel[2] +\ntexture2D(textureSampler,vUV+onePixel*vec2(-1,0))*kernel[3] +\ntexture2D(textureSampler,vUV+onePixel*vec2(0,0))*kernel[4] +\ntexture2D(textureSampler,vUV+onePixel*vec2(1,0))*kernel[5] +\ntexture2D(textureSampler,vUV+onePixel*vec2(-1,1))*kernel[6] +\ntexture2D(textureSampler,vUV+onePixel*vec2(0,1))*kernel[7] +\ntexture2D(textureSampler,vUV+onePixel*vec2(1,1))*kernel[8];\nfloat kernelWeight =\nkernel[0] +\nkernel[1] +\nkernel[2] +\nkernel[3] +\nkernel[4] +\nkernel[5] +\nkernel[6] +\nkernel[7] +\nkernel[8];\nif (kernelWeight<=0.0) {\nkernelWeight=1.0;\n}\ngl_FragColor=vec4((colorSum/kernelWeight).rgb,1);\n}","filterPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform mat4 kernelMatrix;\nvoid main(void)\n{\nvec3 baseColor=texture2D(textureSampler,vUV).rgb;\nvec3 updatedColor=(kernelMatrix*vec4(baseColor,1.0)).rgb;\ngl_FragColor=vec4(updatedColor,1.0);\n}","volumetricLightScatteringPixelShader":"uniform sampler2D textureSampler;\nuniform sampler2D lightScatteringSampler;\nuniform float decay;\nuniform float exposure;\nuniform float weight;\nuniform float density;\nuniform vec2 meshPositionOnScreen;\nvarying vec2 vUV;\nvoid main(void) {\nvec2 tc=vUV;\nvec2 deltaTexCoord=(tc-meshPositionOnScreen.xy);\ndeltaTexCoord*=1.0/float(NUM_SAMPLES)*density;\nfloat illuminationDecay=1.0;\nvec4 color=texture2D(lightScatteringSampler,tc)*0.4;\nfor(int i=0; i\n#include\n#include\nvoid main(void)\n{\nvec4 result=texture2D(textureSampler,vUV);\n#ifdef IMAGEPROCESSING\n#ifndef FROMLINEARSPACE\n\nresult.rgb=toLinearSpace(result.rgb);\n#endif\nresult=applyImageProcessing(result);\n#else\n\n#ifdef FROMLINEARSPACE\nresult=applyImageProcessing(result);\n#endif\n#endif\ngl_FragColor=result;\n}","lensFlareVertexShader":"\nattribute vec2 position;\n\nuniform mat4 viewportMatrix;\n\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvUV=position*madd+madd;\ngl_Position=viewportMatrix*vec4(position,0.0,1.0);\n}","lensFlarePixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nuniform vec4 color;\nvoid main(void) {\nvec4 baseColor=texture2D(textureSampler,vUV);\ngl_FragColor=baseColor*color;\n}","anaglyphPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform sampler2D leftSampler;\nvoid main(void)\n{\nvec4 leftFrag=texture2D(leftSampler,vUV);\nleftFrag=vec4(1.0,leftFrag.g,leftFrag.b,1.0);\nvec4 rightFrag=texture2D(textureSampler,vUV);\nrightFrag=vec4(rightFrag.r,1.0,1.0,1.0);\ngl_FragColor=vec4(rightFrag.rgb*leftFrag.rgb,1.0);\n}","stereoscopicInterlacePixelShader":"const vec3 TWO=vec3(2.0,2.0,2.0);\nvarying vec2 vUV;\nuniform sampler2D camASampler;\nuniform sampler2D textureSampler;\nuniform vec2 stepSize;\nvoid main(void)\n{\nbool useCamB;\nvec2 texCoord1;\nvec2 texCoord2;\nvec3 frag1;\nvec3 frag2;\n#ifdef IS_STEREOSCOPIC_HORIZ\nuseCamB=vUV.x>0.5;\ntexCoord1=vec2(useCamB ? (vUV.x-0.5)*2.0 : vUV.x*2.0,vUV.y);\ntexCoord2=vec2(texCoord1.x+stepSize.x,vUV.y);\n#else\nuseCamB=vUV.y>0.5;\ntexCoord1=vec2(vUV.x,useCamB ? (vUV.y-0.5)*2.0 : vUV.y*2.0);\ntexCoord2=vec2(vUV.x,texCoord1.y+stepSize.y);\n#endif\n\nif (useCamB){\nfrag1=texture2D(textureSampler,texCoord1).rgb;\nfrag2=texture2D(textureSampler,texCoord2).rgb;\n}else{\nfrag1=texture2D(camASampler ,texCoord1).rgb;\nfrag2=texture2D(camASampler ,texCoord2).rgb;\n}\ngl_FragColor=vec4((frag1+frag2)/TWO,1.0);\n}","vrDistortionCorrectionPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform vec2 LensCenter;\nuniform vec2 Scale;\nuniform vec2 ScaleIn;\nuniform vec4 HmdWarpParam;\nvec2 HmdWarp(vec2 in01) {\nvec2 theta=(in01-LensCenter)*ScaleIn; \nfloat rSq=theta.x*theta.x+theta.y*theta.y;\nvec2 rvector=theta*(HmdWarpParam.x+HmdWarpParam.y*rSq+HmdWarpParam.z*rSq*rSq+HmdWarpParam.w*rSq*rSq*rSq);\nreturn LensCenter+Scale*rvector;\n}\nvoid main(void)\n{\nvec2 tc=HmdWarp(vUV);\nif (tc.x <0.0 || tc.x>1.0 || tc.y<0.0 || tc.y>1.0)\ngl_FragColor=vec4(0.0,0.0,0.0,0.0);\nelse{\ngl_FragColor=texture2D(textureSampler,tc);\n}\n}","glowBlurPostProcessPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nuniform vec2 screenSize;\nuniform vec2 direction;\nuniform float blurWidth;\n\nfloat getLuminance(vec3 color)\n{\nreturn dot(color,vec3(0.2126,0.7152,0.0722));\n}\nvoid main(void)\n{\nfloat weights[7];\nweights[0]=0.05;\nweights[1]=0.1;\nweights[2]=0.2;\nweights[3]=0.3;\nweights[4]=0.2;\nweights[5]=0.1;\nweights[6]=0.05;\nvec2 texelSize=vec2(1.0/screenSize.x,1.0/screenSize.y);\nvec2 texelStep=texelSize*direction*blurWidth;\nvec2 start=vUV-3.0*texelStep;\nvec4 baseColor=vec4(0.,0.,0.,0.);\nvec2 texelOffset=vec2(0.,0.);\nfor (int i=0; i<7; i++)\n{\n\nvec4 texel=texture2D(textureSampler,start+texelOffset);\nbaseColor.a+=texel.a*weights[i];\n\nfloat luminance=getLuminance(baseColor.rgb);\nfloat luminanceTexel=getLuminance(texel.rgb);\nfloat choice=step(luminanceTexel,luminance);\nbaseColor.rgb=choice*baseColor.rgb+(1.0-choice)*texel.rgb;\ntexelOffset+=texelStep;\n}\ngl_FragColor=baseColor;\n}","glowMapGenerationPixelShader":"#ifdef ALPHATEST\nvarying vec2 vUVDiffuse;\nuniform sampler2D diffuseSampler;\n#endif\n#ifdef EMISSIVE\nvarying vec2 vUVEmissive;\nuniform sampler2D emissiveSampler;\n#endif\nuniform vec4 color;\nvoid main(void)\n{\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUVDiffuse).a<0.4)\ndiscard;\n#endif\n#ifdef EMISSIVE\ngl_FragColor=texture2D(emissiveSampler,vUVEmissive)*color;\n#else\ngl_FragColor=color;\n#endif\n}","glowMapGenerationVertexShader":"\nattribute vec3 position;\n#include\n#include\n#include[0..maxSimultaneousMorphTargets]\n\n#include\nuniform mat4 viewProjection;\nvarying vec4 vPosition;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef ALPHATEST\nvarying vec2 vUVDiffuse;\nuniform mat4 diffuseMatrix;\n#endif\n#ifdef EMISSIVE\nvarying vec2 vUVEmissive;\nuniform mat4 emissiveMatrix;\n#endif\nvoid main(void)\n{\nvec3 positionUpdated=position;\n#include[0..maxSimultaneousMorphTargets]\n#include\n#include\n#ifdef CUBEMAP\nvPosition=finalWorld*vec4(positionUpdated,1.0);\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\n#else\nvPosition=viewProjection*finalWorld*vec4(positionUpdated,1.0);\ngl_Position=vPosition;\n#endif\n#ifdef ALPHATEST\n#ifdef DIFFUSEUV1\nvUVDiffuse=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef DIFFUSEUV2\nvUVDiffuse=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n#ifdef EMISSIVE\n#ifdef EMISSIVEUV1\nvUVEmissive=vec2(emissiveMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef EMISSIVEUV2\nvUVEmissive=vec2(emissiveMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n}","glowMapMergePixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n#ifdef EMISSIVE\nuniform sampler2D textureSampler2;\n#endif\n\nuniform float offset;\nvoid main(void) {\nvec4 baseColor=texture2D(textureSampler,vUV);\n#ifdef EMISSIVE\nbaseColor+=texture2D(textureSampler2,vUV);\nbaseColor*=offset;\n#else\nbaseColor.a=abs(offset-baseColor.a);\n#ifdef STROKE\nfloat alpha=smoothstep(.0,.1,baseColor.a);\nbaseColor.a=alpha;\nbaseColor.rgb=baseColor.rgb*alpha;\n#endif\n#endif\ngl_FragColor=baseColor;\n}","glowMapMergeVertexShader":"\nattribute vec2 position;\n\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) {\nvUV=position*madd+madd;\ngl_Position=vec4(position,0.0,1.0);\n}","lineVertexShader":"\nattribute vec3 position;\nattribute vec4 normal;\n\nuniform mat4 worldViewProjection;\nuniform float width;\nuniform float aspectRatio;\nvoid main(void) {\nvec4 viewPosition=worldViewProjection*vec4(position,1.0);\nvec4 viewPositionNext=worldViewProjection*vec4(normal.xyz,1.0);\nvec2 currentScreen=viewPosition.xy/viewPosition.w;\nvec2 nextScreen=viewPositionNext.xy/viewPositionNext.w;\ncurrentScreen.x*=aspectRatio;\nnextScreen.x*=aspectRatio;\nvec2 dir=normalize(nextScreen-currentScreen);\nvec2 normalDir=vec2(-dir.y,dir.x);\nnormalDir*=width/2.0;\nnormalDir.x/=aspectRatio;\nvec4 offset=vec4(normalDir*normal.w,0.0,0.0);\ngl_Position=viewPosition+offset;\n}","linePixelShader":"uniform vec4 color;\nvoid main(void) {\ngl_FragColor=color;\n}","outlineVertexShader":"\nattribute vec3 position;\nattribute vec3 normal;\n#include\n\nuniform float offset;\n#include\nuniform mat4 viewProjection;\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform mat4 diffuseMatrix;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#endif\n#include\nvoid main(void)\n{\nvec3 offsetPosition=position+normal*offset;\n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(offsetPosition,1.0);\n#ifdef ALPHATEST\n#ifdef UV1\nvUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef UV2\nvUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n#include\n}\n","outlinePixelShader":"#ifdef LOGARITHMICDEPTH\n#extension GL_EXT_frag_depth : enable\n#endif\nuniform vec4 color;\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n#endif\n#include\nvoid main(void) {\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUV).a<0.4)\ndiscard;\n#endif\n#include\ngl_FragColor=color;\n}","layerVertexShader":"\nattribute vec2 position;\n\nuniform vec2 scale;\nuniform vec2 offset;\nuniform mat4 textureMatrix;\n\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvec2 shiftedPosition=position*scale+offset;\nvUV=vec2(textureMatrix*vec4(shiftedPosition*madd+madd,1.0,0.0));\ngl_Position=vec4(shiftedPosition,0.0,1.0);\n}","layerPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nuniform vec4 color;\nvoid main(void) {\nvec4 baseColor=texture2D(textureSampler,vUV);\n#ifdef ALPHATEST\nif (baseColor.a<0.4)\ndiscard;\n#endif\ngl_FragColor=baseColor*color;\n}","backgroundVertexShader":"precision highp float;\n#include<__decl__backgroundVertex>\n#include\n\nattribute vec3 position;\n#ifdef NORMAL\nattribute vec3 normal;\n#endif\n#include\n\n#include\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif\n\nvarying vec3 vPositionW;\n#ifdef NORMAL\nvarying vec3 vNormalW;\n#endif\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif\n#ifdef MAINUV2\nvarying vec2 vMainUV2; \n#endif\n#if defined(DIFFUSE) && DIFFUSEDIRECTUV == 0\nvarying vec2 vDiffuseUV;\n#endif\n#include\n#include\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\nvoid main(void) {\n#ifdef REFLECTIONMAP_SKYBOX\nvPositionUVW=position;\n#endif \n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\nvec4 worldPos=finalWorld*vec4(position,1.0);\nvPositionW=vec3(worldPos);\n#ifdef NORMAL\nmat3 normalWorld=mat3(finalWorld);\n#ifdef NONUNIFORMSCALING\nnormalWorld=transposeMat3(inverseMat3(normalWorld));\n#endif\nvNormalW=normalize(normalWorld*normal);\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvDirectionW=normalize(vec3(finalWorld*vec4(position,0.0)));\n#ifdef EQUIRECTANGULAR_RELFECTION_FOV\nmat3 screenToWorld=inverseMat3(mat3(finalWorld*viewProjection));\nvec3 segment=mix(vDirectionW,screenToWorld*vec3(0.0,0.0,1.0),abs(fFovMultiplier-1.0));\nif (fFovMultiplier<=1.0) {\nvDirectionW=normalize(segment);\n} else {\nvDirectionW=normalize(vDirectionW+(vDirectionW-segment));\n}\n#endif\n#endif\n#ifndef UV1\nvec2 uv=vec2(0.,0.);\n#endif\n#ifndef UV2\nvec2 uv2=vec2(0.,0.);\n#endif\n#ifdef MAINUV1\nvMainUV1=uv;\n#endif \n#ifdef MAINUV2\nvMainUV2=uv2;\n#endif\n#if defined(DIFFUSE) && DIFFUSEDIRECTUV == 0 \nif (vDiffuseInfos.x == 0.)\n{\nvDiffuseUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvDiffuseUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n\n#include\n\n#include\n\n#include[0..maxSimultaneousLights]\n\n#ifdef VERTEXCOLOR\nvColor=color;\n#endif\n\n#ifdef POINTSIZE\ngl_PointSize=pointSize;\n#endif\n}\n","backgroundPixelShader":"#ifdef TEXTURELODSUPPORT\n#extension GL_EXT_shader_texture_lod : enable\n#endif\nprecision highp float;\n#include<__decl__backgroundFragment>\n#define RECIPROCAL_PI2 0.15915494\n\nuniform vec3 vEyePosition;\n\nvarying vec3 vPositionW;\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif \n#ifdef MAINUV2 \nvarying vec2 vMainUV2; \n#endif \n#ifdef NORMAL\nvarying vec3 vNormalW;\n#endif\n#ifdef DIFFUSE\n#if DIFFUSEDIRECTUV == 1\n#define vDiffuseUV vMainUV1\n#elif DIFFUSEDIRECTUV == 2\n#define vDiffuseUV vMainUV2\n#else\nvarying vec2 vDiffuseUV;\n#endif\nuniform sampler2D diffuseSampler;\n#endif\n\n#ifdef REFLECTION\n#ifdef REFLECTIONMAP_3D\n#define sampleReflection(s,c) textureCube(s,c)\nuniform samplerCube reflectionSampler;\n#ifdef TEXTURELODSUPPORT\n#define sampleReflectionLod(s,c,l) textureCubeLodEXT(s,c,l)\n#else\nuniform samplerCube reflectionSamplerLow;\nuniform samplerCube reflectionSamplerHigh;\n#endif\n#else\n#define sampleReflection(s,c) texture2D(s,c)\nuniform sampler2D reflectionSampler;\n#ifdef TEXTURELODSUPPORT\n#define sampleReflectionLod(s,c,l) texture2DLodEXT(s,c,l)\n#else\nuniform samplerCube reflectionSamplerLow;\nuniform samplerCube reflectionSamplerHigh;\n#endif\n#endif\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#else\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#endif\n#include\n#endif\n\n#ifndef FROMLINEARSPACE\n#define FROMLINEARSPACE;\n#endif\n\n#ifndef SHADOWONLY\n#define SHADOWONLY;\n#endif\n#include\n\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#include\n#include\n#include\n#include\n#include\n\n#include\n#ifdef REFLECTIONFRESNEL\n#define FRESNEL_MAXIMUM_ON_ROUGH 0.25\nvec3 fresnelSchlickEnvironmentGGX(float VdotN,vec3 reflectance0,vec3 reflectance90,float smoothness)\n{\n\nfloat weight=mix(FRESNEL_MAXIMUM_ON_ROUGH,1.0,smoothness);\nreturn reflectance0+weight*(reflectance90-reflectance0)*pow(clamp(1.0-VdotN,0.,1.),5.0);\n}\n#endif\nvoid main(void) {\n#include\nvec3 viewDirectionW=normalize(vEyePosition-vPositionW);\n\n#ifdef NORMAL\nvec3 normalW=normalize(vNormalW);\n#else\nvec3 normalW=vec3(0.0,1.0,0.0);\n#endif\n\nfloat shadow=1.;\nfloat globalShadow=0.;\nfloat shadowLightCount=0.;\n#include[0..maxSimultaneousLights]\n#ifdef SHADOWINUSE\nglobalShadow/=shadowLightCount;\n#else\nglobalShadow=1.0;\n#endif\n\nvec3 reflectionColor=vec3(1.,1.,1.);\n#ifdef REFLECTION\nvec3 reflectionVector=computeReflectionCoords(vec4(vPositionW,1.0),normalW);\n#ifdef REFLECTIONMAP_OPPOSITEZ\nreflectionVector.z*=-1.0;\n#endif\n\n#ifdef REFLECTIONMAP_3D\nvec3 reflectionCoords=reflectionVector;\n#else\nvec2 reflectionCoords=reflectionVector.xy;\n#ifdef REFLECTIONMAP_PROJECTION\nreflectionCoords/=reflectionVector.z;\n#endif\nreflectionCoords.y=1.0-reflectionCoords.y;\n#endif\n#ifdef REFLECTIONBLUR\nfloat reflectionLOD=vReflectionInfos.y;\n#ifdef TEXTURELODSUPPORT\n\nreflectionLOD=reflectionLOD*log2(vReflectionMicrosurfaceInfos.x)*vReflectionMicrosurfaceInfos.y+vReflectionMicrosurfaceInfos.z;\nreflectionColor=sampleReflectionLod(reflectionSampler,reflectionCoords,reflectionLOD).rgb;\n#else\nfloat lodReflectionNormalized=clamp(reflectionLOD,0.,1.);\nfloat lodReflectionNormalizedDoubled=lodReflectionNormalized*2.0;\nvec3 reflectionSpecularMid=sampleReflection(reflectionSampler,reflectionCoords).rgb;\nif(lodReflectionNormalizedDoubled<1.0){\nreflectionColor=mix(\nsampleReflection(reflectionSamplerHigh,reflectionCoords).rgb,\nreflectionSpecularMid,\nlodReflectionNormalizedDoubled\n);\n} else {\nreflectionColor=mix(\nreflectionSpecularMid,\nsampleReflection(reflectionSamplerLow,reflectionCoords).rgb,\nlodReflectionNormalizedDoubled-1.0\n);\n}\n#endif\n#else\nvec4 reflectionSample=sampleReflection(reflectionSampler,reflectionCoords);\nreflectionColor=reflectionSample.rgb;\n#endif\n#ifdef GAMMAREFLECTION\nreflectionColor=toLinearSpace(reflectionColor.rgb);\n#endif\n#ifdef REFLECTIONBGR\nreflectionColor=reflectionColor.bgr;\n#endif\n\nreflectionColor*=vReflectionInfos.x;\n#endif\n\nvec3 diffuseColor=vec3(1.,1.,1.);\nfloat finalAlpha=alpha;\n#ifdef DIFFUSE\nvec4 diffuseMap=texture2D(diffuseSampler,vDiffuseUV);\n#ifdef GAMMADIFFUSE\ndiffuseMap.rgb=toLinearSpace(diffuseMap.rgb);\n#endif\n\ndiffuseMap.rgb*=vDiffuseInfos.y;\n#ifdef DIFFUSEHASALPHA\nfinalAlpha*=diffuseMap.a;\n#endif\ndiffuseColor=diffuseMap.rgb;\n#endif\n\n#ifdef REFLECTIONFRESNEL\nvec3 colorBase=diffuseColor;\n#else\nvec3 colorBase=reflectionColor*diffuseColor;\n#endif\ncolorBase=max(colorBase,0.0);\n\n#ifdef USERGBCOLOR\nvec3 finalColor=colorBase;\n#else\n#ifdef USEHIGHLIGHTANDSHADOWCOLORS\nvec3 mainColor=mix(vPrimaryColorShadow.rgb,vPrimaryColor.rgb,colorBase);\n#else\nvec3 mainColor=vPrimaryColor.rgb;\n#endif\nvec3 finalColor=colorBase*mainColor;\n#endif\n\n#ifdef REFLECTIONFRESNEL\nvec3 reflectionAmount=vReflectionControl.xxx;\nvec3 reflectionReflectance0=vReflectionControl.yyy;\nvec3 reflectionReflectance90=vReflectionControl.zzz;\nfloat VdotN=dot(normalize(vEyePosition),normalW);\nvec3 planarReflectionFresnel=fresnelSchlickEnvironmentGGX(clamp(VdotN,0.0,1.0),reflectionReflectance0,reflectionReflectance90,1.0);\nreflectionAmount*=planarReflectionFresnel;\n#ifdef REFLECTIONFALLOFF\nfloat reflectionDistanceFalloff=1.0-clamp(length(vPositionW.xyz-vBackgroundCenter)*vReflectionControl.w,0.0,1.0);\nreflectionDistanceFalloff*=reflectionDistanceFalloff;\nreflectionAmount*=reflectionDistanceFalloff;\n#endif\nfinalColor=mix(finalColor,reflectionColor,clamp(reflectionAmount,0.,1.));\n#endif\n#ifdef OPACITYFRESNEL\nfloat viewAngleToFloor=dot(normalW,normalize(vEyePosition-vBackgroundCenter));\n\nconst float startAngle=0.1;\nfloat fadeFactor=clamp(viewAngleToFloor/startAngle,0.0,1.0);\nfinalAlpha*=fadeFactor*fadeFactor;\n#endif\n\n#ifdef SHADOWINUSE\nfinalColor=mix(finalColor*shadowLevel,finalColor,globalShadow);\n#endif\n\nvec4 color=vec4(finalColor,finalAlpha);\n#include\n#ifdef IMAGEPROCESSINGPOSTPROCESS\n\n\ncolor.rgb=clamp(color.rgb,0.,30.0);\n#else\n\ncolor=applyImageProcessing(color);\n#endif\n#ifdef PREMULTIPLYALPHA\n\ncolor.rgb*=color.a;\n#endif\n#ifdef NOISE\ncolor.rgb+=dither(vPositionW.xy,0.5);\ncolor=max(color,0.0);\n#endif\ngl_FragColor=color;\n}\n"};
BABYLON.Effect.IncludesShadersStore={"depthPrePass":"#ifdef DEPTHPREPASS\ngl_FragColor=vec4(0.,0.,0.,1.0);\nreturn;\n#endif","bonesDeclaration":"#if NUM_BONE_INFLUENCERS>0\nuniform mat4 mBones[BonesPerMesh];\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#if NUM_BONE_INFLUENCERS>4\nattribute vec4 matricesIndicesExtra;\nattribute vec4 matricesWeightsExtra;\n#endif\n#endif","instancesDeclaration":"#ifdef INSTANCES\nattribute vec4 world0;\nattribute vec4 world1;\nattribute vec4 world2;\nattribute vec4 world3;\n#else\nuniform mat4 world;\n#endif","pointCloudVertexDeclaration":"#ifdef POINTSIZE\nuniform float pointSize;\n#endif","bumpVertexDeclaration":"#if defined(BUMP) || defined(PARALLAX)\n#if defined(TANGENT) && defined(NORMAL) \nvarying mat3 vTBN;\n#endif\n#endif\n","clipPlaneVertexDeclaration":"#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif","fogVertexDeclaration":"#ifdef FOG\nvarying vec3 vFogDistance;\n#endif","morphTargetsVertexGlobalDeclaration":"#ifdef MORPHTARGETS\nuniform float morphTargetInfluences[NUM_MORPH_INFLUENCERS];\n#endif","morphTargetsVertexDeclaration":"#ifdef MORPHTARGETS\nattribute vec3 position{X};\n#ifdef MORPHTARGETS_NORMAL\nattribute vec3 normal{X};\n#endif\n#ifdef MORPHTARGETS_TANGENT\nattribute vec3 tangent{X};\n#endif\n#endif","logDepthDeclaration":"#ifdef LOGARITHMICDEPTH\nuniform float logarithmicDepthConstant;\nvarying float vFragmentDepth;\n#endif","morphTargetsVertex":"#ifdef MORPHTARGETS\npositionUpdated+=(position{X}-position)*morphTargetInfluences[{X}];\n#ifdef MORPHTARGETS_NORMAL\nnormalUpdated+=(normal{X}-normal)*morphTargetInfluences[{X}];\n#endif\n#ifdef MORPHTARGETS_TANGENT\ntangentUpdated.xyz+=(tangent{X}-tangent.xyz)*morphTargetInfluences[{X}];\n#endif\n#endif","instancesVertex":"#ifdef INSTANCES\nmat4 finalWorld=mat4(world0,world1,world2,world3);\n#else\nmat4 finalWorld=world;\n#endif","bonesVertex":"#if NUM_BONE_INFLUENCERS>0\nmat4 influence;\ninfluence=mBones[int(matricesIndices[0])]*matricesWeights[0];\n#if NUM_BONE_INFLUENCERS>1\ninfluence+=mBones[int(matricesIndices[1])]*matricesWeights[1];\n#endif \n#if NUM_BONE_INFLUENCERS>2\ninfluence+=mBones[int(matricesIndices[2])]*matricesWeights[2];\n#endif \n#if NUM_BONE_INFLUENCERS>3\ninfluence+=mBones[int(matricesIndices[3])]*matricesWeights[3];\n#endif \n#if NUM_BONE_INFLUENCERS>4\ninfluence+=mBones[int(matricesIndicesExtra[0])]*matricesWeightsExtra[0];\n#endif \n#if NUM_BONE_INFLUENCERS>5\ninfluence+=mBones[int(matricesIndicesExtra[1])]*matricesWeightsExtra[1];\n#endif \n#if NUM_BONE_INFLUENCERS>6\ninfluence+=mBones[int(matricesIndicesExtra[2])]*matricesWeightsExtra[2];\n#endif \n#if NUM_BONE_INFLUENCERS>7\ninfluence+=mBones[int(matricesIndicesExtra[3])]*matricesWeightsExtra[3];\n#endif \nfinalWorld=finalWorld*influence;\n#endif","bumpVertex":"#if defined(BUMP) || defined(PARALLAX)\n#if defined(TANGENT) && defined(NORMAL)\nvec3 tbnNormal=normalize(normalUpdated);\nvec3 tbnTangent=normalize(tangentUpdated.xyz);\nvec3 tbnBitangent=cross(tbnNormal,tbnTangent)*tangentUpdated.w;\nvTBN=mat3(finalWorld)*mat3(tbnTangent,tbnBitangent,tbnNormal);\n#endif\n#endif","clipPlaneVertex":"#ifdef CLIPPLANE\nfClipDistance=dot(worldPos,vClipPlane);\n#endif","fogVertex":"#ifdef FOG\nvFogDistance=(view*worldPos).xyz;\n#endif","shadowsVertex":"#ifdef SHADOWS\n#if defined(SHADOW{X}) && !defined(SHADOWCUBE{X})\nvPositionFromLight{X}=lightMatrix{X}*worldPos;\nvDepthMetric{X}=((vPositionFromLight{X}.z+light{X}.depthValues.x)/(light{X}.depthValues.y));\n#endif\n#endif","pointCloudVertex":"#ifdef POINTSIZE\ngl_PointSize=pointSize;\n#endif","logDepthVertex":"#ifdef LOGARITHMICDEPTH\nvFragmentDepth=1.0+gl_Position.w;\ngl_Position.z=log2(max(0.000001,vFragmentDepth))*logarithmicDepthConstant;\n#endif","helperFunctions":"const float PI=3.1415926535897932384626433832795;\nconst float LinearEncodePowerApprox=2.2;\nconst float GammaEncodePowerApprox=1.0/LinearEncodePowerApprox;\nconst vec3 LuminanceEncodeApprox=vec3(0.2126,0.7152,0.0722);\nmat3 transposeMat3(mat3 inMatrix) {\nvec3 i0=inMatrix[0];\nvec3 i1=inMatrix[1];\nvec3 i2=inMatrix[2];\nmat3 outMatrix=mat3(\nvec3(i0.x,i1.x,i2.x),\nvec3(i0.y,i1.y,i2.y),\nvec3(i0.z,i1.z,i2.z)\n);\nreturn outMatrix;\n}\n\nmat3 inverseMat3(mat3 inMatrix) {\nfloat a00=inMatrix[0][0],a01=inMatrix[0][1],a02=inMatrix[0][2];\nfloat a10=inMatrix[1][0],a11=inMatrix[1][1],a12=inMatrix[1][2];\nfloat a20=inMatrix[2][0],a21=inMatrix[2][1],a22=inMatrix[2][2];\nfloat b01=a22*a11-a12*a21;\nfloat b11=-a22*a10+a12*a20;\nfloat b21=a21*a10-a11*a20;\nfloat det=a00*b01+a01*b11+a02*b21;\nreturn mat3(b01,(-a22*a01+a02*a21),(a12*a01-a02*a11),\nb11,(a22*a00-a02*a20),(-a12*a00+a02*a10),\nb21,(-a21*a00+a01*a20),(a11*a00-a01*a10))/det;\n}\nfloat computeFallOff(float value,vec2 clipSpace,float frustumEdgeFalloff)\n{\nfloat mask=smoothstep(1.0-frustumEdgeFalloff,1.0,clamp(dot(clipSpace,clipSpace),0.,1.));\nreturn mix(value,1.0,mask);\n}\nvec3 applyEaseInOut(vec3 x){\nreturn x*x*(3.0-2.0*x);\n}\nvec3 toLinearSpace(vec3 color)\n{\nreturn pow(color,vec3(LinearEncodePowerApprox));\n}\nvec3 toGammaSpace(vec3 color)\n{\nreturn pow(color,vec3(GammaEncodePowerApprox));\n}\nfloat square(float value)\n{\nreturn value*value;\n}\nfloat getLuminance(vec3 color)\n{\nreturn clamp(dot(color,LuminanceEncodeApprox),0.,1.);\n}\n\nfloat getRand(vec2 seed) {\nreturn fract(sin(dot(seed.xy ,vec2(12.9898,78.233)))*43758.5453);\n}\nfloat dither(vec2 seed,float varianceAmount) {\nfloat rand=getRand(seed);\nfloat dither=mix(-varianceAmount/255.0,varianceAmount/255.0,rand);\nreturn dither;\n}","lightFragmentDeclaration":"#ifdef LIGHT{X}\nuniform vec4 vLightData{X};\nuniform vec4 vLightDiffuse{X};\n#ifdef SPECULARTERM\nuniform vec3 vLightSpecular{X};\n#else\nvec3 vLightSpecular{X}=vec3(0.);\n#endif\n#ifdef SHADOW{X}\n#if defined(SHADOWCUBE{X})\nuniform samplerCube shadowSampler{X};\n#else\nvarying vec4 vPositionFromLight{X};\nvarying float vDepthMetric{X};\n#if defined(SHADOWPCSS{X})\nuniform highp sampler2DShadow shadowSampler{X};\nuniform highp sampler2D depthSampler{X};\n#elif defined(SHADOWPCF{X})\nuniform highp sampler2DShadow shadowSampler{X};\n#else\nuniform sampler2D shadowSampler{X};\n#endif\nuniform mat4 lightMatrix{X};\n#endif\nuniform vec4 shadowsInfo{X};\nuniform vec2 depthValues{X};\n#endif\n#ifdef SPOTLIGHT{X}\nuniform vec4 vLightDirection{X};\n#endif\n#ifdef HEMILIGHT{X}\nuniform vec3 vLightGround{X};\n#endif\n#ifdef PROJECTEDLIGHTTEXTURE{X}\nuniform mat4 textureProjectionMatrix{X};\nuniform sampler2D projectionLightSampler{X};\n#endif\n#endif","lightsFragmentFunctions":"\nstruct lightingInfo\n{\nvec3 diffuse;\n#ifdef SPECULARTERM\nvec3 specular;\n#endif\n#ifdef NDOTL\nfloat ndl;\n#endif\n};\nlightingInfo computeLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec3 diffuseColor,vec3 specularColor,float range,float glossiness) {\nlightingInfo result;\nvec3 lightVectorW;\nfloat attenuation=1.0;\nif (lightData.w == 0.)\n{\nvec3 direction=lightData.xyz-vPositionW;\nattenuation=max(0.,1.0-length(direction)/range);\nlightVectorW=normalize(direction);\n}\nelse\n{\nlightVectorW=normalize(-lightData.xyz);\n}\n\nfloat ndl=max(0.,dot(vNormal,lightVectorW));\n#ifdef NDOTL\nresult.ndl=ndl;\n#endif\nresult.diffuse=ndl*diffuseColor*attenuation;\n#ifdef SPECULARTERM\n\nvec3 angleW=normalize(viewDirectionW+lightVectorW);\nfloat specComp=max(0.,dot(vNormal,angleW));\nspecComp=pow(specComp,max(1.,glossiness));\nresult.specular=specComp*specularColor*attenuation;\n#endif\nreturn result;\n}\nlightingInfo computeSpotLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec4 lightDirection,vec3 diffuseColor,vec3 specularColor,float range,float glossiness) {\nlightingInfo result;\nvec3 direction=lightData.xyz-vPositionW;\nvec3 lightVectorW=normalize(direction);\nfloat attenuation=max(0.,1.0-length(direction)/range);\n\nfloat cosAngle=max(0.,dot(lightDirection.xyz,-lightVectorW));\nif (cosAngle>=lightDirection.w)\n{\ncosAngle=max(0.,pow(cosAngle,lightData.w));\nattenuation*=cosAngle;\n\nfloat ndl=max(0.,dot(vNormal,lightVectorW));\n#ifdef NDOTL\nresult.ndl=ndl;\n#endif\nresult.diffuse=ndl*diffuseColor*attenuation;\n#ifdef SPECULARTERM\n\nvec3 angleW=normalize(viewDirectionW+lightVectorW);\nfloat specComp=max(0.,dot(vNormal,angleW));\nspecComp=pow(specComp,max(1.,glossiness));\nresult.specular=specComp*specularColor*attenuation;\n#endif\nreturn result;\n}\nresult.diffuse=vec3(0.);\n#ifdef SPECULARTERM\nresult.specular=vec3(0.);\n#endif\n#ifdef NDOTL\nresult.ndl=0.;\n#endif\nreturn result;\n}\nlightingInfo computeHemisphericLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec3 diffuseColor,vec3 specularColor,vec3 groundColor,float glossiness) {\nlightingInfo result;\n\nfloat ndl=dot(vNormal,lightData.xyz)*0.5+0.5;\n#ifdef NDOTL\nresult.ndl=ndl;\n#endif\nresult.diffuse=mix(groundColor,diffuseColor,ndl);\n#ifdef SPECULARTERM\n\nvec3 angleW=normalize(viewDirectionW+lightData.xyz);\nfloat specComp=max(0.,dot(vNormal,angleW));\nspecComp=pow(specComp,max(1.,glossiness));\nresult.specular=specComp*specularColor;\n#endif\nreturn result;\n}\nvec3 computeProjectionTextureDiffuseLighting(sampler2D projectionLightSampler,mat4 textureProjectionMatrix){\nvec4 strq=textureProjectionMatrix*vec4(vPositionW,1.0);\nstrq/=strq.w;\nvec3 textureColor=texture2D(projectionLightSampler,strq.xy).rgb;\nreturn textureColor;\n}","lightUboDeclaration":"#ifdef LIGHT{X}\nuniform Light{X}\n{\nvec4 vLightData;\nvec4 vLightDiffuse;\nvec3 vLightSpecular;\n#ifdef SPOTLIGHT{X}\nvec4 vLightDirection;\n#endif\n#ifdef HEMILIGHT{X}\nvec3 vLightGround;\n#endif\nvec4 shadowsInfo;\nvec2 depthValues;\n} light{X};\n#ifdef PROJECTEDLIGHTTEXTURE{X}\nuniform mat4 textureProjectionMatrix{X};\nuniform sampler2D projectionLightSampler{X};\n#endif\n#ifdef SHADOW{X}\n#if defined(SHADOWCUBE{X})\nuniform samplerCube shadowSampler{X}; \n#else\nvarying vec4 vPositionFromLight{X};\nvarying float vDepthMetric{X};\n#if defined(SHADOWPCSS{X})\nuniform highp sampler2DShadow shadowSampler{X};\nuniform highp sampler2D depthSampler{X};\n#elif defined(SHADOWPCF{X})\nuniform highp sampler2DShadow shadowSampler{X};\n#else\nuniform sampler2D shadowSampler{X};\n#endif\nuniform mat4 lightMatrix{X};\n#endif\n#endif\n#endif","defaultVertexDeclaration":"\nuniform mat4 viewProjection;\nuniform mat4 view;\n#ifdef DIFFUSE\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n#ifdef AMBIENT\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n#ifdef OPACITY\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n#ifdef EMISSIVE\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n#ifdef LIGHTMAP\nuniform vec2 vLightmapInfos;\nuniform mat4 lightmapMatrix;\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM)\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n#ifdef BUMP\nuniform vec3 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif\n","defaultFragmentDeclaration":"uniform vec4 vDiffuseColor;\n#ifdef SPECULARTERM\nuniform vec4 vSpecularColor;\n#endif\nuniform vec3 vEmissiveColor;\n\n#ifdef DIFFUSE\nuniform vec2 vDiffuseInfos;\n#endif\n#ifdef AMBIENT\nuniform vec2 vAmbientInfos;\n#endif\n#ifdef OPACITY \nuniform vec2 vOpacityInfos;\n#endif\n#ifdef EMISSIVE\nuniform vec2 vEmissiveInfos;\n#endif\n#ifdef LIGHTMAP\nuniform vec2 vLightmapInfos;\n#endif\n#ifdef BUMP\nuniform vec3 vBumpInfos;\nuniform vec2 vTangentSpaceParams;\n#endif\n#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)\nuniform mat4 view;\n#endif\n#ifdef REFRACTION\nuniform vec4 vRefractionInfos;\n#ifndef REFRACTIONMAP_3D\nuniform mat4 refractionMatrix;\n#endif\n#ifdef REFRACTIONFRESNEL\nuniform vec4 refractionLeftColor;\nuniform vec4 refractionRightColor;\n#endif\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM)\nuniform vec2 vSpecularInfos;\n#endif\n#ifdef DIFFUSEFRESNEL\nuniform vec4 diffuseLeftColor;\nuniform vec4 diffuseRightColor;\n#endif\n#ifdef OPACITYFRESNEL\nuniform vec4 opacityParts;\n#endif\n#ifdef EMISSIVEFRESNEL\nuniform vec4 emissiveLeftColor;\nuniform vec4 emissiveRightColor;\n#endif\n\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\n#ifdef REFLECTIONMAP_SKYBOX\n#else\n#if defined(REFLECTIONMAP_PLANAR) || defined(REFLECTIONMAP_CUBIC) || defined(REFLECTIONMAP_PROJECTION)\nuniform mat4 reflectionMatrix;\n#endif\n#if defined(USE_LOCAL_REFLECTIONMAP_CUBIC) && defined(REFLECTIONMAP_CUBIC)\nuniform vec3 vReflectionPosition;\nuniform vec3 vReflectionSize; \n#endif\n#endif\n#ifdef REFLECTIONFRESNEL\nuniform vec4 reflectionLeftColor;\nuniform vec4 reflectionRightColor;\n#endif\n#endif","defaultUboDeclaration":"layout(std140,column_major) uniform;\nuniform Material\n{\nvec4 diffuseLeftColor;\nvec4 diffuseRightColor;\nvec4 opacityParts;\nvec4 reflectionLeftColor;\nvec4 reflectionRightColor;\nvec4 refractionLeftColor;\nvec4 refractionRightColor;\nvec4 emissiveLeftColor; \nvec4 emissiveRightColor;\nvec2 vDiffuseInfos;\nvec2 vAmbientInfos;\nvec2 vOpacityInfos;\nvec2 vReflectionInfos;\nvec3 vReflectionPosition;\nvec3 vReflectionSize;\nvec2 vEmissiveInfos;\nvec2 vLightmapInfos;\nvec2 vSpecularInfos;\nvec3 vBumpInfos;\nmat4 diffuseMatrix;\nmat4 ambientMatrix;\nmat4 opacityMatrix;\nmat4 reflectionMatrix;\nmat4 emissiveMatrix;\nmat4 lightmapMatrix;\nmat4 specularMatrix;\nmat4 bumpMatrix; \nvec4 vTangentSpaceParams;\nmat4 refractionMatrix;\nvec4 vRefractionInfos;\nvec4 vSpecularColor;\nvec3 vEmissiveColor;\nvec4 vDiffuseColor;\nfloat pointSize; \n};\nuniform Scene {\nmat4 viewProjection;\nmat4 view;\n};","shadowsFragmentFunctions":"#ifdef SHADOWS\n#ifndef SHADOWFLOAT\nfloat unpack(vec4 color)\n{\nconst vec4 bit_shift=vec4(1.0/(255.0*255.0*255.0),1.0/(255.0*255.0),1.0/255.0,1.0);\nreturn dot(color,bit_shift);\n}\n#endif\nfloat computeShadowCube(vec3 lightPosition,samplerCube shadowSampler,float darkness,vec2 depthValues)\n{\nvec3 directionToLight=vPositionW-lightPosition;\nfloat depth=length(directionToLight);\ndepth=(depth+depthValues.x)/(depthValues.y);\ndepth=clamp(depth,0.,1.0);\ndirectionToLight=normalize(directionToLight);\ndirectionToLight.y=-directionToLight.y;\n#ifndef SHADOWFLOAT\nfloat shadow=unpack(textureCube(shadowSampler,directionToLight));\n#else\nfloat shadow=textureCube(shadowSampler,directionToLight).x;\n#endif\nif (depth>shadow)\n{\nreturn darkness;\n}\nreturn 1.0;\n}\nfloat computeShadowWithPoissonSamplingCube(vec3 lightPosition,samplerCube shadowSampler,float mapSize,float darkness,vec2 depthValues)\n{\nvec3 directionToLight=vPositionW-lightPosition;\nfloat depth=length(directionToLight);\ndepth=(depth+depthValues.x)/(depthValues.y);\ndepth=clamp(depth,0.,1.0);\ndirectionToLight=normalize(directionToLight);\ndirectionToLight.y=-directionToLight.y;\nfloat visibility=1.;\nvec3 poissonDisk[4];\npoissonDisk[0]=vec3(-1.0,1.0,-1.0);\npoissonDisk[1]=vec3(1.0,-1.0,-1.0);\npoissonDisk[2]=vec3(-1.0,-1.0,-1.0);\npoissonDisk[3]=vec3(1.0,-1.0,1.0);\n\n#ifndef SHADOWFLOAT\nif (unpack(textureCube(shadowSampler,directionToLight+poissonDisk[0]*mapSize))1.0 || uv.y<0. || uv.y>1.0)\n{\nreturn 1.0;\n}\nfloat shadowPixelDepth=clamp(depthMetric,0.,1.0);\n#ifndef SHADOWFLOAT\nfloat shadow=unpack(texture2D(shadowSampler,uv));\n#else\nfloat shadow=texture2D(shadowSampler,uv).x;\n#endif\nif (shadowPixelDepth>shadow)\n{\nreturn computeFallOff(darkness,clipSpace.xy,frustumEdgeFalloff);\n}\nreturn 1.;\n}\nfloat computeShadowWithPoissonSampling(vec4 vPositionFromLight,float depthMetric,sampler2D shadowSampler,float mapSize,float darkness,float frustumEdgeFalloff)\n{\nvec3 clipSpace=vPositionFromLight.xyz/vPositionFromLight.w;\nvec2 uv=0.5*clipSpace.xy+vec2(0.5);\nif (uv.x<0. || uv.x>1.0 || uv.y<0. || uv.y>1.0)\n{\nreturn 1.0;\n}\nfloat shadowPixelDepth=clamp(depthMetric,0.,1.0);\nfloat visibility=1.;\nvec2 poissonDisk[4];\npoissonDisk[0]=vec2(-0.94201624,-0.39906216);\npoissonDisk[1]=vec2(0.94558609,-0.76890725);\npoissonDisk[2]=vec2(-0.094184101,-0.92938870);\npoissonDisk[3]=vec2(0.34495938,0.29387760);\n\n#ifndef SHADOWFLOAT\nif (unpack(texture2D(shadowSampler,uv+poissonDisk[0]*mapSize))1.0 || uv.y<0. || uv.y>1.0)\n{\nreturn 1.0;\n}\nfloat shadowPixelDepth=clamp(depthMetric,0.,1.0);\n#ifndef SHADOWFLOAT\nfloat shadowMapSample=unpack(texture2D(shadowSampler,uv));\n#else\nfloat shadowMapSample=texture2D(shadowSampler,uv).x;\n#endif\nfloat esm=1.0-clamp(exp(min(87.,depthScale*shadowPixelDepth))*shadowMapSample,0.,1.-darkness);\nreturn computeFallOff(esm,clipSpace.xy,frustumEdgeFalloff);\n}\nfloat computeShadowWithCloseESM(vec4 vPositionFromLight,float depthMetric,sampler2D shadowSampler,float darkness,float depthScale,float frustumEdgeFalloff)\n{\nvec3 clipSpace=vPositionFromLight.xyz/vPositionFromLight.w;\nvec2 uv=0.5*clipSpace.xy+vec2(0.5);\nif (uv.x<0. || uv.x>1.0 || uv.y<0. || uv.y>1.0)\n{\nreturn 1.0;\n}\nfloat shadowPixelDepth=clamp(depthMetric,0.,1.0); \n#ifndef SHADOWFLOAT\nfloat shadowMapSample=unpack(texture2D(shadowSampler,uv));\n#else\nfloat shadowMapSample=texture2D(shadowSampler,uv).x;\n#endif\nfloat esm=clamp(exp(min(87.,-depthScale*(shadowPixelDepth-shadowMapSample))),darkness,1.);\nreturn computeFallOff(esm,clipSpace.xy,frustumEdgeFalloff);\n}\n#ifdef WEBGL2\n\nfloat computeShadowWithPCF1(vec4 vPositionFromLight,float depthMetric,sampler2DShadow shadowSampler,float darkness,float frustumEdgeFalloff)\n{\nif (depthMetric>1.0 || depthMetric<0.0) {\nreturn 1.0;\n}\nvec3 clipSpace=vPositionFromLight.xyz/vPositionFromLight.w;\nvec3 uvDepth=vec3(0.5*clipSpace.xyz+vec3(0.5));\nfloat shadow=texture2D(shadowSampler,uvDepth);\nshadow=mix(darkness,1.,shadow);\nreturn computeFallOff(shadow,clipSpace.xy,frustumEdgeFalloff);\n}\n\n\n\nfloat computeShadowWithPCF3(vec4 vPositionFromLight,float depthMetric,sampler2DShadow shadowSampler,vec2 shadowMapSizeAndInverse,float darkness,float frustumEdgeFalloff)\n{\nif (depthMetric>1.0 || depthMetric<0.0) {\nreturn 1.0;\n}\nvec3 clipSpace=vPositionFromLight.xyz/vPositionFromLight.w;\nvec3 uvDepth=vec3(0.5*clipSpace.xyz+vec3(0.5));\nvec2 uv=uvDepth.xy*shadowMapSizeAndInverse.x; \nuv+=0.5; \nvec2 st=fract(uv); \nvec2 base_uv=floor(uv)-0.5; \nbase_uv*=shadowMapSizeAndInverse.y; \n\n\n\n\nvec2 uvw0=3.-2.*st;\nvec2 uvw1=1.+2.*st;\nvec2 u=vec2((2.-st.x)/uvw0.x-1.,st.x/uvw1.x+1.)*shadowMapSizeAndInverse.y;\nvec2 v=vec2((2.-st.y)/uvw0.y-1.,st.y/uvw1.y+1.)*shadowMapSizeAndInverse.y;\nfloat shadow=0.;\nshadow+=uvw0.x*uvw0.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[0],v[0]),uvDepth.z));\nshadow+=uvw1.x*uvw0.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[1],v[0]),uvDepth.z));\nshadow+=uvw0.x*uvw1.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[0],v[1]),uvDepth.z));\nshadow+=uvw1.x*uvw1.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[1],v[1]),uvDepth.z));\nshadow=shadow/16.;\nshadow=mix(darkness,1.,shadow);\nreturn computeFallOff(shadow,clipSpace.xy,frustumEdgeFalloff);\n}\n\n\n\nfloat computeShadowWithPCF5(vec4 vPositionFromLight,float depthMetric,sampler2DShadow shadowSampler,vec2 shadowMapSizeAndInverse,float darkness,float frustumEdgeFalloff)\n{\nif (depthMetric>1.0 || depthMetric<0.0) {\nreturn 1.0;\n}\nvec3 clipSpace=vPositionFromLight.xyz/vPositionFromLight.w;\nvec3 uvDepth=vec3(0.5*clipSpace.xyz+vec3(0.5));\nvec2 uv=uvDepth.xy*shadowMapSizeAndInverse.x; \nuv+=0.5; \nvec2 st=fract(uv); \nvec2 base_uv=floor(uv)-0.5; \nbase_uv*=shadowMapSizeAndInverse.y; \n\n\nvec2 uvw0=4.-3.*st;\nvec2 uvw1=vec2(7.);\nvec2 uvw2=1.+3.*st;\nvec3 u=vec3((3.-2.*st.x)/uvw0.x-2.,(3.+st.x)/uvw1.x,st.x/uvw2.x+2.)*shadowMapSizeAndInverse.y;\nvec3 v=vec3((3.-2.*st.y)/uvw0.y-2.,(3.+st.y)/uvw1.y,st.y/uvw2.y+2.)*shadowMapSizeAndInverse.y;\nfloat shadow=0.;\nshadow+=uvw0.x*uvw0.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[0],v[0]),uvDepth.z));\nshadow+=uvw1.x*uvw0.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[1],v[0]),uvDepth.z));\nshadow+=uvw2.x*uvw0.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[2],v[0]),uvDepth.z));\nshadow+=uvw0.x*uvw1.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[0],v[1]),uvDepth.z));\nshadow+=uvw1.x*uvw1.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[1],v[1]),uvDepth.z));\nshadow+=uvw2.x*uvw1.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[2],v[1]),uvDepth.z));\nshadow+=uvw0.x*uvw2.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[0],v[2]),uvDepth.z));\nshadow+=uvw1.x*uvw2.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[1],v[2]),uvDepth.z));\nshadow+=uvw2.x*uvw2.y*texture2D(shadowSampler,vec3(base_uv.xy+vec2(u[2],v[2]),uvDepth.z));\nshadow=shadow/144.;\nshadow=mix(darkness,1.,shadow);\nreturn computeFallOff(shadow,clipSpace.xy,frustumEdgeFalloff);\n}\nconst vec3 PoissonSamplers32[64]=vec3[64](\nvec3(0.06407013,0.05409927,0.),\nvec3(0.7366577,0.5789394,0.),\nvec3(-0.6270542,-0.5320278,0.),\nvec3(-0.4096107,0.8411095,0.),\nvec3(0.6849564,-0.4990818,0.),\nvec3(-0.874181,-0.04579735,0.),\nvec3(0.9989998,0.0009880066,0.),\nvec3(-0.004920578,-0.9151649,0.),\nvec3(0.1805763,0.9747483,0.),\nvec3(-0.2138451,0.2635818,0.),\nvec3(0.109845,0.3884785,0.),\nvec3(0.06876755,-0.3581074,0.),\nvec3(0.374073,-0.7661266,0.),\nvec3(0.3079132,-0.1216763,0.),\nvec3(-0.3794335,-0.8271583,0.),\nvec3(-0.203878,-0.07715034,0.),\nvec3(0.5912697,0.1469799,0.),\nvec3(-0.88069,0.3031784,0.),\nvec3(0.5040108,0.8283722,0.),\nvec3(-0.5844124,0.5494877,0.),\nvec3(0.6017799,-0.1726654,0.),\nvec3(-0.5554981,0.1559997,0.),\nvec3(-0.3016369,-0.3900928,0.),\nvec3(-0.5550632,-0.1723762,0.),\nvec3(0.925029,0.2995041,0.),\nvec3(-0.2473137,0.5538505,0.),\nvec3(0.9183037,-0.2862392,0.),\nvec3(0.2469421,0.6718712,0.),\nvec3(0.3916397,-0.4328209,0.),\nvec3(-0.03576927,-0.6220032,0.),\nvec3(-0.04661255,0.7995201,0.),\nvec3(0.4402924,0.3640312,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.),\nvec3(0.,0.,0.)\n);\nconst vec3 PoissonSamplers64[64]=vec3[64](\nvec3(-0.613392,0.617481,0.),\nvec3(0.170019,-0.040254,0.),\nvec3(-0.299417,0.791925,0.),\nvec3(0.645680,0.493210,0.),\nvec3(-0.651784,0.717887,0.),\nvec3(0.421003,0.027070,0.),\nvec3(-0.817194,-0.271096,0.),\nvec3(-0.705374,-0.668203,0.),\nvec3(0.977050,-0.108615,0.),\nvec3(0.063326,0.142369,0.),\nvec3(0.203528,0.214331,0.),\nvec3(-0.667531,0.326090,0.),\nvec3(-0.098422,-0.295755,0.),\nvec3(-0.885922,0.215369,0.),\nvec3(0.566637,0.605213,0.),\nvec3(0.039766,-0.396100,0.),\nvec3(0.751946,0.453352,0.),\nvec3(0.078707,-0.715323,0.),\nvec3(-0.075838,-0.529344,0.),\nvec3(0.724479,-0.580798,0.),\nvec3(0.222999,-0.215125,0.),\nvec3(-0.467574,-0.405438,0.),\nvec3(-0.248268,-0.814753,0.),\nvec3(0.354411,-0.887570,0.),\nvec3(0.175817,0.382366,0.),\nvec3(0.487472,-0.063082,0.),\nvec3(-0.084078,0.898312,0.),\nvec3(0.488876,-0.783441,0.),\nvec3(0.470016,0.217933,0.),\nvec3(-0.696890,-0.549791,0.),\nvec3(-0.149693,0.605762,0.),\nvec3(0.034211,0.979980,0.),\nvec3(0.503098,-0.308878,0.),\nvec3(-0.016205,-0.872921,0.),\nvec3(0.385784,-0.393902,0.),\nvec3(-0.146886,-0.859249,0.),\nvec3(0.643361,0.164098,0.),\nvec3(0.634388,-0.049471,0.),\nvec3(-0.688894,0.007843,0.),\nvec3(0.464034,-0.188818,0.),\nvec3(-0.440840,0.137486,0.),\nvec3(0.364483,0.511704,0.),\nvec3(0.034028,0.325968,0.),\nvec3(0.099094,-0.308023,0.),\nvec3(0.693960,-0.366253,0.),\nvec3(0.678884,-0.204688,0.),\nvec3(0.001801,0.780328,0.),\nvec3(0.145177,-0.898984,0.),\nvec3(0.062655,-0.611866,0.),\nvec3(0.315226,-0.604297,0.),\nvec3(-0.780145,0.486251,0.),\nvec3(-0.371868,0.882138,0.),\nvec3(0.200476,0.494430,0.),\nvec3(-0.494552,-0.711051,0.),\nvec3(0.612476,0.705252,0.),\nvec3(-0.578845,-0.768792,0.),\nvec3(-0.772454,-0.090976,0.),\nvec3(0.504440,0.372295,0.),\nvec3(0.155736,0.065157,0.),\nvec3(0.391522,0.849605,0.),\nvec3(-0.620106,-0.328104,0.),\nvec3(0.789239,-0.419965,0.),\nvec3(-0.545396,0.538133,0.),\nvec3(-0.178564,-0.596057,0.)\n);\n\n\n\n\n\nfloat computeShadowWithPCSS(vec4 vPositionFromLight,float depthMetric,sampler2D depthSampler,sampler2DShadow shadowSampler,float shadowMapSizeInverse,float lightSizeUV,float darkness,float frustumEdgeFalloff,int searchTapCount,int pcfTapCount,vec3[64] poissonSamplers)\n{\nif (depthMetric>1.0 || depthMetric<0.0) {\nreturn 1.0;\n}\nvec3 clipSpace=vPositionFromLight.xyz/vPositionFromLight.w;\nvec3 uvDepth=vec3(0.5*clipSpace.xyz+vec3(0.5));\nfloat blockerDepth=0.0;\nfloat sumBlockerDepth=0.0;\nfloat numBlocker=0.0;\nfor (int i=0; icurrRayHeight)\n{\nfloat delta1=currSampledHeight-currRayHeight;\nfloat delta2=(currRayHeight+stepSize)-lastSampledHeight;\nfloat ratio=delta1/(delta1+delta2);\nvCurrOffset=(ratio)* vLastOffset+(1.0-ratio)*vCurrOffset;\n\nbreak;\n}\nelse\n{\ncurrRayHeight-=stepSize;\nvLastOffset=vCurrOffset;\nvCurrOffset+=stepSize*vMaxOffset;\nlastSampledHeight=currSampledHeight;\n}\n}\nreturn vCurrOffset;\n}\nvec2 parallaxOffset(vec3 viewDir,float heightScale)\n{\n\nfloat height=texture2D(bumpSampler,vBumpUV).w;\nvec2 texCoordOffset=heightScale*viewDir.xy*height;\nreturn -texCoordOffset;\n}\n#endif\n#endif","clipPlaneFragmentDeclaration":"#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif","fogFragmentDeclaration":"#ifdef FOG\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying vec3 vFogDistance;\nfloat CalcFogFactor()\n{\nfloat fogCoeff=1.0;\nfloat fogStart=vFogInfos.y;\nfloat fogEnd=vFogInfos.z;\nfloat fogDensity=vFogInfos.w;\nfloat fogDistance=length(vFogDistance);\nif (FOGMODE_LINEAR == vFogInfos.x)\n{\nfogCoeff=(fogEnd-fogDistance)/(fogEnd-fogStart);\n}\nelse if (FOGMODE_EXP == vFogInfos.x)\n{\nfogCoeff=1.0/pow(E,fogDistance*fogDensity);\n}\nelse if (FOGMODE_EXP2 == vFogInfos.x)\n{\nfogCoeff=1.0/pow(E,fogDistance*fogDistance*fogDensity*fogDensity);\n}\nreturn clamp(fogCoeff,0.0,1.0);\n}\n#endif","clipPlaneFragment":"#ifdef CLIPPLANE\nif (fClipDistance>0.0)\n{\ndiscard;\n}\n#endif","bumpFragment":"vec2 uvOffset=vec2(0.0,0.0);\n#if defined(BUMP) || defined(PARALLAX)\n#ifdef NORMALXYSCALE\nfloat normalScale=1.0;\n#else \nfloat normalScale=vBumpInfos.y;\n#endif\n#if defined(TANGENT) && defined(NORMAL)\nmat3 TBN=vTBN;\n#else\nmat3 TBN=cotangent_frame(normalW*normalScale,vPositionW,vBumpUV);\n#endif\n#endif\n#ifdef PARALLAX\nmat3 invTBN=transposeMat3(TBN);\n#ifdef PARALLAXOCCLUSION\nuvOffset=parallaxOcclusion(invTBN*-viewDirectionW,invTBN*normalW,vBumpUV,vBumpInfos.z);\n#else\nuvOffset=parallaxOffset(invTBN*viewDirectionW,vBumpInfos.z);\n#endif\n#endif\n#ifdef BUMP\n#ifdef OBJECTSPACE_NORMALMAP\nnormalW=normalize(texture2D(bumpSampler,vBumpUV).xyz*2.0-1.0);\nnormalW=normalize(mat3(normalMatrix)*normalW); \n#else\nnormalW=perturbNormal(TBN,vBumpUV+uvOffset);\n#endif\n#endif","lightFragment":"#ifdef LIGHT{X}\n#if defined(SHADOWONLY) || (defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X}))\n\n#else\n#ifdef PBR\n#ifdef SPOTLIGHT{X}\ninfo=computeSpotLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDirection,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightDiffuse.a,roughness,NdotV,specularEnvironmentR0,specularEnvironmentR90,geometricRoughnessFactor,NdotL);\n#endif\n#ifdef HEMILIGHT{X}\ninfo=computeHemisphericLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightGround,roughness,NdotV,specularEnvironmentR0,specularEnvironmentR90,geometricRoughnessFactor,NdotL);\n#endif\n#if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})\ninfo=computeLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightDiffuse.a,roughness,NdotV,specularEnvironmentR0,specularEnvironmentR90,geometricRoughnessFactor,NdotL);\n#endif\n#else\n#ifdef SPOTLIGHT{X}\ninfo=computeSpotLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDirection,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightDiffuse.a,glossiness);\n#endif\n#ifdef HEMILIGHT{X}\ninfo=computeHemisphericLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightGround,glossiness);\n#endif\n#if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})\ninfo=computeLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightDiffuse.a,glossiness);\n#endif\n#endif\n#ifdef PROJECTEDLIGHTTEXTURE{X}\ninfo.diffuse*=computeProjectionTextureDiffuseLighting(projectionLightSampler{X},textureProjectionMatrix{X});\n#endif\n#endif\n#ifdef SHADOW{X}\n#ifdef SHADOWCLOSEESM{X}\n#if defined(SHADOWCUBE{X})\nshadow=computeShadowWithCloseESMCube(light{X}.vLightData.xyz,shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.z,light{X}.depthValues);\n#else\nshadow=computeShadowWithCloseESM(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.z,light{X}.shadowsInfo.w);\n#endif\n#elif defined(SHADOWESM{X})\n#if defined(SHADOWCUBE{X})\nshadow=computeShadowWithESMCube(light{X}.vLightData.xyz,shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.z,light{X}.depthValues);\n#else\nshadow=computeShadowWithESM(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.z,light{X}.shadowsInfo.w);\n#endif\n#elif defined(SHADOWPOISSON{X})\n#if defined(SHADOWCUBE{X})\nshadow=computeShadowWithPoissonSamplingCube(light{X}.vLightData.xyz,shadowSampler{X},light{X}.shadowsInfo.y,light{X}.shadowsInfo.x,light{X}.depthValues);\n#else\nshadow=computeShadowWithPoissonSampling(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.y,light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#endif\n#elif defined(SHADOWPCF{X})\n#if defined(SHADOWLOWQUALITY{X})\nshadow=computeShadowWithPCF1(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#elif defined(SHADOWMEDIUMQUALITY{X})\nshadow=computeShadowWithPCF3(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.yz,light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#else\nshadow=computeShadowWithPCF5(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.yz,light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#endif\n#elif defined(SHADOWPCSS{X})\n#if defined(SHADOWLOWQUALITY{X})\nshadow=computeShadowWithPCSS16(vPositionFromLight{X},vDepthMetric{X},depthSampler{X},shadowSampler{X},light{X}.shadowsInfo.y,light{X}.shadowsInfo.z,light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#elif defined(SHADOWMEDIUMQUALITY{X})\nshadow=computeShadowWithPCSS32(vPositionFromLight{X},vDepthMetric{X},depthSampler{X},shadowSampler{X},light{X}.shadowsInfo.y,light{X}.shadowsInfo.z,light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#else\nshadow=computeShadowWithPCSS64(vPositionFromLight{X},vDepthMetric{X},depthSampler{X},shadowSampler{X},light{X}.shadowsInfo.y,light{X}.shadowsInfo.z,light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#endif\n#else\n#if defined(SHADOWCUBE{X})\nshadow=computeShadowCube(light{X}.vLightData.xyz,shadowSampler{X},light{X}.shadowsInfo.x,light{X}.depthValues);\n#else\nshadow=computeShadow(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#endif\n#endif\n#ifdef SHADOWONLY\n#ifndef SHADOWINUSE\n#define SHADOWINUSE\n#endif\nglobalShadow+=shadow;\nshadowLightCount+=1.0;\n#endif\n#else\nshadow=1.;\n#endif\n#ifndef SHADOWONLY\n#ifdef CUSTOMUSERLIGHTING\ndiffuseBase+=computeCustomDiffuseLighting(info,diffuseBase,shadow);\n#ifdef SPECULARTERM\nspecularBase+=computeCustomSpecularLighting(info,specularBase,shadow);\n#endif\n#elif defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})\ndiffuseBase+=lightmapColor*shadow;\n#ifdef SPECULARTERM\n#ifndef LIGHTMAPNOSPECULAR{X}\nspecularBase+=info.specular*shadow*lightmapColor;\n#endif\n#endif\n#else\ndiffuseBase+=info.diffuse*shadow;\n#ifdef SPECULARTERM\nspecularBase+=info.specular*shadow;\n#endif\n#endif\n#endif\n#endif","logDepthFragment":"#ifdef LOGARITHMICDEPTH\ngl_FragDepthEXT=log2(vFragmentDepth)*logarithmicDepthConstant*0.5;\n#endif","fogFragment":"#ifdef FOG\nfloat fog=CalcFogFactor();\ncolor.rgb=fog*color.rgb+(1.0-fog)*vFogColor;\n#endif","pbrVertexDeclaration":"uniform mat4 view;\nuniform mat4 viewProjection;\n#ifdef ALBEDO\nuniform mat4 albedoMatrix;\nuniform vec2 vAlbedoInfos;\n#endif\n#ifdef AMBIENT\nuniform mat4 ambientMatrix;\nuniform vec3 vAmbientInfos;\n#endif\n#ifdef OPACITY\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n#ifdef EMISSIVE\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n#ifdef LIGHTMAP\nuniform vec2 vLightmapInfos;\nuniform mat4 lightmapMatrix;\n#endif\n#ifdef REFLECTIVITY \nuniform vec3 vReflectivityInfos;\nuniform mat4 reflectivityMatrix;\n#endif\n#ifdef MICROSURFACEMAP\nuniform vec2 vMicroSurfaceSamplerInfos;\nuniform mat4 microSurfaceSamplerMatrix;\n#endif\n#ifdef BUMP\nuniform vec3 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif\n\n#ifdef REFRACTION\nuniform vec4 vRefractionInfos;\nuniform mat4 refractionMatrix;\nuniform vec3 vRefractionMicrosurfaceInfos;\n#endif\n\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\n#endif\n","pbrFragmentDeclaration":"uniform vec3 vReflectionColor;\nuniform vec4 vAlbedoColor;\n\nuniform vec4 vLightingIntensity;\nuniform vec4 vReflectivityColor;\nuniform vec3 vEmissiveColor;\n\n#ifdef ALBEDO\nuniform vec2 vAlbedoInfos;\n#endif\n#ifdef AMBIENT\nuniform vec3 vAmbientInfos;\n#endif\n#ifdef BUMP\nuniform vec3 vBumpInfos;\nuniform vec2 vTangentSpaceParams;\n#endif\n#ifdef OPACITY \nuniform vec2 vOpacityInfos;\n#endif\n#ifdef EMISSIVE\nuniform vec2 vEmissiveInfos;\n#endif\n#ifdef LIGHTMAP\nuniform vec2 vLightmapInfos;\n#endif\n#ifdef REFLECTIVITY\nuniform vec3 vReflectivityInfos;\n#endif\n#ifdef MICROSURFACEMAP\nuniform vec2 vMicroSurfaceSamplerInfos;\n#endif\n\n#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)\nuniform mat4 view;\n#endif\n\n#ifdef REFRACTION\nuniform vec4 vRefractionInfos;\nuniform mat4 refractionMatrix;\nuniform vec3 vRefractionMicrosurfaceInfos;\n#endif\n\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\n#if defined(USE_LOCAL_REFLECTIONMAP_CUBIC) && defined(REFLECTIONMAP_CUBIC)\nuniform vec3 vReflectionPosition;\nuniform vec3 vReflectionSize; \n#endif\n#endif","pbrUboDeclaration":"layout(std140,column_major) uniform;\nuniform Material\n{\nuniform vec2 vAlbedoInfos;\nuniform vec3 vAmbientInfos;\nuniform vec2 vOpacityInfos;\nuniform vec2 vEmissiveInfos;\nuniform vec2 vLightmapInfos;\nuniform vec3 vReflectivityInfos;\nuniform vec2 vMicroSurfaceSamplerInfos;\nuniform vec4 vRefractionInfos;\nuniform vec2 vReflectionInfos;\nuniform vec3 vReflectionPosition;\nuniform vec3 vReflectionSize; \nuniform vec3 vBumpInfos;\nuniform mat4 albedoMatrix;\nuniform mat4 ambientMatrix;\nuniform mat4 opacityMatrix;\nuniform mat4 emissiveMatrix;\nuniform mat4 lightmapMatrix;\nuniform mat4 reflectivityMatrix;\nuniform mat4 microSurfaceSamplerMatrix;\nuniform mat4 bumpMatrix;\nuniform vec2 vTangentSpaceParams;\nuniform mat4 refractionMatrix;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionColor;\nuniform vec4 vAlbedoColor;\nuniform vec4 vLightingIntensity;\nuniform vec3 vRefractionMicrosurfaceInfos;\nuniform vec3 vReflectionMicrosurfaceInfos;\nuniform vec4 vReflectivityColor;\nuniform vec3 vEmissiveColor;\nuniform float pointSize;\n};\nuniform Scene {\nmat4 viewProjection;\nmat4 view;\n};","pbrFunctions":"\n#define RECIPROCAL_PI2 0.15915494\n#define FRESNEL_MAXIMUM_ON_ROUGH 0.25\n\nconst float kRougnhessToAlphaScale=0.1;\nconst float kRougnhessToAlphaOffset=0.29248125;\nfloat convertRoughnessToAverageSlope(float roughness)\n{\n\nconst float kMinimumVariance=0.0005;\nfloat alphaG=square(roughness)+kMinimumVariance;\nreturn alphaG;\n}\n\nfloat smithVisibilityG1_TrowbridgeReitzGGX(float dot,float alphaG)\n{\nfloat tanSquared=(1.0-dot*dot)/(dot*dot);\nreturn 2.0/(1.0+sqrt(1.0+alphaG*alphaG*tanSquared));\n}\nfloat smithVisibilityG_TrowbridgeReitzGGX_Walter(float NdotL,float NdotV,float alphaG)\n{\nreturn smithVisibilityG1_TrowbridgeReitzGGX(NdotL,alphaG)*smithVisibilityG1_TrowbridgeReitzGGX(NdotV,alphaG);\n}\n\n\nfloat normalDistributionFunction_TrowbridgeReitzGGX(float NdotH,float alphaG)\n{\n\n\n\nfloat a2=square(alphaG);\nfloat d=NdotH*NdotH*(a2-1.0)+1.0;\nreturn a2/(PI*d*d);\n}\nvec3 fresnelSchlickGGX(float VdotH,vec3 reflectance0,vec3 reflectance90)\n{\nreturn reflectance0+(reflectance90-reflectance0)*pow(clamp(1.0-VdotH,0.,1.),5.0);\n}\nvec3 fresnelSchlickEnvironmentGGX(float VdotN,vec3 reflectance0,vec3 reflectance90,float smoothness)\n{\n\nfloat weight=mix(FRESNEL_MAXIMUM_ON_ROUGH,1.0,smoothness);\nreturn reflectance0+weight*(reflectance90-reflectance0)*pow(clamp(1.0-VdotN,0.,1.),5.0);\n}\n\nvec3 computeSpecularTerm(float NdotH,float NdotL,float NdotV,float VdotH,float roughness,vec3 reflectance0,vec3 reflectance90,float geometricRoughnessFactor)\n{\nroughness=max(roughness,geometricRoughnessFactor);\nfloat alphaG=convertRoughnessToAverageSlope(roughness);\nfloat distribution=normalDistributionFunction_TrowbridgeReitzGGX(NdotH,alphaG);\nfloat visibility=smithVisibilityG_TrowbridgeReitzGGX_Walter(NdotL,NdotV,alphaG);\nvisibility/=(4.0*NdotL*NdotV); \nfloat specTerm=max(0.,visibility*distribution)*NdotL;\nvec3 fresnel=fresnelSchlickGGX(VdotH,reflectance0,reflectance90);\nreturn fresnel*specTerm;\n}\nfloat computeDiffuseTerm(float NdotL,float NdotV,float VdotH,float roughness)\n{\n\n\nfloat diffuseFresnelNV=pow(clamp(1.0-NdotL,0.000001,1.),5.0);\nfloat diffuseFresnelNL=pow(clamp(1.0-NdotV,0.000001,1.),5.0);\nfloat diffuseFresnel90=0.5+2.0*VdotH*VdotH*roughness;\nfloat fresnel =\n(1.0+(diffuseFresnel90-1.0)*diffuseFresnelNL) *\n(1.0+(diffuseFresnel90-1.0)*diffuseFresnelNV);\nreturn fresnel*NdotL/PI;\n}\nfloat adjustRoughnessFromLightProperties(float roughness,float lightRadius,float lightDistance)\n{\n#ifdef USEPHYSICALLIGHTFALLOFF\n\nfloat lightRoughness=lightRadius/lightDistance;\n\nfloat totalRoughness=clamp(lightRoughness+roughness,0.,1.);\nreturn totalRoughness;\n#else\nreturn roughness;\n#endif\n}\nfloat computeDefaultMicroSurface(float microSurface,vec3 reflectivityColor)\n{\nconst float kReflectivityNoAlphaWorkflow_SmoothnessMax=0.95;\nfloat reflectivityLuminance=getLuminance(reflectivityColor);\nfloat reflectivityLuma=sqrt(reflectivityLuminance);\nmicroSurface=reflectivityLuma*kReflectivityNoAlphaWorkflow_SmoothnessMax;\nreturn microSurface;\n}\n\n\nfloat fresnelGrazingReflectance(float reflectance0) {\nfloat reflectance90=clamp(reflectance0*25.0,0.0,1.0);\nreturn reflectance90;\n}\n\n\n#define UNPACK_LOD(x) (1.0-x)*255.0\nfloat getLodFromAlphaG(float cubeMapDimensionPixels,float alphaG,float NdotV) {\nfloat microsurfaceAverageSlope=alphaG;\n\n\n\n\n\n\nmicrosurfaceAverageSlope*=sqrt(abs(NdotV));\nfloat microsurfaceAverageSlopeTexels=microsurfaceAverageSlope*cubeMapDimensionPixels;\nfloat lod=log2(microsurfaceAverageSlopeTexels);\nreturn lod;\n}\nfloat environmentRadianceOcclusion(float ambientOcclusion,float NdotVUnclamped) {\n\n\nfloat temp=NdotVUnclamped+ambientOcclusion;\nreturn clamp(square(temp)-1.0+ambientOcclusion,0.0,1.0);\n}\nfloat environmentHorizonOcclusion(vec3 view,vec3 normal) {\n\nvec3 reflection=reflect(view,normal);\nfloat temp=clamp( 1.0+1.1*dot(reflection,normal),0.0,1.0);\nreturn square(temp);\n}","harmonicsFunctions":"#ifdef USESPHERICALFROMREFLECTIONMAP\nuniform vec3 vSphericalX;\nuniform vec3 vSphericalY;\nuniform vec3 vSphericalZ;\nuniform vec3 vSphericalXX_ZZ;\nuniform vec3 vSphericalYY_ZZ;\nuniform vec3 vSphericalZZ;\nuniform vec3 vSphericalXY;\nuniform vec3 vSphericalYZ;\nuniform vec3 vSphericalZX;\nvec3 quaternionVectorRotation_ScaledSqrtTwo(vec4 Q,vec3 V){\nvec3 T=cross(Q.xyz,V);\nT+=Q.www*V;\nreturn cross(Q.xyz,T)+V;\n}\nvec3 environmentIrradianceJones(vec3 normal)\n{\n\n\n\n\n\n\n\n\n\nfloat Nx=normal.x;\nfloat Ny=normal.y;\nfloat Nz=normal.z;\nvec3 C1=vSphericalZZ.rgb;\nvec3 Cx=vSphericalX.rgb;\nvec3 Cy=vSphericalY.rgb;\nvec3 Cz=vSphericalZ.rgb;\nvec3 Cxx_zz=vSphericalXX_ZZ.rgb;\nvec3 Cyy_zz=vSphericalYY_ZZ.rgb;\nvec3 Cxy=vSphericalXY.rgb;\nvec3 Cyz=vSphericalYZ.rgb;\nvec3 Czx=vSphericalZX.rgb;\nvec3 a1=Cyy_zz*Ny+Cy;\nvec3 a2=Cyz*Nz+a1;\nvec3 b1=Czx*Nz+Cx;\nvec3 b2=Cxy*Ny+b1;\nvec3 b3=Cxx_zz*Nx+b2;\nvec3 t1=Cz*Nz+C1;\nvec3 t2=a2*Ny+t1;\nvec3 t3=b3*Nx+t2;\nreturn t3;\n}\n#endif","pbrLightFunctions":"\nstruct lightingInfo\n{\nvec3 diffuse;\n#ifdef SPECULARTERM\nvec3 specular;\n#endif\n};\nfloat computeDistanceLightFalloff(vec3 lightOffset,float lightDistanceSquared,float range)\n{ \n#ifdef USEPHYSICALLIGHTFALLOFF\nfloat lightDistanceFalloff=1.0/((lightDistanceSquared+0.001));\n#else\nfloat lightDistanceFalloff=max(0.,1.0-length(lightOffset)/range);\n#endif\nreturn lightDistanceFalloff;\n}\nfloat computeDirectionalLightFalloff(vec3 lightDirection,vec3 directionToLightCenterW,float cosHalfAngle,float exponent)\n{\nfloat falloff=0.0;\n#ifdef USEPHYSICALLIGHTFALLOFF\nconst float kMinusLog2ConeAngleIntensityRatio=6.64385618977; \n\n\n\n\n\nfloat concentrationKappa=kMinusLog2ConeAngleIntensityRatio/(1.0-cosHalfAngle);\n\n\nvec4 lightDirectionSpreadSG=vec4(-lightDirection*concentrationKappa,-concentrationKappa);\nfalloff=exp2(dot(vec4(directionToLightCenterW,1.0),lightDirectionSpreadSG));\n#else\nfloat cosAngle=max(0.000000000000001,dot(-lightDirection,directionToLightCenterW));\nif (cosAngle>=cosHalfAngle)\n{\nfalloff=max(0.,pow(cosAngle,exponent));\n}\n#endif\nreturn falloff;\n}\nlightingInfo computeLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec3 diffuseColor,vec3 specularColor,float rangeRadius,float roughness,float NdotV,vec3 reflectance0,vec3 reflectance90,float geometricRoughnessFactor,out float NdotL) {\nlightingInfo result;\nvec3 lightDirection;\nfloat attenuation=1.0;\nfloat lightDistance;\n\nif (lightData.w == 0.)\n{\nvec3 lightOffset=lightData.xyz-vPositionW;\nfloat lightDistanceSquared=dot(lightOffset,lightOffset);\nattenuation=computeDistanceLightFalloff(lightOffset,lightDistanceSquared,rangeRadius);\nlightDistance=sqrt(lightDistanceSquared);\nlightDirection=normalize(lightOffset);\n}\n\nelse\n{\nlightDistance=length(-lightData.xyz);\nlightDirection=normalize(-lightData.xyz);\n}\n\nroughness=adjustRoughnessFromLightProperties(roughness,rangeRadius,lightDistance);\n\nvec3 H=normalize(viewDirectionW+lightDirection);\nNdotL=clamp(dot(vNormal,lightDirection),0.00000000001,1.0);\nfloat VdotH=clamp(dot(viewDirectionW,H),0.0,1.0);\nfloat diffuseTerm=computeDiffuseTerm(NdotL,NdotV,VdotH,roughness);\nresult.diffuse=diffuseTerm*diffuseColor*attenuation;\n#ifdef SPECULARTERM\n\nfloat NdotH=clamp(dot(vNormal,H),0.000000000001,1.0);\nvec3 specTerm=computeSpecularTerm(NdotH,NdotL,NdotV,VdotH,roughness,reflectance0,reflectance90,geometricRoughnessFactor);\nresult.specular=specTerm*diffuseColor*attenuation;\n#endif\nreturn result;\n}\nlightingInfo computeSpotLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec4 lightDirection,vec3 diffuseColor,vec3 specularColor,float rangeRadius,float roughness,float NdotV,vec3 reflectance0,vec3 reflectance90,float geometricRoughnessFactor,out float NdotL) {\nlightingInfo result;\nvec3 lightOffset=lightData.xyz-vPositionW;\nvec3 directionToLightCenterW=normalize(lightOffset);\n\nfloat lightDistanceSquared=dot(lightOffset,lightOffset);\nfloat attenuation=computeDistanceLightFalloff(lightOffset,lightDistanceSquared,rangeRadius);\n\nfloat directionalAttenuation=computeDirectionalLightFalloff(lightDirection.xyz,directionToLightCenterW,lightDirection.w,lightData.w);\nattenuation*=directionalAttenuation;\n\nfloat lightDistance=sqrt(lightDistanceSquared);\nroughness=adjustRoughnessFromLightProperties(roughness,rangeRadius,lightDistance);\n\nvec3 H=normalize(viewDirectionW+directionToLightCenterW);\nNdotL=clamp(dot(vNormal,directionToLightCenterW),0.000000000001,1.0);\nfloat VdotH=clamp(dot(viewDirectionW,H),0.0,1.0);\nfloat diffuseTerm=computeDiffuseTerm(NdotL,NdotV,VdotH,roughness);\nresult.diffuse=diffuseTerm*diffuseColor*attenuation;\n#ifdef SPECULARTERM\n\nfloat NdotH=clamp(dot(vNormal,H),0.000000000001,1.0);\nvec3 specTerm=computeSpecularTerm(NdotH,NdotL,NdotV,VdotH,roughness,reflectance0,reflectance90,geometricRoughnessFactor);\nresult.specular=specTerm*diffuseColor*attenuation;\n#endif\nreturn result;\n}\nlightingInfo computeHemisphericLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec3 diffuseColor,vec3 specularColor,vec3 groundColor,float roughness,float NdotV,vec3 reflectance0,vec3 reflectance90,float geometricRoughnessFactor,out float NdotL) {\nlightingInfo result;\n\n\n\nNdotL=dot(vNormal,lightData.xyz)*0.5+0.5;\nresult.diffuse=mix(groundColor,diffuseColor,NdotL);\n#ifdef SPECULARTERM\n\nvec3 lightVectorW=normalize(lightData.xyz);\nvec3 H=normalize(viewDirectionW+lightVectorW);\nfloat NdotH=clamp(dot(vNormal,H),0.000000000001,1.0);\nNdotL=clamp(NdotL,0.000000000001,1.0);\nfloat VdotH=clamp(dot(viewDirectionW,H),0.0,1.0);\nvec3 specTerm=computeSpecularTerm(NdotH,NdotL,NdotV,VdotH,roughness,reflectance0,reflectance90,geometricRoughnessFactor);\nresult.specular=specTerm*diffuseColor;\n#endif\nreturn result;\n}\nvec3 computeProjectionTextureDiffuseLighting(sampler2D projectionLightSampler,mat4 textureProjectionMatrix){\nvec4 strq=textureProjectionMatrix*vec4(vPositionW,1.0);\nstrq/=strq.w;\nvec3 textureColor=texture2D(projectionLightSampler,strq.xy).rgb;\nreturn toLinearSpace(textureColor);\n}","kernelBlurFragment":"#ifdef DOF\nfactor=sampleCoC(sampleCoord{X}); \ncomputedWeight=KERNEL_WEIGHT{X}*factor;\nsumOfWeights+=computedWeight;\n#else\ncomputedWeight=KERNEL_WEIGHT{X};\n#endif\n#ifdef PACKEDFLOAT\nblend+=unpack(texture2D(textureSampler,sampleCoord{X}))*computedWeight;\n#else\nblend+=texture2D(textureSampler,sampleCoord{X})*computedWeight;\n#endif","kernelBlurFragment2":"#ifdef DOF\nfactor=sampleCoC(sampleCenter+delta*KERNEL_DEP_OFFSET{X});\ncomputedWeight=KERNEL_DEP_WEIGHT{X}*factor;\nsumOfWeights+=computedWeight;\n#else\ncomputedWeight=KERNEL_DEP_WEIGHT{X};\n#endif\n#ifdef PACKEDFLOAT\nblend+=unpack(texture2D(textureSampler,sampleCenter+delta*KERNEL_DEP_OFFSET{X}))*computedWeight;\n#else\nblend+=texture2D(textureSampler,sampleCenter+delta*KERNEL_DEP_OFFSET{X})*computedWeight;\n#endif","kernelBlurVaryingDeclaration":"varying vec2 sampleCoord{X};","kernelBlurVertex":"sampleCoord{X}=sampleCenter+delta*KERNEL_OFFSET{X};","mrtFragmentDeclaration":"#if __VERSION__>=200\nlayout(location=0) out vec4 glFragData[{X}];\n#endif\n","bones300Declaration":"#if NUM_BONE_INFLUENCERS>0\nuniform mat4 mBones[BonesPerMesh];\nin vec4 matricesIndices;\nin vec4 matricesWeights;\n#if NUM_BONE_INFLUENCERS>4\nin vec4 matricesIndicesExtra;\nin vec4 matricesWeightsExtra;\n#endif\n#endif","instances300Declaration":"#ifdef INSTANCES\nin vec4 world0;\nin vec4 world1;\nin vec4 world2;\nin vec4 world3;\n#else\nuniform mat4 world;\n#endif","backgroundVertexDeclaration":"uniform mat4 view;\nuniform mat4 viewProjection;\nuniform float shadowLevel;\n#ifdef DIFFUSE\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\nuniform float fFovMultiplier;\n#endif\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif","backgroundFragmentDeclaration":" uniform vec4 vPrimaryColor;\n#ifdef USEHIGHLIGHTANDSHADOWCOLORS\nuniform vec4 vPrimaryColorShadow;\n#endif\nuniform float shadowLevel;\nuniform float alpha;\n#ifdef DIFFUSE\nuniform vec2 vDiffuseInfos;\n#endif\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\n#endif\n#if defined(REFLECTIONFRESNEL) || defined(OPACITYFRESNEL)\nuniform vec3 vBackgroundCenter;\n#endif\n#ifdef REFLECTIONFRESNEL\nuniform vec4 vReflectionControl;\n#endif\n#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)\nuniform mat4 view;\n#endif","backgroundUboDeclaration":"layout(std140,column_major) uniform;\nuniform Material\n{\nuniform vec4 vPrimaryColor;\nuniform vec4 vPrimaryColorShadow;\nuniform vec2 vDiffuseInfos;\nuniform vec2 vReflectionInfos;\nuniform mat4 diffuseMatrix;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\nuniform float fFovMultiplier;\nuniform float pointSize;\nuniform float shadowLevel;\nuniform float alpha;\n#if defined(REFLECTIONFRESNEL) || defined(OPACITYFRESNEL)\nuniform vec3 vBackgroundCenter;\n#endif\n#ifdef REFLECTIONFRESNEL\nuniform vec4 vReflectionControl;\n#endif\n};\nuniform Scene {\nmat4 viewProjection;\nmat4 view;\n};"};